Skip to content

Commit

Permalink
- Selection manipulation\Shuffle: new sorting bias settings. Key (sor…
Browse files Browse the repository at this point in the history
…ted from 12A to 1B), Key 6A centered (starting from 6A). Using these is like merging Harmonic Mix (consecutive tracks should have similar keys) and Smart Shuffle.

- Selection manipulation\Group: new tool to group tracks by TF without respecting the original sorting. It may be used to listen to all tracks of a random album played in a shuffled order, then all of another album (chosen randomly), ...
- Selection manipulation\Shuffle: sorting bias setting not being applied on selection manipulation tool (thus always using 'random').
  • Loading branch information
regorxxx committed Jul 21, 2023
1 parent fc45796 commit 3dd75ba
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 8 deletions.
4 changes: 3 additions & 1 deletion main/playlist_tools/playlist_tools_menu_pools.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';
//09/06/23
//04/07/23

// Pools
{
Expand Down Expand Up @@ -654,6 +654,8 @@
{key: 'Rating', flags: MF_STRING},
{key: 'Popularity', flags: utils.GetPackageInfo('{F5E9D9EB-42AD-4A47-B8EE-C9877A8E7851}') ? MF_STRING : MF_GRAYED, req: 'Find & Play'},
{key: 'Last played', flags: isPlayCount ? MF_STRING : MF_GRAYED, req: 'foo_playcount'},
{key: 'Key', flags: MF_STRING},
{key: 'Key 6A centered', flags: MF_STRING},
];
menu.newEntry({menuName: subMenuNameSecond, entryText: 'Prioritize tracks by:', flags: MF_GRAYED});
menu.newEntry({menuName: subMenuNameSecond, entryText: 'sep'});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';
//27/03/23
//04/07/23

// Similar by...Graph\Dyngenre\Weight
{
Expand Down Expand Up @@ -371,6 +371,8 @@
{key: 'Rating', flags: MF_STRING},
{key: 'Popularity', flags: utils.GetPackageInfo('{F5E9D9EB-42AD-4A47-B8EE-C9877A8E7851}') ? MF_STRING : MF_GRAYED, req: 'Find & Play'},
{key: 'Last played', flags: isPlayCount ? MF_STRING : MF_GRAYED, req: 'foo_playcount'},
{key: 'Key', flags: MF_STRING},
{key: 'Key 6A centered', flags: MF_STRING},
];
menu.newEntry({menuName: subMenuNameSecond, entryText: 'Prioritize tracks by:', flags: MF_GRAYED});
menu.newEntry({menuName: subMenuNameSecond, entryText: 'sep'});
Expand Down
106 changes: 103 additions & 3 deletions main/playlist_tools/playlist_tools_menu_sel_manipulation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';
//13/06/23
//21/07/23

// Selection manipulation...
{
Expand Down Expand Up @@ -467,7 +467,12 @@
} else {entryNames.add(shuffleName);}
// Entries
menu.newEntry({menuName: subMenuName, entryText: shuffleName, func: () => {
shuffleByTags({...shuffleObj.args, bDebug: defaultArgs.bDebug});
shuffleByTags({
...shuffleObj.args,
bAdvancedShuffle: menu_properties.bSmartShuffleAdvc[1],
sortBias: menu_properties.smartShuffleSortBias[1],
bDebug: defaultArgs.bDebug
});
}, flags: multipleSelectedFlagsReorder});
}
});
Expand Down Expand Up @@ -501,7 +506,6 @@
});
}
}});
menu.newEntry({menuName, entryText: 'sep'});
if (!menusEnabled.hasOwnProperty(configMenu) || menusEnabled[configMenu] === true) {
const subMenuName = 'Smart shuffle';
if (!menu.hasMenu(subMenuName, configMenu)) {
Expand Down Expand Up @@ -533,6 +537,8 @@
{key: 'Rating', flags: MF_STRING},
{key: 'Popularity', flags: utils.GetPackageInfo('{F5E9D9EB-42AD-4A47-B8EE-C9877A8E7851}') ? MF_STRING : MF_GRAYED, req: 'Find & Play'},
{key: 'Last played', flags: isPlayCount ? MF_STRING : MF_GRAYED, req: 'foo_playcount'},
{key: 'Key', flags: MF_STRING},
{key: 'Key 6A centered', flags: MF_STRING},
];
menu.newEntry({menuName: subMenuNameSecond, entryText: 'Prioritize tracks by:', flags: MF_GRAYED});
menu.newEntry({menuName: subMenuNameSecond, entryText: 'sep'});
Expand Down Expand Up @@ -562,6 +568,100 @@
} else {menuDisabled.push({menuName: name, subMenuFrom: menuName, index: menu.getMenus().filter((entry) => {return menuAltAllowed.has(entry.subMenuFrom);}).length + disabledCount++, bIsMenu: true});}
}
}
{ // Group
const scriptPath = folders.xxx + 'main\\sort\\group_by_tags.js';
if (_isFile(scriptPath)){
const name = 'Group by tags';
if (!menusEnabled.hasOwnProperty(name) || menusEnabled[name] === true) {
include(scriptPath.replace(folders.xxx + 'main\\', '..\\'));
readmes[menuName + '\\' + name] = folders.xxx + 'helpers\\readme\\group_by_tags.txt';
const subMenuName = menu.newMenu(name, menuName);
let group = [
{name: 'Group by artist' , args: {tagName: [globTags.artist]}},
{name: 'Group by genre' , args: {tagName: [globTags.genre]}},
{name: 'Group by style' , args: {tagName: [globTags.style]}},
{name: 'Group by album' , args: {tagName: ['ALBUM']}}
];
let selArg = {name: 'Custom', args: group[0].args};
const groupDefaults = [...group];
// Create new properties with previous args
menu_properties['group'] = [menuName + '\\' + name + ' entries', JSON.stringify(group)];
menu_properties['groupCustomArg'] = [menuName + '\\' + name + ' Dynamic menu custom args', JSON.stringify(selArg)];
// Check
menu_properties['group'].push({func: isJSON}, menu_properties['group'][1]);
menu_properties['groupCustomArg'].push({func: isJSON}, menu_properties['groupCustomArg'][1]);
// Helpers
const inputGroup = () => {
let tagName = '';
try {tagName = utils.InputBox(window.ID, 'Enter tag(s) or TF expression(s):\n(multiple values may be separated by \';\')', scriptName + ': ' + name, selArg.args.tagName, true);}
catch (e) {return;}
if (!tagName.length) {return;}
tagName = tagName.split(/;|,/g);
return {args: {tagName}};
};
// Menus
menu.newEntry({menuName: subMenuName, entryText: 'Group by TF (without sorting):', func: null, flags: MF_GRAYED});
menu.newEntry({menuName: subMenuName, entryText: 'sep'});
menu.newCondEntry({entryText: 'Group... (cond)', condFunc: () => {
// Entry list
group = JSON.parse(menu_properties['group'][1]);
const entryNames = new Set();
group.forEach((groupObj) => {
// Add separators
if (groupObj.hasOwnProperty('name') && groupObj.name === 'sep') {
menu.newEntry({menuName: subMenuName, entryText: 'sep'});
} else {
// Create names for all entries
let groupName = groupObj.name;
groupName = groupName.length > 40 ? groupName.substring(0,40) + ' ...' : groupName;
if (entryNames.has(groupName)) {
fb.ShowPopupMessage('There is an entry with duplicated name:\t' + groupName + '\nEdit the custom entries and either remove or rename it.\n\nEntry:\n' + JSON.stringify(groupObj, null, '\t'), scriptName + ': ' + name);
return;
} else {entryNames.add(groupName);}
// Entries
menu.newEntry({menuName: subMenuName, entryText: groupName, func: () => {
groupByTags({
...groupObj.args,
bDebug: defaultArgs.bDebug
});
}, flags: multipleSelectedFlagsReorder});
}
});
menu.newEntry({menuName: subMenuName, entryText: 'sep'});
{ // Static menu: user configurable
menu.newEntry({menuName: subMenuName, entryText: 'By... (tag)', func: () => {
const ap = plman.ActivePlaylist;
if (ap === -1) {return;}
// On first execution, must update from property
selArg.args.tagName = JSON.parse(menu_properties['groupCustomArg'][1]).args.tagName;
// Input
const input = inputGroup();
if (!input) {return;}
// Execute
groupByTags({...input.args, bDebug: defaultArgs.bDebug});
// For internal use original object
selArg.args = input.args;
menu_properties['groupCustomArg'][1] = JSON.stringify(selArg); // And update property with new value
overwriteMenuProperties(); // Updates panel
}, flags: multipleSelectedFlagsReorder});
menu.newEntry({menuName: subMenuName, entryText: 'sep'});
}
{ // Add / Remove
createSubMenuEditEntries(subMenuName, {
name,
list: group,
propName: 'group',
defaults: groupDefaults,
defaultPreset: folders.xxx + 'presets\\Playlist Tools\\group\\default.json',
input : inputGroup
});
}
}});
} else {menuDisabled.push({menuName: name, subMenuFrom: menuName, index: menu.getMenus().filter((entry) => {return menuAltAllowed.has(entry.subMenuFrom);}).length + disabledCount++, bIsMenu: true});}
}
}
['Sort...', 'Advanced sort...', 'Scatter by tags', 'Intercalate by tags', 'Shuffle by tags', 'Group by tags']
.some((n) => !menusEnabled.hasOwnProperty(n) || menusEnabled[n] === true) && menu.newEntry({menuName, entryText: 'sep'});
{ // Remove and find in playlists
const scriptPath = folders.xxx + 'main\\playlists\\find_remove_from_playlists.js';
if (_isFile(scriptPath)){
Expand Down
8 changes: 5 additions & 3 deletions main/sort/scatter_by_tags.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';
//27/03/23
//21/07/23

include('..\\..\\helpers\\helpers_xxx_basic_js.js');
include('..\\..\\helpers\\helpers_xxx_prototypes.js');
Expand Down Expand Up @@ -91,7 +91,7 @@ function scatterByTags({
plman.SetPlaylistSelection(plman.ActivePlaylist, idx, true);
plman.SetPlaylistFocusItem(plman.ActivePlaylist, focusIdx);
}
console.log('Selection scattered by tag(s) \'' + tagValue.join(',') + '\' (' + tagName.join(', ') + ') on playlist: ' + plman.GetPlaylistName(plman.ActivePlaylist));
console.log('Selection scattered by tag(s) \'' + tagValue.join(', ') + '\' (' + tagName.join(', ') + ') on playlist: ' + plman.GetPlaylistName(plman.ActivePlaylist));
}
return selItemsArray;
}
Expand Down Expand Up @@ -181,7 +181,7 @@ function shuffleByTags({
bSendToActivePls = true,
data = {handleArray: [], dataArray: [], tagsArray: []}, // Shallow copies are made
bAdvancedShuffle = false, // Tries to scatter instrumental, live tracks, ...
sortBias = 'random', // random | playcount | rating | popularity | lastplayed | TitleFormat expression || '' (none)
sortBias = 'random', // random | playcount | rating | popularity | lastplayed | key | TitleFormat expression || '' (none)
sortDir = 1,
bDebug = false
} = {}) {
Expand Down Expand Up @@ -209,6 +209,8 @@ function shuffleByTags({
case 'rating': sortTF = '$max(%RATING%,$meta(RATING),0)'; break;
case 'popularity': sortTF = '$max($meta(Track Statistics Last.fm,5[score]),0)'; break;
case 'lastplayed': sortTF = bEnhPlayCount ? '%LAST_PLAYED_ENHANCED%' : '%LAST_PLAYED%'; break;
case 'key': sortTF = '$if($stricmp(%KEY%,G#m),$puts(kTrans,1B))$if($stricmp(%KEY%,Abm),$puts(kTrans,1B))$if($stricmp(%KEY%,D#m),$puts(kTrans,2B))$if($stricmp(%KEY%,Ebm),$puts(kTrans,2B))$if($stricmp(%KEY%,A#m),$puts(kTrans,3B))$if($stricmp(%KEY%,Bbm),$puts(kTrans,3B))$if($stricmp(%KEY%,Fm),$puts(kTrans,4B))$if($stricmp(%KEY%,Cm),$puts(kTrans,5B))$if($stricmp(%KEY%,Gm),$puts(kTrans,6B))$if($stricmp(%KEY%,Dm),$puts(kTrans,7B))$if($stricmp(%KEY%,Am),$puts(kTrans,8B))$if($stricmp(%KEY%,Em),$puts(kTrans,9B))$if($stricmp(%KEY%,Bm),$puts(kTrans,10B))$if($stricmp(%KEY%,F#m),$puts(kTrans,11B))$if($stricmp(%KEY%,Gbm),$puts(kTrans,11B))$if($stricmp(%KEY%,C#m),$puts(kTrans,12B))$if($stricmp(%KEY%,Dbm),$puts(kTrans,12B))$if($stricmp(%KEY%,6m),$puts(kTrans,1B))$if($stricmp(%KEY%,7m),$puts(kTrans,2B))$if($stricmp(%KEY%,8m),$puts(kTrans,3B))$if($stricmp(%KEY%,9m),$puts(kTrans,4B))$if($stricmp(%KEY%,10m),$puts(kTrans,5B))$if($stricmp(%KEY%,11m),$puts(kTrans,6B))$if($stricmp(%KEY%,12m),$puts(kTrans,7B))$if($stricmp(%KEY%,1m),$puts(kTrans,8B))$if($stricmp(%KEY%,2m),$puts(kTrans,9B))$if($stricmp(%KEY%,3m),$puts(kTrans,10B))$if($stricmp(%KEY%,4m),$puts(kTrans,11B))$if($stricmp(%KEY%,5m),$puts(kTrans,12B))$if($stricmp(%KEY%,B),$puts(kTrans,1A))$if($stricmp(%KEY%,F#),$puts(kTrans,2A))$if($stricmp(%KEY%,Gb),$puts(kTrans,2A))$if($stricmp(%KEY%,C#),$puts(kTrans,3A))$if($stricmp(%KEY%,Db),$puts(kTrans,3A))$if($stricmp(%KEY%,G#),$puts(kTrans,4A))$if($stricmp(%KEY%,Ab),$puts(kTrans,4A))$if($stricmp(%KEY%,D#),$puts(kTrans,5A))$if($stricmp(%KEY%,Eb),$puts(kTrans,5A))$if($stricmp(%KEY%,A#),$puts(kTrans,6A))$if($stricmp(%KEY%,Bb),$puts(kTrans,6A))$if($stricmp(%KEY%,F),$puts(kTrans,7A))$if($stricmp(%KEY%,C),$puts(kTrans,8A))$if($stricmp(%KEY%,G),$puts(kTrans,9A))$if($stricmp(%KEY%,D),$puts(kTrans,10A))$if($stricmp(%KEY%,A),$puts(kTrans,11A))$if($stricmp(%KEY%,E),$puts(kTrans,12A))$if($stricmp(%KEY%,6d),$puts(kTrans,1A))$if($stricmp(%KEY%,7d),$puts(kTrans,2A))$if($stricmp(%KEY%,8d),$puts(kTrans,3A))$if($stricmp(%KEY%,9d),$puts(kTrans,4A))$if($stricmp(%KEY%,10d),$puts(kTrans,5A))$if($stricmp(%KEY%,11d),$puts(kTrans,6A))$if($stricmp(%KEY%,12d),$puts(kTrans,7A))$if($stricmp(%KEY%,1d),$puts(kTrans,8A))$if($stricmp(%KEY%,2d),$puts(kTrans,9A))$if($stricmp(%KEY%,3d),$puts(kTrans,10A))$if($stricmp(%KEY%,4d),$puts(kTrans,11A))$if($stricmp(%KEY%,5d),$puts(kTrans,12A))$if($get(kTrans),,$puts(kTrans,%key%))$get(kTrans)';break;
case 'key6acentered': sortTF = '$if($stricmp(%KEY%,G#m),$puts(kTrans,7B))$if($stricmp(%KEY%,Abm),$puts(kTrans,7B))$if($stricmp(%KEY%,D#m),$puts(kTrans,8B))$if($stricmp(%KEY%,Ebm),$puts(kTrans,8B))$if($stricmp(%KEY%,A#m),$puts(kTrans,9B))$if($stricmp(%KEY%,Bbm),$puts(kTrans,9B))$if($stricmp(%KEY%,Fm),$puts(kTrans,10B))$if($stricmp(%KEY%,Cm),$puts(kTrans,11B))$if($stricmp(%KEY%,Gm),$puts(kTrans,12B))$if($stricmp(%KEY%,Dm),$puts(kTrans,1B))$if($stricmp(%KEY%,Am),$puts(kTrans,2B))$if($stricmp(%KEY%,Em),$puts(kTrans,3B))$if($stricmp(%KEY%,Bm),$puts(kTrans,4B))$if($stricmp(%KEY%,F#m),$puts(kTrans,5B))$if($stricmp(%KEY%,Gbm),$puts(kTrans,5B))$if($stricmp(%KEY%,C#m),$puts(kTrans,6B))$if($stricmp(%KEY%,Dbm),$puts(kTrans,6B))$if($stricmp(%KEY%,6m),$puts(kTrans,7B))$if($stricmp(%KEY%,7m),$puts(kTrans,8B))$if($stricmp(%KEY%,8m),$puts(kTrans,9B))$if($stricmp(%KEY%,9m),$puts(kTrans,10B))$if($stricmp(%KEY%,10m),$puts(kTrans,11B))$if($stricmp(%KEY%,11m),$puts(kTrans,12B))$if($stricmp(%KEY%,12m),$puts(kTrans,1B))$if($stricmp(%KEY%,1m),$puts(kTrans,2B))$if($stricmp(%KEY%,2m),$puts(kTrans,3B))$if($stricmp(%KEY%,3m),$puts(kTrans,4B))$if($stricmp(%KEY%,4m),$puts(kTrans,5B))$if($stricmp(%KEY%,5m),$puts(kTrans,6B))$if($stricmp(%KEY%,B),$puts(kTrans,7A))$if($stricmp(%KEY%,F#),$puts(kTrans,8A))$if($stricmp(%KEY%,Gb),$puts(kTrans,8A))$if($stricmp(%KEY%,C#),$puts(kTrans,9A))$if($stricmp(%KEY%,Db),$puts(kTrans,9A))$if($stricmp(%KEY%,G#),$puts(kTrans,10A))$if($stricmp(%KEY%,Ab),$puts(kTrans,10A))$if($stricmp(%KEY%,D#),$puts(kTrans,11A))$if($stricmp(%KEY%,Eb),$puts(kTrans,11A))$if($stricmp(%KEY%,A#),$puts(kTrans,12A))$if($stricmp(%KEY%,Bb),$puts(kTrans,12A))$if($stricmp(%KEY%,F),$puts(kTrans,1A))$if($stricmp(%KEY%,C),$puts(kTrans,2A))$if($stricmp(%KEY%,G),$puts(kTrans,3A))$if($stricmp(%KEY%,D),$puts(kTrans,4A))$if($stricmp(%KEY%,A),$puts(kTrans,5A))$if($stricmp(%KEY%,E),$puts(kTrans,6A))$if($stricmp(%KEY%,6d),$puts(kTrans,7A))$if($stricmp(%KEY%,7d),$puts(kTrans,8A))$if($stricmp(%KEY%,8d),$puts(kTrans,9A))$if($stricmp(%KEY%,9d),$puts(kTrans,10A))$if($stricmp(%KEY%,10d),$puts(kTrans,11A))$if($stricmp(%KEY%,11d),$puts(kTrans,12A))$if($stricmp(%KEY%,12d),$puts(kTrans,1A))$if($stricmp(%KEY%,1d),$puts(kTrans,2A))$if($stricmp(%KEY%,2d),$puts(kTrans,3A))$if($stricmp(%KEY%,3d),$puts(kTrans,4A))$if($stricmp(%KEY%,4d),$puts(kTrans,5A))$if($stricmp(%KEY%,5d),$puts(kTrans,6A))$if($get(kTrans),,$puts(kTrans,%key%))$get(kTrans)';break;
case 'random': sortTF = null; break;
default: sortTF = sortBias; // Pass a TF expression or empty (don't sort)
}
Expand Down

0 comments on commit 3dd75ba

Please sign in to comment.