Author Topic: MusicBee API  (Read 285419 times)

Kafka

  • Newbie
  • *
  • Posts: 6
Hi Steven.
I've trouble querying and getting files in the library,is it right to get by using Library_QueryFilesEx*?And what the format of parameter "query"?

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34312
its the same xml format used to store auto-playlists, so to make it easy create an auto-playlist in MB with the appropriate query and use the xml from the saved file as the basis to build queries

Kafka

  • Newbie
  • *
  • Posts: 6
Unfortunately,I dont konw why it gets all the files in the library but not the one I want.Here is the code:
Code
            StringBuilder query = new StringBuilder();
            query.Append("<SmartPlaylist");
            query.Append("<Source Type=\"1\">");
            query.Append(" <Description />");
            query.Append(" <Conditions CombineMethod=\"All\">");
            query.Append(" <Condition Field=\"None\" Comparison=\"Is \" Value=\"Someone Like You\" />");
            query.Append(" </Conditions>");
            query.Append("</Source>");
            query.Append("</SmartPlaylist>");
            pApi.Library_QueryFilesEx(query.ToString().Trim() + "", out var results);

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34312
<SmartPlaylist is missing the closing bracket

Kafka

  • Newbie
  • *
  • Posts: 6

Kafka

  • Newbie
  • *
  • Posts: 6
Library_QueryFilesEx* can't get any files with the query below
Code
string query = " <SmartPlaylist>\n"
            +"<Source Type=\"1\">\n"
            + "<Conditions CombineMethod=\"All\"> \n"
            + "<Condition Field=\"Title\" Comparison=\"Is\" Value=\"Mysteria Tale\" />\n"
            + "</Conditions>\n"
            + "</Source>\n"
            + "</SmartPlaylist>\n";
However,it can get all files in the library with the query below
Code
StringBuilder query = new StringBuilder();
            query.Append("<SmartPlaylist>\n");
            query.Append("<Source Type=\"1\">\n");
            query.Append("<Conditions CombineMethod=\"All\">\n");
            query.Append("<Condition Field=\"Title\" Comparison=\"Is \" Value=\"Mysteria Tale\" />\n");
            query.Append("</Conditions>\n");
            query.Append("</Source>\n");
            query.Append("</SmartPlaylist>\n");
What's more ,it alse gets all files in the library  with such query
Code
StringBuilder query = new StringBuilder();
            query.Append("<SmartPlaylist>\n");
I am puzzled.

dandepeched

  • Jr. Member
  • **
  • Posts: 43
I am puzzled.

Hi Kafka! Maybe I can help you.
To query all files from library you can do the following:
Code
string[] songsList = null;
_api.Library_QueryFilesEx(null, ref songsList);
To build a query you can use "Library_QueryFiles" method:
Code
string searchText= "SomeTitleToSearch"
_api.Library_QueryFiles(XmlFilter(new[] {"Title"}, searchText, false);
Here is the XmlFilter implementation, it may not cover all the cases, but will help you to get the idea:
Code
       private static string XmlFilter(string[] tags, string query, bool isStrict,
            SearchSource source = SearchSource.None)
        {
            short src;
            if (source != SearchSource.None)
            {
                src = (short) source;
            }
            else
            {
                var userDefaults = UserSettings.Instance.Source != SearchSource.None;
                src = (short)
                (userDefaults
                    ? UserSettings.Instance.Source
                    : SearchSource.Library);
            }


            var filter = new XElement("Source",
                new XAttribute("Type", src));

            var conditions = new XElement("Conditions",
                new XAttribute("CombineMethod", "Any"));
            foreach (var tag in tags)
            {
                var condition = new XElement("Condition",
                    new XAttribute("Field", tag),
                    new XAttribute("Comparison", isStrict ? "Is" : "Contains"),
                    new XAttribute("Value", query));
                conditions.Add(condition);
            }
            filter.Add(conditions);

            return filter.ToString();
        }

dandepeched

  • Jr. Member
  • **
  • Posts: 43
Hi Steven, I think I have found 1 more issue in the API.
It appears for the Upcoming Tracks list when using _api.NowPlayingList_QueueFilesNext(songsArray); and then _api.NowPlayingList_QueryFiles(null); while Shuffle is On.

Steps to reproduce:
1) Play some playlist with Shuffle ON.
2) Call _api.NowPlayingList_QueryFiles(null); and go though list with _api.NowPlayingList_GetNextIndex(offset); to receive Upcoming Tracks list
3) Received list is identical to the one displayed in MusicBee player
4) Call _api.NowPlayingList_QueueFilesNext(songsArray); to queue some file.
5) Observe that Upcoming Tracks list is updated properly in MusicBee player
6) Use API from step 2 to receive Upcoming Tracks list
7) Received list is NOT identical to the one displayed in the player - currently playing track is displayed as "queued" instead of selected track
8 ) Repeat steps 3-6 for another track
9) Received list is NOT identical to the one displayed in the player - queued track from step 4 is now displayed in proper position, but currently playing track is displayed as "queued" instead of recently queued track from step 8
10) Press Next and use API from step 2 to receive Upcoming Tracks list
11) Proper track from step 4 is playing now
12) Received list is NOT identical to the one displayed in the player - currently playing track is displayed as "queued" instead of selected track from step 8

Here is the code I use to get Upcoming Tracks list:
Code
public void RequestNowPlayingListOrdered(string clientId, int offset = 0, int limit = 100)
        {
            _api.NowPlayingList_QueryFiles(null);

            var tracks = new List<NowPlaying>();
            var position = 1;
            var itemIndex = _api.NowPlayingList_GetCurrentIndex();
            while (position <= limit)
            {
                var trackPath = _api.NowPlayingList_GetListFileUrl(itemIndex);

                var track = getFileMetadata(trackPath, itemIndex);

                tracks.Add(track);
                itemIndex = _api.NowPlayingList_GetNextIndex(position);
                position++;
            }

            sendDataToClient(clientId, tracks);
        }

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34312
Are you still trying to change the play order of existing files for a shuffled playlist?
You wont be able to do it until i add API support for that.
NowPlayingList_QueueFilesNext() will add the files to the now playing list and queue them next - the equivalent of right clicking in the main panel/ Play Next.

dandepeched

  • Jr. Member
  • **
  • Posts: 43
Are you still trying to change the play order of existing files for a shuffled playlist?
You wont be able to do it until i add API support for that.
NowPlayingList_QueueFilesNext() will add the files to the now playing list and queue them next - the equivalent of right clicking in the main panel/ Play Next.

I still do ;D  But this case is different because it works properly for MusicBee player, so behavior is inconsistent between player and API.
NowPlayingList_QueueFilesNext() adds file in the next position for Upcoming Tracks list - that's what I observe in MusicBee.

Also for the new API in v3.5, it would be cool to have all the NowPlayingList actions to be mirrored with the UpcomingTracksList actions.
Last Edit: March 21, 2021, 01:44:15 PM by dandepeched

derTyp

  • Jr. Member
  • **
  • Posts: 71
Hi,

I just found out that some Metadata fields seem to be missing from the current API version (C#) e.g. the "Year(yyyy)" tag and virtual tags 25+. Would be nice if the API could be updated so all fields are available, I guess its just the "MetaDataType" enum that is missing some members.


Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34312
I will provide an updated API interface file at a later date but here is what you need
Code
        public enum MetaDataType
        {
            TrackTitle = 65,
            Album = 30,
AlbumUniqueId = 108,
            AlbumArtist = 31,        // displayed album artist
            AlbumArtistRaw = 34,     // stored album artist
            Artist = 32,             // displayed artist
            MultiArtist = 33,        // individual artists, separated by a null char
PrimaryArtist = 19,      // first artist from multi-artist tagged file, otherwise displayed artist
            Artists = 144,
            ArtistsWithArtistRole = 145,
            ArtistsWithPerformerRole = 146,
            ArtistsWithGuestRole = 147,
            ArtistsWithRemixerRole = 148,
            Artwork = 40,
            BeatsPerMin = 41,
            Composer = 43,           // displayed composer
            MultiComposer = 89,      // individual composers, separated by a null char
            Comment = 44,
            Conductor = 45,
            Custom1 = 46,
            Custom2 = 47,
            Custom3 = 48,
            Custom4 = 49,
            Custom5 = 50,
            Custom6 = 96,
            Custom7 = 97,
            Custom8 = 98,
            Custom9 = 99,
            Custom10 = 128,
            Custom11 = 129,
            Custom12 = 130,
            Custom13 = 131,
            Custom14 = 132,
            Custom15 = 133,
            Custom16 = 134,
Decade = 105,
            DiscNo = 52,
            DiscCount = 54,
            Encoder = 55,
            Genre = 59,
            Genres = 143,
            GenreCategory = 60,
            Grouping = 61,
            Keywords = 84,
            HasLyrics = 63,
            Lyricist = 62,
            Lyrics = 114,
            Mood = 64,
            Occasion = 66,
            Origin = 67,
            Publisher = 73,
            Quality = 74,
            Rating = 75,
            RatingLove = 76,
            RatingAlbum = 104,
            Tempo = 85,
            TrackNo = 86,
            TrackCount = 87,
            Virtual1 = 109,
            Virtual2 = 110,
            Virtual3 = 111,
            Virtual4 = 112,
            Virtual5 = 113,
            Virtual6 = 122,
            Virtual7 = 123,
            Virtual8 = 124,
            Virtual9 = 125,
            Virtual10 = 135,
            Virtual11 = 136,
            Virtual12 = 137,
            Virtual13 = 138,
            Virtual14 = 139,
            Virtual15 = 140,
            Virtual16 = 141,
            Virtual17 = 149,
            Virtual18 = 150,
            Virtual19 = 151,
            Virtual20 = 152,
            Virtual21 = 153,
            Virtual22 = 154,
            Virtual23 = 155,
            Virtual24 = 156,
            Virtual25 = 157,
Virtual26 = 185,
Virtual27 = 186,
Virtual28 = 187,
Virtual29 = 188,
Virtual30 = 189,
Virtual31 = 190,
Virtual32 = 191,
            Year = 88,
YearOnly = 35,
            SortTitle = 163,
            SortAlbum = 164,
            SortAlbumArtist = 165,
            SortArtist = 166,
            SortComposer = 167,
            Work = 168,
            MovementName = 169,
            MovementNo = 170,
            MovementCount = 171,
            ShowMovement = 172,
            Language = 173,
            OriginalArtist = 174,
            OriginalYear = 175,
            OriginalTitle = 177,
            InstrumentsPerformers = 182
        }


derTyp

  • Jr. Member
  • **
  • Posts: 71

jkfranks9

  • Newbie
  • *
  • Posts: 2
Steven, I've been able to successfully retrieve music tracks and playlists, but I don't see any way to get music video files using the API. Is this something that exists but is not obvious? If it doesn't exist, any plans to add video retrieval?

Many thanks for providing this API!

boroda

  • Sr. Member
  • ****
  • Posts: 4595
Steven, could you implement API function MbApiInterface.MB_UnRegisterCommand("Hotkey description ")? Or even better, MbApiInterface.MB_UnRegisterCommands("Hotkey descriptions"), where "Hotkey descriptions" can contain "*" wildchar? something like "Tagging Tools: *". there is no need to support "?" wildchar, and even support for "*" is required only at the end of hotkeys description string (at least personally for me).