Command: CreateRetroArchPlaylist

I needed to create a bunch of playlist for RetroArch, to configure multi-disk games for the PUAE core.
This command takes the selected files, tries to guess the game's name (common text minus d,disk, etc) and generates an .m3u file with the selected file names.

If you save the list exactly on the same folder as the game files, the paths will be relative, if you save it somewhere else it will save absolute file paths.

<?xml version="1.0" encoding="UTF-8"?>
<usercommand backcol="none" hide_from_menu="no" textcol="none">
	<label>CreateRetroArchPlaylist</label>
	<tip>Creates a RetroArch compatible playlist with the selected files.</tip>
	<user_label>Create RetroArch Playlist</user_label>
	<icon1>/hostpictures/dopus-icons/retroarch-playlist.png,0</icon1>
	<function type="script">
		<instruction>@disablenosel</instruction>
		<instruction>@script JScript</instruction>
		<instruction>function openSaveDialog(sourceTab, defaultName) {</instruction>
		<instruction>	return DOpus.Dlg.Save(&quot;Generate M3U Playlist&quot;, sourceTab.path+&quot;\\&quot;+defaultName+&quot;.m3u&quot;, sourceTab, &quot;M3U Playlist!*.m3u&quot;);</instruction>
		<instruction>}</instruction>
		<instruction />
		<instruction>function checkCommonText(text, text2) {		</instruction>
		<instruction>	for(var i = 0; i &lt; Math.min(text.length, text2.length); i++) {</instruction>
		<instruction>		if(text[i].toLowerCase() != text2[i].toLowerCase()) break;</instruction>
		<instruction>	}</instruction>
		<instruction>	return text.substr(0, i);</instruction>
		<instruction>}</instruction>
		<instruction />
		<instruction>function getCommonStartingText (texts, defaultText) {</instruction>
		<instruction>	var sortByLength = function(a, b) {</instruction>
		<instruction>		var diff = (a.length - b.length);</instruction>
		<instruction>		return diff / Math.abs(diff);</instruction>
		<instruction>	};</instruction>
		<instruction>	texts.sort(sortByLength);</instruction>
		<instruction>	var commonStartText = texts[0];	</instruction>
		<instruction>	for(var i = 1; i &lt; texts.length &amp;&amp; commonStartText.length &gt; 0; i++) {</instruction>
		<instruction>		commonStartText = checkCommonText(commonStartText, texts[i]);</instruction>
		<instruction>	}</instruction>
		<instruction>	var result = (commonStartText.length == 0 ? defaultText : commonStartText);	</instruction>
		<instruction>	var garbageEnds = [/[-\(#_]*\s*\d*$/,/[-\(]*\s*(d|disk|part)\s*$/i, /\.(\w{1,3})$/i, /\s*$/];</instruction>
		<instruction>	for(var i = 0; i &lt; garbageEnds.length; i++) {</instruction>
		<instruction>		result = result.replace(garbageEnds[i], &quot;&quot;);</instruction>
		<instruction>	}</instruction>
		<instruction>	return result;</instruction>
		<instruction>}</instruction>
		<instruction />
		<instruction>function savePlaylist(items, path, prependPath) {</instruction>
		<instruction>	var sourcePath = DOpus.FSUtil.Resolve(path);</instruction>
		<instruction>	var fso = new ActiveXObject(&quot;Scripting.FileSystemObject&quot;);</instruction>
		<instruction>	var m3uFile = fso.CreateTextFile(sourcePath, true);</instruction>
		<instruction>	for(var i = 0; i &lt; items.length; i++) {</instruction>
		<instruction>		m3uFile.WriteLine(prependPath+items[i])</instruction>
		<instruction>	}</instruction>
		<instruction>	m3uFile.Close();</instruction>
		<instruction>}</instruction>
		<instruction />
		<instruction>function getSelectedFiles(sourceTab) {</instruction>
		<instruction>	var fileNames = [];</instruction>
		<instruction>	for (var eSel = new Enumerator(sourceTab.selected); !eSel.atEnd(); eSel.moveNext())</instruction>
		<instruction>	{</instruction>
		<instruction>		var item = eSel.item();</instruction>
		<instruction>		if (!item.is_dir)</instruction>
		<instruction>		{</instruction>
		<instruction>			fileNames.push(item.name);</instruction>
		<instruction>		}			</instruction>
		<instruction>	}</instruction>
		<instruction>	return fileNames;</instruction>
		<instruction>}</instruction>
		<instruction />
		<instruction>function OnClick(clickData)</instruction>
		<instruction>{</instruction>
		<instruction>	// --------------------------------------------------------</instruction>
		<instruction>	DOpus.ClearOutput();</instruction>
		<instruction>	// --------------------------------------------------------</instruction>
		<instruction>	var cmd = clickData.func.command;</instruction>
		<instruction>	cmd.deselect = false; // Prevent automatic deselection</instruction>
		<instruction>	// --------------------------------------------------------</instruction>
		<instruction>	cmd.RunCommand(&quot;Set VIEW=Details&quot;);</instruction>
		<instruction>	// --------------------------------------------------------</instruction>
		<instruction>	var sourceTab = clickData.func.sourcetab;	</instruction>
		<instruction>	var listItems = getSelectedFiles(sourceTab);</instruction>
		<instruction>	var dialogResult = openSaveDialog(sourceTab, getCommonStartingText(listItems, &quot;playlist&quot;));		</instruction>
		<instruction>	if(dialogResult.result) {</instruction>
		<instruction>		var isPathDifferent = dialogResult.pathpart != sourceTab.path;</instruction>
		<instruction>		var prependPath = isPathDifferent ? sourceTab.path + &quot;\\&quot; : &quot;&quot;;		</instruction>
		<instruction>		savePlaylist(listItems, dialogResult, prependPath);</instruction>
		<instruction>		DOpus.Notify(&quot;Playlist generated&quot;, &quot;File &apos;&quot; + dialogResult.filepart + &quot;&apos; generated.&quot;);</instruction>
		<instruction>	}		</instruction>
		<instruction>}</instruction>
	</function>
</usercommand>

Icon:
retroarch-playlist

1 Like