Script to fix dumb Zen MX playlist format

Post a reply

Smilies
:D :) :( :o :-? 8) :lol: :x :P :oops: :cry: :evil: :roll: :wink:

BBCode is ON
[img] is ON
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Script to fix dumb Zen MX playlist format

Re: Script to fix dumb Zen MX playlist format

by rovingcowboy » Tue Dec 25, 2012 6:54 am

Thanks for the christmas present. :)

Re: Script to fix dumb Zen MX playlist format

by stoffel » Tue Dec 25, 2012 6:30 am

Here is another, probably last update of my script. It provides some more elaborate error handling in case of missing track files.
Tested with newest MM 4.0.7 under W7

Enjoy :D

Code: Select all

// Fix stupid ZEN MX Bug: Playlists must define their tracknames in 8.3 DOS style
// Convert every playlist '<name>.m3u' found in /playlist to '@ <name>.m3u' changing tracknames to 8.3 DOS style.
// By default original files are not changed
//
// (c) Stefan Skopnik (sskopnik(at)web(dot)de)
//
// 01.01.2010 fixes for W7, don't generate if newpl exists and is newer than orgpl, changed NewPlName
// 14.01.2010 scan for drive modified, test for dir exist, more detailed messages, change naming schema again to: '@ <name>.m3u'
// 08.09.2011 fixes for Zen Style 100 and MM4 (now works with MM3 and MM4)
// 12.09.2011 New Configsystem. New flags DeleteOrgPl and ReplaceOrgPl.
//            Now you can decide if you want to:
//            - delete the original pl-file after conversion (DeleteOrgPl=true) leaving only the converted @pl-file
//            - replace the old pl-file with the converted version (ReplaceOrgPl=true) preserving the original name.
//              (This may be the default in the future, Here only converted files are taken into account)
// 24.12.2012 More intelligent error handling in case of missing files
/*

Installation:
-------------
0.) IMPORTANT: Configure your ZEN device in MM : Under Playlist / Options: *Don't* use
    UTF8 Unicode Coding for .m3u playlists 

1.) Copy this file to <MediaMonkeyInstallDir>\Scripts\FixZenMXPlaylist.js
    (Windows7: This dir is write protected, you have to change this!)

2.) Append to file <MediaMonkeyInstallDir>\Scripts\scripts.ini:
< --- COPY AFTER THIS LINE --->
[FixZenMXPlaylist]
FileName=FixZenMXPlaylist.js
ProcName=FixZenMXPlaylist
Order=1
DisplayName=Fix dumb ZEN MX playlist
;DisplayName=Korrektur von ZEN MX Playlisten

Description=Fixes ZEN MX playlist by converting filepath into 8.3 DOS format
;Description=Korrektur von ZEN MX Playlisten durch konvertieren der Dateinamen/pfade in das 8.3 DOS Format
Language=JScript
ScriptType=0
<--- COPY BEFORE THIS LINE --->

3.) (Re)start MM

4.) Plugin Zen MX and create PLs in MediaMonkey

5.) Send PL to 'My ZEN'

6.) Run this Script from Extras / Scripts / Fix dumb ZEN MX playlist

7.) Unplug ZEN MX

8.) Enjoy your MM PL on ZEN MX. You find them under '@ <ORGNAME>.m3u


Configuration:
-------------

This script should work 'out of the box' with Zen MX Player using english language.
If you like you can configure the script in some aspects. See 'Config' for options

*/

var Config = {                              // All user changeable config settings go here
        Language     : 'en',                // Set your prefered language (Currently 'en' = English, 'de' = German is supported)
        DeleteOrgPl  : false,               // Set true if you want to delete original playlist files after conversion
        ReplaceOrgPl : false,               // Set true if you want to replace original playlist with converted version
        Device       : 'ZENMX',             // Define your player device here, see 'DeviceConfig' for possible devices (ZENMX,ZENSTYLE100)
        NewPlName    : "@ %1.%2",           // Mask for new Playlist filenames,
                                            // %1 is replaced with old filenameprefix, %2 is replaced with old filenamesuffix
        ReExclFn     : /@.*\.m3u$/          // RE for Filenames to be EXCLUDED from conversion (must match 'NewPlName')
    },
    
    re_inclfn    = /\.m3u$/,                // RE for Filenames to be INCLUDED into conversion
    re_ignoreln  = /^#/,                    // RE for lines to be ignored during conversion
    OutDrive     = "?",                     // Define your Zen MX Drive ('X:') or leave "?" to let script find device
    OutDir       = "\\Playlist",            // Define location of PL on device
    Scriptname   = "FixZenMXPlaylist.js",
    Version      = "1.05",
    FileComment  = "#!@ 8.3 DOS converted by %1 V%2",
    re_flag      = /^#!@ 8.3 DOS converted/,

    DeviceConfig = {                        // Deviceconfiguration. You have to look into the registry!
        'ZENMX'       : "USBSTOR\\Disk&Ven_Creative&Prod_ZEN_MX",
        'ZENSTYLE100' : "USBSTOR\\Disk&Ven_Creative&Prod_ZEN_Style_Series&Rev_0200"
    },

    Lang_rc = {
        'de' : {
            msg0 : "Es wurden keine Playlisten im Verzeichnis '%2' erstellt.",
            msg1 : "Folgende %1 neue Playlisten wurden im Verzeichnis '%2' erstellt:\n\n",
            msg2 : "Folgende neue Playliste wurde im Verzeichnis '%2' erstellt:\n\n",
            msg4 : "Kein Zen MX MP3-Player gefunden!",
            msg5 : "Zen MX MP3-Player in Laufwerk '%1' gefunden.\nPlaylisten konvertieren?",
            msg6 : "Unterverzeichnis '%1' auf Laufwerk '%2' nicht gefunden!",
            msg7 : "Zen MX MP3-Player gefunden, aber Unterverzeichnis '%1' fehlt!",
            msg8 : "Fehler in Playliste '%1':\nFehlender Titel '%2'!\n\nAbbrechen = Weiter mit der nächsten Playliste, Abbruch = Programmabbruch",
			msg9 : "Einige Titel konnten nicht gefunden werden!"
        },
        'en' : {
            msg0 : "No playlists created in directory '%2'.",
            msg1 : "%1 new playlists where created in directory '%2':\n\n",
            msg2 : "%1 new playlist was created in directory '%2':\n\n",
            msg4 : "No Zen MX MP3-Player found!",
            msg5 : "Found Zen MX MP3-Player in drive '%1'.\nConvert Playlists?",
            msg6 : "Subdirectory '%1' missing on drive '%2'!",
            msg7 : "Zen MX MP3-Player found, but subdirectory '%1' missing!",
			msg8 : "Error in playlist '%1':\nMissing title '%2'!\n\nCancel = Continue with next playlist, Abort = Exit program",
			msg9 : "Could't find some titles!"
        }
    },
    Lang = Lang_rc[Config.Language],
    
    objFso = new ActiveXObject("Scripting.FileSystemObject"),
    objDic = new ActiveXObject("Scripting.Dictionary"),
    C_ForReading = 1
;

// some utillity functions

function sprintf() {
var savearg = arguments;

    return savearg[0].replace(new RegExp("%(\\d+)","g"),
                function ($0, $1, $2) { return savearg[$1]; }
           );
}

function getDriveLetter(i) {
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    s;
    s = str.charAt(i);
    return(s + ":");
}

function JS2VBArray(objJSArray) {
    objDic.RemoveAll();
    for (var i = 0; i < objJSArray.length; i++ ) {
        objDic.add(i,objJSArray[i]);
    }
    return objDic.Items();
}

function getShortPath(filespec, nodrive) {
// messageBox("File: " + filespec, mtInformation, new Array(mbOk.toString()));
var f,
    ret;

	try {
		f = objFso.GetFile(filespec),
		ret = f.ShortPath;
	} catch (e) {
	 return undefined;
	}
	
    if (nodrive) ret = ret.substr(2);
    return(ret);
}

function convColltoArr(col) {
var ret = new Array();

    for (var e = new Enumerator(col), i = 0; !e.atEnd(); e.moveNext(), i++) {
        ret[i] = e.item();
    }
    return ret;
}

function stripDriveLetter(fn) {
var start = fn.indexOf(":");

    return fn.slice(++start);
}

function getPath(fn) {
var stop = fn.lastIndexOf("\\");

    if (stop==-1) return "";
    return fn.slice(0,stop);
}

function getFilename(fn) {
var start = fn.lastIndexOf("\\");

    return fn.slice(++start);
}

function getFilenamePrefix(fn) {
var ret = getFilename(fn),
    stop = ret.lastIndexOf(".");

    if (stop==-1) return ret;
    return ret.slice(0,stop);
}

function getFilenameSuffix(fn) {
var ret = getFilename(fn),
    start = ret.lastIndexOf(".");

    if (start==-1) return "";
    return ret.slice(++start);
}

function messageBox(s,t,barr) {
    return SDB.MessageBox(s, t, JS2VBArray(barr));
}

// ---

function FixZenMXPlaylist() {
var fc,
    fin,
    fout,
    orgfile,
    newfile,
    newfilearr = new Array(),
    nrfiles = 0,
	bufferline,
    ret,
	ret2,
	bIgnoreAll = false,
    devlist,
    i,
    f_org,
    f_new,
    actmsg,
	errmsg = '';

    /*
     * Find the Drive letter of Zen MX
     * Well, I have no real idea what ActiveDeviceList is supposed to return. XP and W7 return complety different FriendlyNames.
     * In W7 the second Drive is never returned.
     * So this is a rather dumb method:
     *
     * Scan all Drives with correct vendor&Product Name.
     *   If you find drive with existing subdir <OutDir> use it!
     *   else give up!
     *
     * This was tested with XP / W7 successfully
     */
    if (OutDrive == "?") {
        devlist = SDB.Device.ActiveDeviceList(DeviceConfig[Config.Device]); 
        for (i = 0; i < devlist.Count;i++) {
            OutDrive = "!";
            //messageBox(i + ": (" + devlist.DeviceID(i) + ") " + devlist.FriendlyName(i) + " " +
            //    devlist.DeviceInst(i) + " " + getDriveLetter(devlist.DriveLetterIndex(i)), mtInformation, new Array(mbOk) );
            TestOutDrive = getDriveLetter(devlist.DriveLetterIndex(i));
            // if (devlist.FriendlyName(i) == "Creative ZEN MX USB Device") break;
            if (objFso.FolderExists(TestOutDrive + OutDir)) {
                OutDrive = TestOutDrive;
                break;
            }
        }
    }
    switch (OutDrive) {
        case "?":   messageBox(Lang.msg4, mtError, new Array(mbOk.toString())); // single num arg to array constructor sets array size!
                    return(-1);
        case "!":   messageBox(sprintf(Lang.msg7, OutDir), mtError, new Array(mbOk.toString()));
                    return(-1);
        default:    ret = messageBox(sprintf(Lang.msg5, OutDrive), mtConfirmation, new Array(mbOk, mbCancel));
                    if (ret == mrCancel) return (-2);
    }

    // Ok, we want this folder! Else exit
    if (!objFso.FolderExists(OutDrive + OutDir)) {
        messageBox(sprintf(Lang.msg6, OutDir, OutDrive), mtError, new Array(mbOk.toString())); // single num arg to array constructor sets array size!
        return(-1);
    }

    objDir = objFso.GetFolder(OutDrive + OutDir);

    for (fc = new Enumerator(objDir.files); !fc.atEnd() && ret2 != mrAbort; fc.moveNext()) {
        ele = fc.item();
        if (re_inclfn.test(ele.Name) && !Config.ReExclFn.test(ele.Name)) {
            // WScript.Echo("File: " + ele.Path);

            orgfile = ele.Path;
            newfile = getPath(orgfile) + "\\" + sprintf (Config.NewPlName, getFilenamePrefix(orgfile), getFilenameSuffix(orgfile));

            // Don't generate if newfile already exists and is newer than oldfile
            if (objFso.FileExists(newfile)) {
                f_org = objFso.GetFile(orgfile);
                f_new = objFso.GetFile(newfile);
                if (f_new.DateLastModified > f_org.DateLastModified) continue;
            }

            fin = objFso.OpenTextFile(orgfile, C_ForReading, false);
            fout = objFso.CreateTextFile(newfile, true);

            l = fin.ReadLine();
            if (!l || re_flag.test(l)) { 			// was the file already converted? don't do it again
				fin.Close();
			    fout.Close();
			    objFso.DeleteFile(newfile, true);
				continue;
			}			
            bufferLine = l;                         // else buffer the first line

            nrfiles++;
            newfilearr.push(getFilename(Config.ReplaceOrgPl ? orgfile : newfile));

            fout.WriteLine(sprintf(FileComment, Scriptname, Version)); // mark new file as converted
            while (!fin.AtEndOfStream) {
				ret2 = undefined;

                if (bufferLine) {   
                    l = bufferLine;
                    bufferLine = undefined;
                } else {
                    l = fin.ReadLine();
                }

                if (!re_ignoreln.test(l)) {
                    l = stripDriveLetter(l);    // MM4 by default generates filepath with drive letters, we don't want them!
                    sn = getShortPath(OutDrive + l, true);
					if (sn == undefined) {
						if (bIgnoreAll) ret = mrIgnore;
						else {
							errmsg = '\n\n' + Lang['msg9'];
							ret2 = messageBox(sprintf(Lang['msg8'], orgfile, OutDrive + l),
								mtError, new Array(mbCancel.toString(), mbAbort.toString(), mbIgnore.toString(), mbIgnoreToAll.toString() )
								);
							if (ret2 == mrAbort || ret2 == mrCancel) break;	
							if (ret2 == mrIgnoreToAll) bIgnoreAll = true;
						}
					}
                    l = sn;
                }
                if (ret2 == undefined) fout.WriteLine(l);

            }
            fin.Close();
            fout.Close();

            if (Config.DeleteOrgPl || Config.ReplaceOrgPl)    objFso.DeleteFile(orgfile, true);
            if (Config.ReplaceOrgPl)                          objFso.MoveFile(newfile, orgfile);
        }
    }
    switch (nrfiles) {
        case 0:     actmsg = 'msg0'; break
        case 1:     actmsg = 'msg2'; break
        default:    actmsg = 'msg1';
    }
    messageBox(sprintf(Lang[actmsg], nrfiles, OutDrive + OutDir) + newfilearr.join(", ") + errmsg,
        errmsg ? mtError : mtInformation, new Array(mbOk.toString())
    );
    return (0);
}

Re: Script to fix dumb Zen MX playlist format

by stoffel » Tue Oct 09, 2012 4:08 pm

Well, sorry I haven't been into Zen playlist business lately. What version of MM are you using?
It seems that:

line 290:
sn = getShortPath(OutDrive + l, true);

has a problem. Can you add a

messageBox(OutDrive + l, mtError, new Array(mbOk.toString()));

before the line 290, start again an report the output. Is it a valid Path? Maybe you should change the option "Force relative path" under External Device - Playlist to OFF

Please send the response of the output to stefan.skopnik@osnanet.de, because I do no look into this forum frequently!

Re: Script to fix dumb Zen MX playlist format

by Orion » Mon Sep 24, 2012 1:16 am

Hi stoffel!


I cant get your script working on my zen style 100 :( Ive spent hours trying to remove the error msg, but I guess I need a pro.

This is the msg I keep getting, similar to pawriter:

error #53 - Microsoft jscript runtime error
file not found
File: 'C:\programefiles\mediamonkey\scripts\fixzenmxplaylist.js, line:139, Column 0

I have settled all your requirements, created the script, pasted it, changed the ini file, and changed the script from zenMX to zenstyle100.

Please help,


Thanks!

Orion

Re: Script to fix dumb Zen MX playlist format

by stoffel » Wed Sep 28, 2011 4:52 am

PawWriter wrote:Hi there!

The script I am running is the one I copied and pasted from the previous page of this thread in a file titled "FixZenMXPlaylist.js" in the scripts folder of my Media Monkey install.

I also have the following entry appended on the "Scripts.ini" file of the install:
[FixZenMXPlaylist]
FileName=FixZenMXPlaylist.js
ProcName=FixZenMXPlaylist
Order=1
DisplayName=Fix dumb ZEN MX playlist
;DisplayName=Korrektur von ZEN MX Playlisten
Description=Fix dumb ZEN MX playlist
;Description=Korrektur von ZEN MX Playlisten
Language=JScript
ScriptType=0

Thanks for the help!
Looks good! Maybe we should continue our communication via PM to speed up the solution process. You find my eMail in the sourcecode.
I'm still not quite sure about your problem

Re: Script to fix dumb Zen MX playlist format

by PawWriter » Tue Sep 27, 2011 12:53 pm

Hi there!

The script I am running is the one I copied and pasted from the previous page of this thread in a file titled "FixZenMXPlaylist.js" in the scripts folder of my Media Monkey install.

I also have the following entry appended on the "Scripts.ini" file of the install:
[FixZenMXPlaylist]
FileName=FixZenMXPlaylist.js
ProcName=FixZenMXPlaylist
Order=1
DisplayName=Fix dumb ZEN MX playlist
;DisplayName=Korrektur von ZEN MX Playlisten
Description=Fix dumb ZEN MX playlist
;Description=Korrektur von ZEN MX Playlisten
Language=JScript
ScriptType=0

Thanks for the help!

Re: Script to fix dumb Zen MX playlist format

by stoffel » Fri Sep 23, 2011 2:45 am

PawWriter wrote:Hi there,
Question: how do you run a Scriptconfiguration? Sorry for the ignorance. Prior to Media Monkey, I never really messed with Java at all.

Next question: how would I put in a sample pl?
Well, sorry maybe I did presume too much :D

First of all you don't have to mess with Java! JavaScript has nothing to do with Java, its a Scripting language more like VisualBasic for Applications (VBA) for C-Programmers.

In the script there is a configuration block. You answer shows me, that you didn't mess with the configuaration, so everything should be set to default.

Are you sure you're running the right script? Where did you place the new script version? Did you copy it under C:\<PROGDIR>\MediaMonkey4\Scripts ? Correct name: FixZenMXPlaylist.js
I think there something wrong with your infrastructure!

Re: Script to fix dumb Zen MX playlist format

by PawWriter » Thu Sep 22, 2011 8:24 pm

Hi there,
Question: how do you run a Scriptconfiguration? Sorry for the ignorance. Prior to Media Monkey, I never really messed with Java at all.

Next question: how would I put in a sample pl?

Re: Script to fix dumb Zen MX playlist format

by stoffel » Wed Sep 21, 2011 8:47 am

PawWriter wrote:Hi there,
The "one playlist at a time" error happens only when "Force relative paths" is selected. When that option isn't selected, none of the playlists convert and it returns the same runtime error.
Sure you are using the latest version of my script ??? It should run fine NOT depending on "Force relative paths" ! Tested this!!!
Please try the latest version below (with a small fix). You could post a pl example and your Scriptconfiguration:

var Config = { // All user changeable config settings go here
Language : 'en', // Set your prefered language (Currently 'en' = English, 'de' = German is supported)
DeleteOrgPl : false, // Set true if you want to delete original playlist files after conversion
ReplaceOrgPl : true, // Set true if you want to replace original playlist with converted version
Device : 'ZENMX', // Define your player device here, see 'DeviceConfig' for possible devices (ZENMX,ZENSTYLE100)
NewPlName : "@ %1.%2", // Mask for new Playlist filenames,
// %1 is replaced with old filenameprefix, %2 is replaced with old filenamesuffix
ReExclFn : /@.*\.m3u$/ // RE for Filenames to be EXCLUDED from conversion (must match 'NewPlName')
},

Code: Select all

/*
  Fix stupid ZEN MX Bug: Playlists on the ZEN MX must define their tracknames in 8.3 DOS style
  Convert every playlist '<name>.m3u' found in /playlist to '@ <name>.m3u' changing tracknames to 8.3 DOS style.
  By default original files are not changed
 
  (c) Stefan Skopnik (sskopnik(at)web(dot)de)
 
  01.01.2010 fixes for W7, don't generate if newpl exists and is newer than orgpl, changed NewPlName
  14.01.2010 scan for drive modified, test for dir exist, more detailed messages, change naming schema again to: '@ <name>.m3u'
  08.09.2011 fixes for Zen Style 100 and MM4 (now works with MM3 and MM4)
  12.09.2011 New Configsystem. New flags DeleteOrgPl and ReplaceOrgPl.
             Now you can decide if you want to:
             - delete the original pl-file after conversion (DeleteOrgPl=true) leaving only the converted @pl-file
             - replace the old pl-file with the converted version (ReplaceOrgPl=true) preserving the original name.
               (This may be the default in the future, Here only converted files are taken into account)
  18.09.2011 fix: don't create @-files of 0 bytes if no file need to be created


Installation:
-------------

1.) Copy this file to <MediaMonkeyInstallDir>\Scripts\FixZenMXPlaylist.js
    (Windows7: This dir is write protected, you have to change this!)

2.) Append to file <MediaMonkeyInstallDir>\Scripts\scripts.ini:

< --- COPY AFTER THIS LINE --->
[FixZenMXPlaylist]
FileName=FixZenMXPlaylist.js
ProcName=FixZenMXPlaylist
Order=1
DisplayName=Fix dumb ZEN MX playlist
;DisplayName=Korrektur von ZEN MX Playlisten

Description=Fixes ZEN MX playlist by converting filepath into 8.3 DOS format
;Description=Korrektur von ZEN MX Playlisten durch Konvertieren der Dateinamen/pfade in das 8.3 DOS Format
Language=JScript
ScriptType=0
<--- COPY BEFORE THIS LINE --->

3.) (Re)start MM

4.) Plugin Zen MX and create PLs in MediaMonkey

5.) Send PL to 'My ZEN'

6.) Run this Script from Extras / Scripts / Fix dumb ZEN MX playlist

7.) Unplug ZEN MX

8.) Enjoy your MM PL on ZEN MX. You find them under '@ <ORGNAME>.m3u


Configuration:
-------------

This script should work 'out of the box' with Zen MX Player using english laguage.
If you like you can configure the script in some aspects. See 'Config' for options

*/

var Config = {                              // All user changeable config settings go here
        Language     : 'en',                // Set your prefered language (Currently 'en' = English, 'de' = German is supported)
        DeleteOrgPl  : false,               // Set true if you want to delete original playlist files after conversion
        ReplaceOrgPl : true,               // Set true if you want to replace original playlist with converted version
        Device       : 'ZENMX',             // Define your player device here, see 'DeviceConfig' for possible devices (ZENMX,ZENSTYLE100)
        NewPlName    : "@ %1.%2",           // Mask for new Playlist filenames,
                                            // %1 is replaced with old filenameprefix, %2 is replaced with old filenamesuffix
        ReExclFn     : /@.*\.m3u$/          // RE for Filenames to be EXCLUDED from conversion (must match 'NewPlName')
    },
    
    re_inclfn    = /\.m3u$/,                // RE for Filenames to be INCLUDED into conversion
    re_ignoreln  = /^#/,                    // RE for lines to be ignored during conversion
    OutDrive     = "?",                     // Define your Zen MX Drive ('X:') or leave "?" to let script find device
    OutDir       = "\\Playlist",            // Define location of PL on device
    Scriptname   = "FixZenMXPlaylist.js",
    Version      = "1.05",
    FileComment  = "#!@ 8.3 DOS converted by %1 V%2",
    re_flag      = /^#!@ 8.3 DOS converted/,

    DeviceConfig = {                        // Deviceconfiguration. You have to look into the registry!
        'ZENMX'       : "USBSTOR\\Disk&Ven_Creative&Prod_ZEN_MX",
        'ZENSTYLE100' : "USBSTOR\\Disk&Ven_Creative&Prod_ZEN_Style_Series&Rev_0200"
    },

    Lang_rc = {
        'de' : {
            msg0 : "Es wurden keine Playlisten im Verzeichnis '%2' erstellt.",
            msg1 : "Folgende %1 neue Playlisten wurden im Verzeichnis '%2' erstellt:\n\n",
            msg2 : "Folgende neue Playliste wurde im Verzeichnis '%2' erstellt:\n\n",
            msg4 : "Kein Zen MX MP3-Player gefunden!",
            msg5 : "Zen MX MP3-Player in Laufwerk '%1' gefunden.\nPlaylisten konvertieren?",
            msg6 : "Unterverzeichnis '%1' auf Laufwerk '%2' nicht gefunden!",
            msg7 : "Zen MX MP3-Player gefunden, aber Unterverzeichnis '%1' fehlt!"
        },
        'en' : {
            msg0 : "No playlists created in directory '%2'.",
            msg1 : "%1 new playlists where created in directory '%2':\n\n",
            msg2 : "%1 new playlist was created in directory '%2':\n\n",
            msg4 : "No Zen MX MP3-Player found!",
            msg5 : "Found Zen MX MP3-Player in drive '%1'.\nConvert Playlists?",
            msg6 : "Subdirectory '%1' missing on drive '%2'!",
            msg7 : "Zen MX MP3-Player found, but subdirectory '%1' missing!"
        }
    },
    Lang = Lang_rc[Config.Language],
    
    objFso = new ActiveXObject("Scripting.FileSystemObject"),
    objDic = new ActiveXObject("Scripting.Dictionary"),
    C_ForReading = 1
;

// some utillity functions

function sprintf() {
var savearg = arguments;

    return savearg[0].replace(new RegExp("%(\\d+)","g"),
                function ($0, $1, $2) { return savearg[$1]; }
           );
}

function getDriveLetter(i) {
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    s;
    s = str.charAt(i);
    return(s + ":");
}

function JS2VBArray(objJSArray) {
    objDic.RemoveAll();
    for (var i = 0; i < objJSArray.length; i++ ) {
        objDic.add(i,objJSArray[i]);
    }
    return objDic.Items();
}

function getShortPath(filespec, nodrive) {
var f = objFso.GetFile(filespec),
    ret = f.ShortPath;

    if (nodrive) ret = ret.substr(2);
    return(ret);
}

function convColltoArr(col) {
var ret = new Array();

    for (var e = new Enumerator(col), i = 0; !e.atEnd(); e.moveNext(), i++) {
        ret[i] = e.item();
    }
    return ret;
}

function stripDriveLetter(fn) {
var start = fn.indexOf(":");

    return fn.slice(++start);
}

function getPath(fn) {
var stop = fn.lastIndexOf("\\");

    if (stop==-1) return "";
    return fn.slice(0,stop);
}

function getFilename(fn) {
var start = fn.lastIndexOf("\\");

    return fn.slice(++start);
}

function getFilenamePrefix(fn) {
var ret = getFilename(fn),
    stop = ret.lastIndexOf(".");

    if (stop==-1) return ret;
    return ret.slice(0,stop);
}

function getFilenameSuffix(fn) {
var ret = getFilename(fn),
    start = ret.lastIndexOf(".");

    if (start==-1) return "";
    return ret.slice(++start);
}

function messageBox(s,t,barr) {
    return SDB.MessageBox(s, t, JS2VBArray(barr));
}

// ---

function FixZenMXPlaylist() {
var fc,
    fin,
    fout,
    orgfile,
    newfile,
    newfilearr = new Array(),
    nrfiles = 0,
	bufferline,
    ret,
    devlist,
    i,
    f_org,
    f_new,
    actmsg;

    /*
     * Find the Drive letter of Zen MX
     * Well, I have no real idea what ActiveDeviceList is supposed to return. XP and W7 return complety different FriendlyNames.
     * In W7 the second Drive is never returned.
     * So this is a rather dumb method:
     *
     * Scan all Drives with correct vendor&Product Name.
     *   If you find drive with existing subdir <OutDir> use it!
     *   else give up!
     *
     * This was tested with XP / W7 successfully
     */
    if (OutDrive == "?") {
        devlist = SDB.Device.ActiveDeviceList(DeviceConfig[Config.Device]); 
        for (i = 0; i < devlist.Count;i++) {
            OutDrive = "!";
            //messageBox(i + ": (" + devlist.DeviceID(i) + ") " + devlist.FriendlyName(i) + " " +
            //    devlist.DeviceInst(i) + " " + getDriveLetter(devlist.DriveLetterIndex(i)), mtInformation, new Array(mbOk) );
            TestOutDrive = getDriveLetter(devlist.DriveLetterIndex(i));
            // if (devlist.FriendlyName(i) == "Creative ZEN MX USB Device") break;
            if (objFso.FolderExists(TestOutDrive + OutDir)) {
                OutDrive = TestOutDrive;
                break;
            }
        }
    }
    switch (OutDrive) {
        case "?":   messageBox(Lang.msg4, mtError, new Array(mbOk.toString())); // single num arg to array constructor sets array size!
                    return(-1);
        case "!":   messageBox(sprintf(Lang.msg7, OutDir), mtError, new Array(mbOk.toString()));
                    return(-1);
        default:    ret = messageBox(sprintf(Lang.msg5, OutDrive), mtConfirmation, new Array(mbOk, mbCancel));
                    if (ret == mrCancel) return (-2);
    }

    // Ok, we want this folder! Else exit
    if (!objFso.FolderExists(OutDrive + OutDir)) {
        messageBox(sprintf(Lang.msg6, OutDir, OutDrive), mtError, new Array(mbOk.toString())); // single num arg to array constructor sets array size!
        return(-1);
    }

    objDir = objFso.GetFolder(OutDrive + OutDir);

    for (fc = new Enumerator(objDir.files); !fc.atEnd(); fc.moveNext()) {
        ele = fc.item();
        if (re_inclfn.test(ele.Name) && !Config.ReExclFn.test(ele.Name)) {
            // WScript.Echo("File: " + ele.Path);

            orgfile = ele.Path;
            newfile = getPath(orgfile) + "\\" + sprintf (Config.NewPlName, getFilenamePrefix(orgfile), getFilenameSuffix(orgfile));

            // Don't generate if newfile already exists and is newer than oldfile
            if (objFso.FileExists(newfile)) {
                f_org = objFso.GetFile(orgfile);
                f_new = objFso.GetFile(newfile);
                if (f_new.DateLastModified > f_org.DateLastModified) continue;
            }

            fin = objFso.OpenTextFile(orgfile, C_ForReading, false);
            l = fin.ReadLine();
            if (!l || re_flag.test(l)) continue;    // was the file already converted? don't do it again
            bufferLine = l;                         // else buffer the first line

            fout = objFso.CreateTextFile(newfile, true);
            nrfiles++;
            newfilearr.push(getFilename(Config.ReplaceOrgPl ? orgfile : newfile));
            fout.WriteLine(sprintf(FileComment, Scriptname, Version)); // mark new file as converted
            while (!fin.AtEndOfStream) {

                if (bufferLine) {   
                    l = bufferLine;
                    bufferLine = undefined;
                } else {
                    l = fin.ReadLine();
                }

                if (!re_ignoreln.test(l)) {
                    l = stripDriveLetter(l);    // MM4 by default generates filepath with drive letters, we don't want them!
                    sn = getShortPath(OutDrive + l, true);
                    l = sn;
                }
                fout.WriteLine(l);

            }
            fin.Close();
            fout.Close();

            if (Config.DeleteOrgPl || Config.ReplaceOrgPl)    objFso.DeleteFile(orgfile, true);
            if (Config.ReplaceOrgPl)                          objFso.MoveFile(newfile, orgfile);
        }
    }
    switch (nrfiles) {
        case 0:     actmsg = 'msg0'; break
        case 1:     actmsg = 'msg2'; break
        default:    actmsg = 'msg1';
    }
    messageBox(sprintf(Lang[actmsg], nrfiles, OutDrive + OutDir) + newfilearr.join(", "),
        mtInformation, new Array(mbOk.toString())
    );
    return (0);
}

Re: Script to fix dumb Zen MX playlist format

by PawWriter » Tue Sep 20, 2011 9:19 pm

Hi there,
The "one playlist at a time" error happens only when "Force relative paths" is selected. When that option isn't selected, none of the playlists convert and it returns the same runtime error.

Blank playlist in empty directory works just fine. Converts with no errors and converted over all 51 test tracks.

Tried some of my playlists in a blank directory. None of my original playlists will convert in batches, and all of them will only do the first 7 tracks. There are two things I wonder that might be affecting this: 1) many of my playlists are AutoLists (though my regular playlists don't work either) and 2) some of my tracks have foreign languages in them.

Which config options do you need me to list? Not quite sure what you'd need to figure out if I did something weird.

Thanks for the help!

Re: Script to fix dumb Zen MX playlist format

by stoffel » Sun Sep 18, 2011 11:48 am

PawWriter wrote:Hi there,
Newest build (1433) comes back with the following error: Error #53 - File Not Found; Line 136, Column 0. Any idea what's causing it?
Thanks again!

Edit: The script will work for one playlist. Then, when I delete the original M3U off of my player and run the script again, it will do the next playlist. Repeat the process for each list I have and eventually I can get all of my playlists converted. Did I mess something up somewhere so that it won't convert multiple lists at once?

Edit 2: Only the first 7 tracks of any given playlist will convert into the new format. Strange.
Well, I tested again, found a small bug where @-files of length 0 are created even if nothing has to be done. But a can't reproduce any of your (really strange) phenomenons !
- file not found error was the main fix of this release! Should not occur any more!
- Script works for one playlist only: Can't believe :o Tested with 28!
- Only the first 7 tracks are converted: :o :o :o

Very strange!! Tested with 1426,1433 without any error! What config do you use? Try with a clean playlist dir an create a new pl via MM

Re: Script to fix dumb Zen MX playlist format

by PawWriter » Fri Sep 16, 2011 10:33 pm

Hi there,
Newest build (1433) comes back with the following error: Error #53 - File Not Found; Line 136, Column 0. Any idea what's causing it?
Thanks again!

Edit: The script will work for one playlist. Then, when I delete the original M3U off of my player and run the script again, it will do the next playlist. Repeat the process for each list I have and eventually I can get all of my playlists converted. Did I mess something up somewhere so that it won't convert multiple lists at once?

Edit 2: Only the first 7 tracks of any given playlist will convert into the new format. Strange.

Re: Script to fix dumb Zen MX playlist format

by stoffel » Thu Sep 15, 2011 4:18 pm

Ok, here's another "final" version fore MM 3/4.
Little more tested and implementing some new features.
See inline doc. Maybe you want to give:

ReplaceOrgPl : true

a try.

Have fun ;-)

Code: Select all

// Fix stupid ZEN MX Bug: Playlists must define their tracknames in 8.3 DOS style
// Convert every playlist '<name>.m3u' found in /playlist to '@ <name>.m3u' changing tracknames to 8.3 DOS style.
// By default original files are not changed
//
// (c) Stefan Skopnik (sskopnik(at)web(dot)de)
//
// 01.01.2010 fixes for W7, don't generate if newpl exists and is newer than orgpl, changed NewPlName
// 14.01.2010 scan for drive modified, test for dir exist, more detailed messages, change naming schema again to: '@ <name>.m3u'
// 08.09.2011 fixes for Zen Style 100 and MM4 (now works with MM3 and MM4)
// 12.09.2011 New Configsystem. New flags DeleteOrgPl and ReplaceOrgPl.
//            Now you can decide if you want to:
//            - delete the original pl-file after conversion (DeleteOrgPl=true) leaving only the converted @pl-file
//            - replace the old pl-file with the converted version (ReplaceOrgPl=true) preserving the original name.
//              (This may be the default in the future, Here only converted files are taken into account)
/*

Installation:
-------------

1.) Copy this file to <MediaMonkeyInstallDir>\Scripts\FixZenMXPlaylist.js
    (Windows7: This dir is write protected, you have to change this!)

2.) Append to file <MediaMonkeyInstallDir>\Scripts\scripts.ini:
< --- COPY AFTER THIS LINE --->
[FixZenMXPlaylist]
FileName=FixZenMXPlaylist.js
ProcName=FixZenMXPlaylist
Order=1
DisplayName=Fix dumb ZEN MX playlist
;DisplayName=Korrektur von ZEN MX Playlisten

Description=Fixes ZEN MX playlist by converting filepath into 8.3 DOS format
;Description=Korrektur von ZEN MX Playlisten durch konvertieren der Dateinamen/pfade in das 8.3 DOS Format
Language=JScript
ScriptType=0
<--- COPY BEFORE THIS LINE --->

3.) (Re)start MM

4.) Plugin Zen MX and create PLs in MediaMonkey

5.) Send PL to 'My ZEN'

6.) Run this Script from Extras / Scripts / Fix dumb ZEN MX playlist

7.) Unplug ZEN MX

8.) Enjoy your MM PL on ZEN MX. You find them under '@ <ORGNAME>.m3u


Configuration:
-------------

This script should work 'out of the box' with Zen MX Player using english laguage.
If you like you can configure the script in some aspects. See 'Config' for options

*/

var Config = {                              // All user changeable config settings go here
        Language     : 'en',                // Set your prefered language (Currently 'en' = English, 'de' = German is supported)
        DeleteOrgPl  : false,               // Set true if you want to delete original playlist files after conversion
        ReplaceOrgPl : false,               // Set true if you want to replace original playlist with converted version
        Device       : 'ZENMX',             // Define your player device here, see 'DeviceConfig' for possible devices (ZENMX,ZENSTYLE100)
        NewPlName    : "@ %1.%2",           // Mask for new Playlist filenames,
                                            // %1 is replaced with old filenameprefix, %2 is replaced with old filenamesuffix
        ReExclFn     : /@.*\.m3u$/          // RE for Filenames to be EXCLUDED from conversion (must match 'NewPlName')
    },
    
    re_inclfn    = /\.m3u$/,                // RE for Filenames to be INCLUDED into conversion
    re_ignoreln  = /^#/,                    // RE for lines to be ignored during conversion
    OutDrive     = "?",                     // Define your Zen MX Drive ('X:') or leave "?" to let script find device
    OutDir       = "\\Playlist",            // Define location of PL on device
    Scriptname   = "FixZenMXPlaylist.js",
    Version      = "1.04",
    FileComment  = "#!@ 8.3 DOS converted by %1 V%2",
    re_flag      = /^#!@ 8.3 DOS converted/,

    DeviceConfig = {                        // Deviceconfiguration. You have to look into the registry!
        'ZENMX'       : "USBSTOR\\Disk&Ven_Creative&Prod_ZEN_MX",
        'ZENSTYLE100' : "USBSTOR\\Disk&Ven_Creative&Prod_ZEN_Style_Series&Rev_0200"
    },

    Lang_rc = {
        'de' : {
            msg0 : "Es wurden keine Playlisten im Verzeichnis '%2' erstellt.",
            msg1 : "Folgende %1 neue Playlisten wurden im Verzeichnis '%2' erstellt:\n\n",
            msg2 : "Folgende neue Playliste wurde im Verzeichnis '%2' erstellt:\n\n",
            msg4 : "Kein Zen MX MP3-Player gefunden!",
            msg5 : "Zen MX MP3-Player in Laufwerk '%1' gefunden.\nPlaylisten konvertieren?",
            msg6 : "Unterverzeichnis '%1' auf Laufwerk '%2' nicht gefunden!",
            msg7 : "Zen MX MP3-Player gefunden, aber Unterverzeichnis '%1' fehlt!"
        },
        'en' : {
            msg0 : "No playlists created in directory '%2'.",
            msg1 : "%1 new playlists where created in directory '%2':\n\n",
            msg2 : "%1 new playlist was created in directory '%2':\n\n",
            msg4 : "No Zen MX MP3-Player found!",
            msg5 : "Found Zen MX MP3-Player in drive '%1'.\nConvert Playlists?",
            msg6 : "Subdirectory '%1' missing on drive '%2'!",
            msg7 : "Zen MX MP3-Player found, but subdirectory '%1' missing!"
        }
    },
    Lang = Lang_rc[Config.Language],
    
    objFso = new ActiveXObject("Scripting.FileSystemObject"),
    objDic = new ActiveXObject("Scripting.Dictionary"),
    C_ForReading = 1
;

// some utillity functions

function sprintf() {
var savearg = arguments;

    return savearg[0].replace(new RegExp("%(\\d+)","g"),
                function ($0, $1, $2) { return savearg[$1]; }
           );
}

function getDriveLetter(i) {
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    s;
    s = str.charAt(i);
    return(s + ":");
}

function JS2VBArray(objJSArray) {
    objDic.RemoveAll();
    for (var i = 0; i < objJSArray.length; i++ ) {
        objDic.add(i,objJSArray[i]);
    }
    return objDic.Items();
}

function getShortPath(filespec, nodrive) {
var f = objFso.GetFile(filespec),
    ret = f.ShortPath;

    if (nodrive) ret = ret.substr(2);
    return(ret);
}

function convColltoArr(col) {
var ret = new Array();

    for (var e = new Enumerator(col), i = 0; !e.atEnd(); e.moveNext(), i++) {
        ret[i] = e.item();
    }
    return ret;
}

function stripDriveLetter(fn) {
var start = fn.indexOf(":");

    return fn.slice(++start);
}

function getPath(fn) {
var stop = fn.lastIndexOf("\\");

    if (stop==-1) return "";
    return fn.slice(0,stop);
}

function getFilename(fn) {
var start = fn.lastIndexOf("\\");

    return fn.slice(++start);
}

function getFilenamePrefix(fn) {
var ret = getFilename(fn),
    stop = ret.lastIndexOf(".");

    if (stop==-1) return ret;
    return ret.slice(0,stop);
}

function getFilenameSuffix(fn) {
var ret = getFilename(fn),
    start = ret.lastIndexOf(".");

    if (start==-1) return "";
    return ret.slice(++start);
}

function messageBox(s,t,barr) {
    return SDB.MessageBox(s, t, JS2VBArray(barr));
}

// ---

function FixZenMXPlaylist() {
var fc,
    fin,
    fout,
    orgfile,
    newfile,
    newfilearr = new Array(),
    nrfiles = 0,
	bufferline,
    ret,
    devlist,
    i,
    f_org,
    f_new,
    actmsg;

    /*
     * Find the Drive letter of Zen MX
     * Well, I have no real idea what ActiveDeviceList is supposed to return. XP and W7 return complety different FriendlyNames.
     * In W7 the second Drive is never returned.
     * So this is a rather dumb method:
     *
     * Scan all Drives with correct vendor&Product Name.
     *   If you find drive with existing subdir <OutDir> use it!
     *   else give up!
     *
     * This was tested with XP / W7 successfully
     */
    if (OutDrive == "?") {
        devlist = SDB.Device.ActiveDeviceList(DeviceConfig[Config.Device]); 
        for (i = 0; i < devlist.Count;i++) {
            OutDrive = "!";
            //messageBox(i + ": (" + devlist.DeviceID(i) + ") " + devlist.FriendlyName(i) + " " +
            //    devlist.DeviceInst(i) + " " + getDriveLetter(devlist.DriveLetterIndex(i)), mtInformation, new Array(mbOk) );
            TestOutDrive = getDriveLetter(devlist.DriveLetterIndex(i));
            // if (devlist.FriendlyName(i) == "Creative ZEN MX USB Device") break;
            if (objFso.FolderExists(TestOutDrive + OutDir)) {
                OutDrive = TestOutDrive;
                break;
            }
        }
    }
    switch (OutDrive) {
        case "?":   messageBox(Lang.msg4, mtError, new Array(mbOk.toString())); // single num arg to array constructor sets array size!
                    return(-1);
        case "!":   messageBox(sprintf(Lang.msg7, OutDir), mtError, new Array(mbOk.toString()));
                    return(-1);
        default:    ret = messageBox(sprintf(Lang.msg5, OutDrive), mtConfirmation, new Array(mbOk, mbCancel));
                    if (ret == mrCancel) return (-2);
    }

    // Ok, we want this folder! Else exit
    if (!objFso.FolderExists(OutDrive + OutDir)) {
        messageBox(sprintf(Lang.msg6, OutDir, OutDrive), mtError, new Array(mbOk.toString())); // single num arg to array constructor sets array size!
        return(-1);
    }

    objDir = objFso.GetFolder(OutDrive + OutDir);

    for (fc = new Enumerator(objDir.files); !fc.atEnd(); fc.moveNext()) {
        ele = fc.item();
        if (re_inclfn.test(ele.Name) && !Config.ReExclFn.test(ele.Name)) {
            // WScript.Echo("File: " + ele.Path);

            orgfile = ele.Path;
            newfile = getPath(orgfile) + "\\" + sprintf (Config.NewPlName, getFilenamePrefix(orgfile), getFilenameSuffix(orgfile));

            // Don't generate if newfile already exists and is newer than oldfile
            if (objFso.FileExists(newfile)) {
                f_org = objFso.GetFile(orgfile);
                f_new = objFso.GetFile(newfile);
                if (f_new.DateLastModified > f_org.DateLastModified) continue;
            }

            fin = objFso.OpenTextFile(orgfile, C_ForReading, false);
            fout = objFso.CreateTextFile(newfile, true);

            l = fin.ReadLine();
            if (!l || re_flag.test(l)) continue;    // was the file already converted? don't do it again
            bufferLine = l;                         // else buffer the first line

            nrfiles++;
            newfilearr.push(getFilename(Config.ReplaceOrgPl ? orgfile : newfile));

            fout.WriteLine(sprintf(FileComment, Scriptname, Version)); // mark new file as converted
            while (!fin.AtEndOfStream) {

                if (bufferLine) {   
                    l = bufferLine;
                    bufferLine = undefined;
                } else {
                    l = fin.ReadLine();
                }

                if (!re_ignoreln.test(l)) {
                    l = stripDriveLetter(l);    // MM4 by default generates filepath with drive letters, we don't want them!
                    sn = getShortPath(OutDrive + l, true);
                    l = sn;
                }
                fout.WriteLine(l);

            }
            fin.Close();
            fout.Close();

            if (Config.DeleteOrgPl || Config.ReplaceOrgPl)    objFso.DeleteFile(orgfile, true);
            if (Config.ReplaceOrgPl)                          objFso.MoveFile(newfile, orgfile);
        }
    }
    switch (nrfiles) {
        case 0:     actmsg = 'msg0'; break
        case 1:     actmsg = 'msg2'; break
        default:    actmsg = 'msg1';
    }
    messageBox(sprintf(Lang[actmsg], nrfiles, OutDrive + OutDir) + newfilearr.join(", "),
        mtInformation, new Array(mbOk.toString())
    );
    return (0);
}

Re: Script to fix dumb Zen MX playlist format

by PawWriter » Thu Sep 08, 2011 11:58 pm

HURRAY!

Stoffel, you are truly a Java guru! For the first time since I got this player, I have editable playlists!

Thank you and thank you again!

Re: Script to fix dumb Zen MX playlist format

by stoffel » Thu Sep 08, 2011 6:22 am

A new version for MM4. No need for checking 'Enforce relative paths' anymore. Very untested!

Have fun :D

Code: Select all

// Fix stupid ZEN MX Bug: Playlists must define their tracknames in 8.3 DOS style
// Convert every playlist '<name>.m3u' found in /playlist to '@ <name>.m3u'. Original files are not changed
//
// (c) Stefan Skopnik (sskopnik(at)web(dot)de)
//
// 01.01.2010 fixes for W7, don't generate if newpl exists and is newer than orgpl, changed NewPlName
// 14.01.2010 scan for drive modified, test for dir exist, more detailed messages, change naming schema again to: '@ <name>.m3u'
// 08.09.2011 fixes for Zen Style 100 and MM4

/*
Installation:
1.) Copy this file to C:\<Program>\MediaMonkey\Scripts\FixZenMXPlaylist.js
	(Windows7: This dir is write protected, you have to change this!)

2.) Append to file C:\<Program>\MediaMonkey\Scripts\scripts.ini:
[FixZenMXPlaylist]
FileName=FixZenMXPlaylist.js
ProcName=FixZenMXPlaylist
Order=1
DisplayName=Fix dumb ZEN MX playlist
;DisplayName=Korrektur von ZEN MX Playlisten
Description=Fix dumb ZEN MX playlist
;Description=Korrektur von ZEN MX Playlisten
Language=JScript
ScriptType=0

3.) Plugin Zen MX and create PLs in MediaMonkey

4.) Send PL to 'My ZEN'

5.) Run this Script from Extras / Scripts / Fix dumb ZEN MX playlist

6.) Unplug ZEN MX

7.) Enjoy your MM PL on ZEN MX. You find them under '@ <ORGNAME>.m3u
*/

var	MyLang      = 'en',						// Define your language: 'en' = English, 'de' = German
    MyDevice    = 'ZENMX',					// Define your player device here, see DeviceConfig for possible devices (ZENMX,ZENSTYLE100)

	OutDrive    = "?",						// Define your Zen MX Drive ('X:') or leave "?" to let script find device
	OutDir      = "\\Playlist",				// Define location of PL on device
	Scriptname  = "FixZenMXPlaylist.js",
	Version     = "1.03"
	NewPlName   = "@ %1.%2",				// Mask for new Playlist filenames, %1 is replaced with old filenameprefix, %2 is replaced with old filenamesuffix
											// Don't forget to modify re_exclfn accordingly
	
	re_exclfn 	 = /@.*\.m3u$/,				// RE for Filenames to be EXCLUDED from conversion (must match NewPlName)
	
	re_inclfn 	 = /\.m3u$/,				// RE for Filenames to be INCLUDED into conversion
	re_ignoreln  = /^#/,					// RE for lines to be ignored during conversion
	
	DeviceConfig = {						// Deviceconfiguration. You have to look into the registry!
		'ZENMX'       : "USBSTOR\\Disk&Ven_Creative&Prod_ZEN_MX",
		'ZENSTYLE100' : "USBSTOR\\Disk&Ven_Creative&Prod_ZEN_Style_Series&Rev_0200"
	},
	
	objFso = new ActiveXObject("Scripting.FileSystemObject"),
	objDic = new ActiveXObject("Scripting.Dictionary"),
	C_ForReading = 1,
	Lang_rc = {
		'de' : {
			msg0 : "Keine Playliste im Verzeichnis '%2' erstellt.",
			msg1 : "Folgende %1 neue Playlisten wurden im Verzeichnis '%2' erstellt:\n\n",
			msg2 : "Folgende neue Playliste wurde im Verzeichnis '%2' erstellt:\n\n",
			msg4 : "Kein Zen MX Spieler gefunden!",
			msg5 : "Zen MX Spieler in Laufwerk '%1' gefunden.\nPlaylisten konvertieren?",
			msg6 : "Unterverzeichnis '%1' auf Laufwerk '%2' nicht gefunden!",
			msg7 : "Zen MX Spieler gefunden, aber Unterverzeichnis '%1' nicht gefunden!"
		},
		'en' : {
			msg0 : "No playlist created in directory '%2'.",
			msg1 : "%1 new playlists where created in directory '%2':\n\n",
			msg2 : "%1 new playlist was created in directory '%2':\n\n",
			msg4 : "No Zen MX Player found!",
			msg5 : "Found Zen MX Player in drive '%1'.\nConvert Playlists?",
			msg6 : "Subdirectory '%1' missing on drive '%2'!",
			msg7 : "Zen MX Player found, but subdirectory '%1' missing!"
		}
	},
	Lang = Lang_rc[MyLang];

// some utillity functions
	
function sprintf() {
var savearg = arguments;

	return savearg[0].replace(new RegExp("%(\\d+)","g"),
			    function ($0, $1, $2) { return savearg[$1]; }
		   );
}

function getDriveLetter(i) {
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
	s;
	s = str.charAt(i);
	return(s + ":");
}

function JS2VBArray(objJSArray) {
	objDic.RemoveAll();
    for (var i = 0; i < objJSArray.length; i++ ) {
        objDic.add(i,objJSArray[i]);
    }
    return objDic.Items();
}

function getShortPath(filespec, nodrive) {
var f = objFso.GetFile(filespec),
	ret = f.ShortPath;
	
	if (nodrive) ret = ret.substr(2);
	return(ret);
}

function convColltoArr(col) {
var ret = new Array();

	for (var e = new Enumerator(col), i = 0; !e.atEnd(); e.moveNext(), i++) {
		ret[i] = e.item();
	}
	return ret;
}

function stripDriveLetter(fn) {
var start = fn.indexOf(":");

	return fn.slice(++start);	
}

function getPath(fn) {
var stop = fn.lastIndexOf("\\");

	if (stop==-1) return "";
	return fn.slice(0,stop);
}

function getFilename(fn) {
var start = fn.lastIndexOf("\\");

	return fn.slice(++start);
}

function getFilenamePrefix(fn) {
var ret = getFilename(fn),
	stop = ret.lastIndexOf(".");
	
	if (stop==-1) return ret;
	return ret.slice(0,stop);
}

function getFilenameSuffix(fn) {
var ret = getFilename(fn),
	start = ret.lastIndexOf(".");
	
	if (start==-1) return "";
	return ret.slice(++start);
}

function messageBox(s,t,barr) {
	return SDB.MessageBox(s, t, JS2VBArray(barr));
}

// ---

function FixZenMXPlaylist() {
var	fc,
	fin,
	fout,
	orgfile,
	newfile,
	newfilearr = new Array(),
	nrfiles = 0,
	ret,
	devlist,
	i,
	f_org,
	f_new,
	actmsg;
	
	/*
	 * Find the Drive letter of Zen MX
	 * Well, I have no real idea what ActiveDeviceList is supposed to return. XP and W7 return complety different FriendlyNames. 
	 * In W7 the second Drive is never returned.
	 * So this is a rather dumb method:
	 * 
	 * Scan all Drives with correct vendor&Product Name.
	 * 		If you find drive with existing subdir <OutDir>  use it!
	 * 		else give up!
	 * 		
	 * This was tested with XP / W7 successfully
	 */
	if (OutDrive == "?") {
		devlist = SDB.Device.ActiveDeviceList(DeviceConfig[MyDevice]); // You have to look into the registry!
		for (i = 0; i < devlist.Count;i++) {
			OutDrive = "!";
			//messageBox(i + ": (" + devlist.DeviceID(i) + ") " + devlist.FriendlyName(i) + " " + 
			//	devlist.DeviceInst(i) + " " + getDriveLetter(devlist.DriveLetterIndex(i)), mtInformation, new Array(mbOk) );
			TestOutDrive = getDriveLetter(devlist.DriveLetterIndex(i));
			// if (devlist.FriendlyName(i) == "Creative ZEN MX USB Device") break;
			if (objFso.FolderExists(TestOutDrive + OutDir)) {
				OutDrive = TestOutDrive;
				break;
			}
		}
	}	
	switch (OutDrive) {
		case "?":	messageBox(Lang.msg4, mtError, new Array(mbOk.toString())); // single num arg to array constructor sets array size!
					return(-1);
		case "!":	messageBox(sprintf(Lang.msg7, OutDir), mtError, new Array(mbOk.toString()));
					return(-1);
		default:	ret = messageBox(sprintf(Lang.msg5, OutDrive), mtConfirmation, new Array(mbOk, mbCancel));
					if (ret == mrCancel) return (-2);
	}	
	
	// Ok, we want this folder! Else exit
	if (!objFso.FolderExists(OutDrive + OutDir)) {
		messageBox(sprintf(Lang.msg6, OutDir, OutDrive), mtError, new Array(mbOk.toString())); // single num arg to array constructor sets array size!
		return(-1);
	}	

	objDir = objFso.GetFolder(OutDrive + OutDir);

	for (fc = new Enumerator(objDir.files); !fc.atEnd(); fc.moveNext()) {
		ele = fc.item();
		if (re_inclfn.test(ele.Name) && !re_exclfn.test(ele.Name)) {
			// WScript.Echo("File: " + ele.Path);

			orgfile = ele.Path;
			newfile = getPath(orgfile) + "\\" + sprintf (NewPlName, getFilenamePrefix(orgfile), getFilenameSuffix(orgfile));
			
			// Don't generate if newfile already exists and is newer than oldfile
			if (objFso.FileExists(newfile)) {
				f_org = objFso.GetFile(orgfile);
				f_new = objFso.GetFile(newfile);
				if (f_new.DateLastModified > f_org.DateLastModified) continue;
			}
			nrfiles++;
			newfilearr.push(getFilename(newfile));
			
			fin = objFso.OpenTextFile(orgfile, C_ForReading, false);
			fout = objFso.CreateTextFile(newfile, true);

			while (!fin.AtEndOfLine) {
				l = fin.ReadLine();
				
				l = stripDriveLetter(l);
				
				if (!re_ignoreln.test(l)) {
					sn = getShortPath(OutDrive + l, true);
					l = sn;
				}
				fout.WriteLine(l);

			}
			fin.Close();
			fout.Close();
		}
	}
	switch (nrfiles) {
		case 0:		actmsg = 'msg0'; break
		case 1: 	actmsg = 'msg2'; break
		default:	actmsg = 'msg1'; 
	}	
	messageBox(sprintf(Lang[actmsg], nrfiles, OutDrive + OutDir) + newfilearr.join(", "), 
		mtInformation, new Array(mbOk.toString())
	);
	return (0);
}

Top