[Solved] Need help converting MM4 "Weighted Shuffle" script

To discuss development of addons / skins / customization of MediaMonkey.

Moderators: jiri, drakinite, Addon Administrators

dksmedia
Posts: 3
Joined: Sat Mar 11, 2023 12:10 pm

[Solved] Need help converting MM4 "Weighted Shuffle" script

Post by dksmedia »

I am a longtime MediaMonkey user who can sometimes manipulate a script to suit my purposes but by no definition would I be considered a developer. I would like to update from MM4 to MM5 but have not done so because I use a handful of scripts to create weighted shuffle playlists that I am unable to convert.

The existing scripts are very basic, probably poorly written, and fairly clumsy to use but they to serve my purpose. They simply create a subnode to the Now Playing node that copies each item in the Now Playing list a certain number of times based on each items rating. To use them I have to first play the items that I want weighted, go to the subnode created by the script, copy everything there into a new manual playlist, then finally shuffle that list manually. As I said, it is not an elegant process but it works.

I did try running them through the VBS to JS converter but they do not function. I suspect the underlying code is simply not compatible with the MM5 node structure but honestly I am not even sure I am even installing them correctly. I just saved the converted output as a json file and place it into the Scripts folder.

If somebody could help me replicate this functionality in MM5 I would be eternally grateful. Beyond that, if you are so inclined, what would be even better is if instead of using the Now Playing node, you could show me how to specify an existing playlist as the basis for the new playlist. Better still would be the ability to automatically write the results to a new playlist and shuffle it automatically. Of course any help would be appreciated. As long as I am able to replicate my existing playlists I will be happy, even if I still have to perform a few steps manually.

Here is an example of my existing MM4 scripts:

Code: Select all

Sub OnStartup
  Dim Tree
  Set Tree = SDB.MainTree
 
  Dim Node
  Set Node = Tree.CreateNode
  Node.Caption = "Weighted 1.5 Half Step"
  Node.IconIndex = 40
  Node.UseScript = Script.ScriptPath
  Node.OnFillTracksFunct = "FillNPTracks"
 
  Tree.AddNode Tree.Node_NowPlaying, Node, 3   ' Add as the last child
End Sub
 
Sub FillNPTracks( Node)  

    Dim i
    i=0
    Dim List, Trcks
    Set List = SDB.Player.CurrentPlaylist
    Set Trcks = SDB.MainTracksWindow
   
    While i<List.Count And Not Script.Terminate	
    
      ' 1.5 Stars
      If (List.Item(i).Rating > 26) Then
        Trcks.AddTrack List.Item(i)
      End If
     
      ' 2.0 Stars
      If (List.Item(i).Rating > 36) Then
        Trcks.AddTrack List.Item(i)
      End If
     
      ' 2.5 Stars
      If (List.Item(i).Rating > 46) Then
        Trcks.AddTrack List.Item(i)
      End If
      
      ' 3 Stars
      If (List.Item(i).Rating > 56) Then
        Trcks.AddTrack List.Item(i)
      End If
      
      ' 3.5 Stars   
      If (List.Item(i).Rating > 66) Then
        Trcks.AddTrack List.Item(i)
      End If
      
      ' 4 Stars
      If (List.Item(i).Rating > 76) Then
        Trcks.AddTrack List.Item(i)
      End If
      
      ' 4.5 Stars
      If (List.Item(i).Rating > 86) Then
        Trcks.AddTrack List.Item(i)
      End If
      
      ' 5 Stars
      If (List.Item(i).Rating > 96) Then
        Trcks.AddTrack List.Item(i)
      End If
      
      i=i+1
      
    WEnd
    
  Trcks.FinishAdding
End Sub
EDIT: So I have made some very minor progress in that I was able to modify the "Randomise Playlist" add-on to add a "Weighted Shuffle" button to the playlist view. Currently it simply replicates the "Randomise Playlist" functionality but I believe it should work if I am able to translate the vbs code above to javascript. Below is my current actions_add.js file which is basically just a modified version of that found in the Randomise Playlist" addon. I just need to know what I should declare for the variables and how to add the items to the playlist. Again, any help is appreciated.

Code: Select all

actions.shuffleWeighted_15_half = {
	title: function () {
        	return _('Weighted Shuffle 1.5 Half Step')
    	},
    	hotkeyAble: false,
    	icon: 'shuffle',
    	visible: function () {
        	if (!window.uitools.getCanEdit())
        		return false;
        	else {
        		// boundObject is for the playlist 3dots menu, otherwise the action is fired from the viewhandler
	   	 	var pl = resolveToValue(this.boundObject);
	    		if (pl)
            			return (pl.parent != undefined && !pl.isAutoPlaylist); // to exclude root playlists node and auto-playlists
	    		else 
				return true;
        	}
    	},
    	execute: function (playlist) {
		if (!playlist) {
			playlist = resolveToValue(this.boundObject);
		}
		var i=0;
		var list;
        	var tracks = playlist.getTracklist();
        	tracks.whenLoaded().then(() => {
			tracks.randomize();
			playlist.reorderAsync(tracks);
       		 });
    	}
};
EDIT2: I got it to work by modifying the the code from removePlaylistsDupsByTitle and Randomise Playlist. It copies the contents of one playlist into a new playlist a certain number of times based upon each items rating. I was not able to get it to shuffle automatically but the Randomise Playlist add on makes that easy enough. Below is the code for anybody interested.

EDIT 3: For some reason this stopped working. I made some adjustments and corrected the code below. The forum url filter forced me to add spaces before the "." in "newplaylist .name" and "playlist .name" in actions_add.js so remember to remove them before saving your scripts.

info.json

Code: Select all

{
    "title": "Weighted Shuffle 1.5 Half Step",
    "id": "shuffleWeighted_15_half",
    "description": "Weighted Shuffle 1.5 Half Step",
    "version": "1.0.2",
    "type": "general",
    "author": "dksmedia"
}
actions_add.js

Code: Select all

actions.shuffleWeighted_15_half = {
    title: function () {
        return _('Weighted Shuffle 1.5 Half Step')
    },
	hotkeyAble: false,
    icon: 'shuffle',
    visible: function () {
        if (!window.uitools.getCanEdit())
            return false;
        else {
            // boundObject is for the playlist 3dots menu, otherwise the action is fired from the viewhandler
			var pl = resolveToValue(this.boundObject);
			if (pl)
            	return (pl.parent != undefined && !pl.isAutoPlaylist); // to exclude root playlists node and auto-playlists
			else 
				return true;
        }
    },
    execute: function (playlist) {
		if (!playlist) {
			playlist = resolveToValue(this.boundObject);
		}
        var tracks = playlist.getTracklist();
        var newList = app.utils.createTracklist();
        tracks.whenLoaded().then(async () => {
            listForEach(tracks, (track, idx) => {
				if (track.rating > 26) {
					newList.add(track);
				}
				if (track.rating > 36) {
					newList.add(track);
				}
				if (track.rating > 46) {
					newList.add(track);
				}
				if (track.rating > 56) {
					newList.add(track);
				}
				if (track.rating > 66) {
					newList.add(track);
				}
				if (track.rating > 76) {
					newList.add(track);
				}
				if (track.rating > 86) {
					newList.add(track);
				}
				if (track.rating > 96) {
					newList.add(track);
				}
            });
            var newplaylist = app.playlists.root.newPlaylist();
            newplaylist .name = '_' + playlist .name + '_weighted_1.5_half';
            await newplaylist.commitAsync();
            newplaylist.addTracksAsync(newList);
        });
    }
};
viewHandlers_add.js

Code: Select all

var playlistPrototype = nodeHandlersClasses.PlaylistBase.prototype;

playlistPrototype.menuAddons = playlistPrototype.menuAddons || [];

playlistPrototype.menuAddons.push(function(node) {
	return {
		action: {
			title: actions.shuffleWeighted_15_half.title,
			hotkeyAble: actions.shuffleWeighted_15_half.hotkeyAble,
			icon: actions.shuffleWeighted_15_half.icon,
			visible: function () {
				return (node.dataSource && !node.dataSource.isAutoPlaylist);
			},
			execute: function () {
				actions.shuffleWeighted_15_half.execute(node.dataSource);
			}
		},
		order: 70,
		grouporder: 10
	}
});
playlistHeader_add.js:

Code: Select all

PlaylistHeader.prototype.override({
    _initButtons: function ($super) {
        $super();
        var _this = this;
        this.btnMenu.controlClass.menuArray.push({
            action: bindAction(window.actions.shuffleWeighted_15_half, () => {
                return _this._playlist;
            }),
            order: 25,
            grouporder: 10
        });
    }
});