View Issue Details

IDProjectCategoryView StatusLast Update
0017790MMW 5Playbackpublic2021-05-12 22:04
Reporterdrakinite Assigned To 
PriorityurgentSeverityminorReproducibilitysometimes
Status closedResolutionfixed 
Product Version5.0 
Target Version5.0.1Fixed in Version5.0.1 
Summary0017790: Inconsistent behavior of player.clearPlaylist()
DescriptionThe method clearPlaylist() is a synchronous method, but it seems to behave asynchronously.

Take the following code:
app.playlists.getByTitleAsync('(Playlist Name)').then(async (playlist) => {
    if (playlist) {
    await player.stopAsync();
    let tracklist = playlist.getTracklist();
    player.clearPlaylist(true);
    await player.addTracksAsync(tracklist);
    let idx = Math.floor(Math.random() * player.getSongList().count);
    console.log(player.getSongList().count);
    await player.setPlaylistPosAsync(idx);
    player.playAsync();
    }
});
Sometimes it runs correctly, but it is inconsistent. Some of the time, the playlist just stays empty. I suspect that the player isn't finished with clearing the current playlist before the next line repopulates it.

The following code, with a 10 ms timer after clearPlaylist, works 100% of the time for me:
app.playlists.getByTitleAsync('(Playlist Name)').then(async (playlist) => {
    if (playlist) {
        await player.stopAsync();
        let tracklist = playlist.getTracklist();
        console.log(tracklist)
        player.clearPlaylist(true);
        setTimeout(async () => {
            await player.addTracksAsync(tracklist);
            let idx = Math.floor(Math.random() * player.getSongList().count);
            console.log(tracklist.count)
            console.log(player.getSongList().count);
            await player.setPlaylistPosAsync(idx);
            player.playAsync();
        }, 10);
    }
});

If my suspicion is correct, the solution could be to make the clearPlaylist() method into clearPlaylistAsync() and return a promise.
TagsNo tags attached.
Fixed in build2400

Activities

Ludek

2021-04-28 11:12

developer   ~0062946

Last edited: 2021-04-28 11:20

By a quick review I don't see anything in app.player.clearPlaylist() being asynchronous. Michal, please double-check this.

BTW: There is already withClear parametr that can be used in app.player.addTracksAsync , see: https://www.mediamonkey.com/webhelp/MM5Preview/classes/Player.html#method_addTracksAsync

michal

2021-04-28 12:09

developer   ~0062947

The original issue is caused by the error in script code - playlist.getTracklist() returns tracklist object, but you need to wait for whenLoaded promise to be sure, the list is already fully loaded before next use.
And as Ludek said, better, in this case, is using withClear parameter in addTracksAsync instead.

Anyway clearPlaylist should by asynchronous because it uses write lock for the list, changed to clearPlaylistAsync in build 2400.

drakinite

2021-05-12 22:04

developer   ~0063162

Verified the change from clearPlaylist() to clearPlaylistAsync() in 2404. Closing.

Thanks for the notes regarding withClear and the whenLoaded promise. I wasn't aware of either of those (and the latter helps clarify my past confusion on why tracklists seemed inconsistent when I tried to access their properties immediately). After making the suggested changes to the script, it is now consistent:

app.playlists.getByTitleAsync('foofoo').then(async (playlist) => {
    if (playlist) {
      await player.stopAsync();
      let tracklist = playlist.getTracklist();
      await tracklist.whenLoaded();
      await player.addTracksAsync(tracklist, {withClear: true});
      let idx = Math.floor(Math.random() * player.getSongList().count);
      console.log(player.getSongList().count);
      await player.setPlaylistPosAsync(idx);
      player.playAsync();
    }
});