Workaround for Zen MX Playlist Sync Issues

Get answers about syncing MediaMonkey 4 with iPods and other devices.

Moderator: Gurus

moatmai
Posts: 16
Joined: Sat Oct 31, 2009 9:27 am

Workaround for Zen MX Playlist Sync Issues

Post by moatmai »

After seeing several people having trouble syncing their playlists with a Zen MX player, I did a bit of investigating.

Summary: The Creative Zen MX firmware contains a severe bug regarding playlist management (confirmed with both firmware 1.01.06 and 1.02.04. Creative seems to be aware of this since their own Centrale media management software contains an ugly workaround for the problem. MediaMonkey users can reproduce a similar workaround through a custom renaming scheme in the Zen MX's device profile. It's an ugly hack with certain drawbacks, though.

The file mask: This whole monster has to be pasted into the field "Sync tracks to:"

Code: Select all

\Music\$Trim($Left($Replace(<Album Artist>, ,),8))\$Trim($Left($Replace(<Album>, ,),6))$Trim($Right(<Disc#>,2))\$Trim($Left(<Track#>-$Replace(<Title>, ,),8))
In addition, you have to click on "Options..." next to "Copy playlists" and change the "Destination directory" to

Code: Select all

\Playlist\
Now for the details.

The Bug: For the most part, the Zen MX navigates through long paths and filenames without problems. Playlists, however, need to conform to the 8.3 filename limitation of the DOS stone age. The 8.3 filenames are part of the FAT32 file system, yet it's just not that simple to access them. In 8.3 notation, a path such as "\Music\Sample Artist\Sample Album\01 - Sample Track.mp3" becomes "\Music\Sample~1\Sample~1\01-Sam~1.mp3".

Spaces are omitted. "~1" etc. is used to differentiate file names starting with the same first six letters. For instance, the albums "My Favorites 2008" and "My Favorites 2009" will become "MyFavo~1" and "MyFavo~2" respectively.

Playlists for the Zen MX must use these short names, otherwise the Zen MX will not find the tracks referenced in the playlist.

An example. Creative Centrale shortens the paths:

Code: Select all

\Music\(2001) Yoshiesque Two\01 - Kings Of Tomorrow - Finally (The String Reprise).mp3
\Music\(2001) Yoshiesque Two\01 - Spiritualized - I Think I'm In Love (Chemical Brothers Vocal Remix).mp3
to:

Code: Select all

\Music\(2001)~1\01-SPI~1.MP3
\Music\(2001)~1\02-JOR~1.MP3
MediaMonkey currently offers no method of using the truncated file names for the playlists. It's not a trivial thing to implement, either: MediaMonkey would have to query the short filenames from the player before writing the playlist. That's because if the sample albums used above are transferred in the opposite order, "My Favorites 2009" will become "MyFavo~1" and "My Favorites 2008" will be "MyFavo~2" - instead of the other way around. There's no way for MediaMonkey to blindly predict the short file names on the player because they are assigned in the order the files are written to the file system.

Hence, the only solution is to violently truncate the path names during transfer to the player. This is accomplished by using the $Replace and $Trim commands. Multi-Disc set collisions are prevented by welding the disc number to the rear end of the album name. I have found no way of truncating the artist name in a way which would avoid collisions, i.e. if you have music by the groups "Techno Maniacs" and "Techno Marsupials", they'll end up in the same artist folder.

A quick rundown at what every part of the Monster Mask does:
  • \Music -> copies the audio files to the \Music\ base folder where the Zen MX expects to find its music.
  • \$Trim($Left($Replace(<Album Artist>, ,_),8)) -> shortens the Album Artist value to eight letters, replaces spaces with underscores.
  • \$Trim($Left($Replace(<Album>, ,_),5))_$Trim($Right(<Disc#>,2)) -> shortens the Disc Title to five letters, adds an underscore and the disc number as a two-digit string (if present in the ID3 tag). Again, spaces are replaced with underscores.
  • \$Trim($Left(<Track#>-$Replace(<Title>, ,_),8)) -> shortens the track's number and name to a total of eight characters, replacing spaces with underscores.
Issues: This approach has a couple of drawbacks.
  • The file names actually become truncated like this, i.e. when you access the player with a file manager such as Windows Explorer, the folder structure will be compressed in the manner described above. The ID3 tags are not touched, so you won't notice anything amiss as long as you only navigate your player via its menus or using MediaMonkey.
  • This approach cannot prevent all collisions; see the "Techno Maniacs" / "Techno Marsupials" example above. Collisions should, however, be extremely unlikely. (If the "Techno Maniacs" and "Techno Marsupials" should both publish an album called "Bleeps" and the first track of one album is called "Sinus Wave" whereas the first track of the second album is "Sinus World", one will overwrite the other.)
  • There might be problems with unicode characters. I see no way to avoid these at this point; umlauts should be fine though.
  • You need to transfer all your files and create all your playlists for the Zen MX with MediaMonkey.
Permanent solution: The MediaMonkey developers could conceivably develop a device plug-in which would check the short file names written to the device and write playlists with these file names. This way, filenames could be transferred without changes to the device (the Monster Mask wouldn't have to be applied). This would probably slow down synchronization, though. And you'd probably have to lobby very hard.

I am currently investigating whether the same problem applies to the Creative Zen X-Fi2 player. (it doesn't, see below)

Edit: Slight improvement in the "Monster Mask" :)

Edit: Bug is exclusive to the Zen MX and has indeed been fixed in Zen X-Fi2 firmware.

I just checked: The Zen X-Fi2 internally writes playlists with 8.3 paths, but it handles playlists with long path and filenames just fine. I.e. when you create a playlist on the device, it contains 8.3 paths. When you copy a playlist to the Zen X-Fi2 with long paths with MediaMonkey, the player parses it without any problems. The only adjustment you have to make is that the playlist folder on the device is called "\Playlist", not "\Playlists" (MM's default).
Last edited by moatmai on Mon Nov 16, 2009 3:33 pm, edited 2 times in total.
stoffel

Re: Workaround for Zen MX Playlist Sync Issues

Post by stoffel »

Sorry I really can't believe this!!!!!

Tonight I was trying to sync my first playlist form WinAmp / MM to my Zen MX. After described failures, I browsed WWW. It took 1 hour to find this posting stating that it was a BUG in MX firmware.

Im really depressed!
Guest

Re: Workaround for Zen MX Playlist Sync Issues

Post by Guest »

stoffel wrote:Sorry I really can't believe this!!!!!

Tonight I was trying to sync my first playlist form WinAmp / MM to my Zen MX. After described failures, I browsed WWW. It took 1 hour to find this posting stating that it was a BUG in MX firmware.

Im really depressed!
Ok, my solution: Javascript that scans all Playlists in 'Playlist' and replaces all long names with short ones using the following function:

function ShowShortName(filespec)
{
var fso, f, s;
fso = new ActiveXObject("Scripting.FileSystemObject");
f = fso.GetFile(filespec);
s = "The short name for " + "" + f.Name;
s += "" + "<br>";
s += "is: " + "" + f.ShortName + "";
return(s);
}

WScript.Echo(ShowShortName("\\Music\\A-Ha\\Foot Of The Mountain\\Foot Of The Mountain.mp3"));

it's too late now! Will do it tomorrow!
moatmai
Posts: 16
Joined: Sat Oct 31, 2009 9:27 am

Re: Workaround for Zen MX Playlist Sync Issues

Post by moatmai »

Guest wrote:Ok, my solution: Javascript that scans all Playlists in 'Playlist' and replaces all long names with short ones using the following function:
That looks really promising.

Do you think you (or someone else) can package this as a MediaMonkey script?
Guest

Re: Workaround for Zen MX Playlist Sync Issues

Post by Guest »

Guest wrote:
stoffel wrote:Sorry I really can't believe this!!!!!

Tonight I was trying to sync my first playlist form WinAmp / MM to my Zen MX. After described failures, I browsed WWW. It took 1 hour to find this posting stating that it was a BUG in MX firmware.

Im really depressed!
Ok, here we go: Copy the following script to MX root folder. Execute it via double click every time new playlists are synchronized. Thats it. Works with WinAMP too. You probably need WSH installed on your system:

// Fix stupid ZEN MX Bug: Playlists must defined their tracks in 8.3 DOS style
// Convert every playlist <name> found in /playlist to <name>_mx

var Scriptname = "FixZenMXPlaylist",
objFso = WScript.CreateObject("Scripting.FileSystemObject"),
fc,
fin,
fout,
re = /\.m3u$/,
re2 = /_mx\.m3u$/,
re3 = /^#/,
newsuff = "_mx",
nrfiles = 0,
C_ForReading = 1;

// some file utillity functions

function getShortPath(filespec)
{
var f = objFso.GetFile(filespec);
return(f.ShortPath);
}

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

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);
var stop = ret.lastIndexOf(".");
if (stop==-1) return ret;
return ret.slice(0,stop);
}

function getFilenameSuffix(fn) {
var ret = getFilename(fn);
var start = ret.lastIndexOf(".");
if (start==-1) return "";
return ret.slice(++start);
}
function genNewPlaylistname(filespec) {
return getPath(filespec) + "\\" + getFilenamePrefix(filespec) + newsuff + "." + getFilenameSuffix(filespec);
}
// ---

dir = "\\Playlist";

var Arg = convColltoArr(WScript.Arguments);
if (Arg.length) dir = Arg[0];

objDir = objFso.GetFolder(dir);

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

fin = objFso.OpenTextFile(ele.Path, C_ForReading, false);
fout = objFso.CreateTextFile(genNewPlaylistname(ele.Path), true);
while (!fin.AtEndOfLine) {
l = fin.ReadLine();
if (!re3.test(l)) {
sn = getShortPath(l);
l = sn;
}
fout.WriteLine(l);

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


}
}
WScript.Echo(Scriptname + " : " + nrfiles + " Playlists converted to short Tacknames.");
Guest

Re: Workaround for Zen MX Playlist Sync Issues

Post by Guest »

moatmai wrote:
Guest wrote:Ok, my solution: Javascript that scans all Playlists in 'Playlist' and replaces all long names with short ones using the following function:
That looks really promising.

Do you think you (or someone else) can package this as a MediaMonkey script?
Don't know about MM-Scripting. Can JScript be used ?
Guest

Re: Workaround for Zen MX Playlist Sync Issues

Post by Guest »

Guest wrote:
Guest wrote:
stoffel wrote:Sorry I really can't believe this!!!!!

Tonight I was trying to sync my first playlist form WinAmp / MM to my Zen MX. After described failures, I browsed WWW. It took 1 hour to find this posting stating that it was a BUG in MX firmware.

Im really depressed!
Ok, here we go: Copy the following script to MX root folder. Execute it via double click every time new playlists are synchronized. That's it. Works with WinAMP too. You probably need WSH installed on your system.

You must save the script under "FixZenMXPlaylist.js"
Guest

Re: Workaround for Zen MX Playlist Sync Issues

Post by Guest »

Ok, here we go: Copy the following script to MX root folder. Execute it via double click every time new playlists are synchronized. That's it. Works with WinAMP too. You probably need WSH installed on your system.

You must save the script under "FixZenMXPlaylist.js"

Sorry a little bug. Here the corrected version:

// Fix stupid ZEN MX Bug: Playlists must defined their tracks in 8.3 DOS style
// Convert every playlist <name> found in /playlist to <name>_mx

var Scriptname = "FixZenMXPlaylist.js",
objFso = WScript.CreateObject("Scripting.FileSystemObject"),
fc,
fin,
fout,
re = /\.m3u$/,
re2 = /_mx\.m3u$/,
re3 = /^#/,
newsuff = "_mx",
nrfiles = 0,
C_ForReading = 1;

// some file utillity functions

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 = e.item();
}
return ret;
}

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);
var stop = ret.lastIndexOf(".");
if (stop==-1) return ret;
return ret.slice(0,stop);
}

function getFilenameSuffix(fn) {
var ret = getFilename(fn);
var start = ret.lastIndexOf(".");
if (start==-1) return "";
return ret.slice(++start);
}
function genNewPlaylistname(filespec) {
return getPath(filespec) + "\\" + getFilenamePrefix(filespec) + newsuff + "." + getFilenameSuffix(filespec);
}
// ---

dir = "\\Playlist";

var Arg = convColltoArr(WScript.Arguments);
if (Arg.length) dir = Arg[0];

objDir = objFso.GetFolder(dir);

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

fin = objFso.OpenTextFile(ele.Path, C_ForReading, false);
fout = objFso.CreateTextFile(genNewPlaylistname(ele.Path), true);
while (!fin.AtEndOfLine) {
l = fin.ReadLine();
if (!re3.test(l)) {
sn = getShortPath(l, true);
l = sn;
}
fout.WriteLine(l);

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


}
}
WScript.Echo(Scriptname + " : " + nrfiles + " Playlists converted to short Tacknames.");
moatmai
Posts: 16
Joined: Sat Oct 31, 2009 9:27 am

Re: Workaround for Zen MX Playlist Sync Issues

Post by moatmai »

Guest wrote:
moatmai wrote:Do you think you (or someone else) can package this as a MediaMonkey script?
Don't know about MM-Scripting. Can JScript be used ?
According to the documentation, it can: http://www.mediamonkey.com/wiki/index.p ... _scripting

The Wiki holds this caveat, though:
Scripting Wiki wrote:Although, in theory, MediaMonkey supports both of the VBScript (*.vbs) and JScript (*.js) scripting languages, the implementation for JScript is only partial, so only VBScript can be used for some purposes. Programmers not wishing to deal with the idiosyncrasies of VBScript may wish to create an external script or application using their preferred language and use a script written in VBScript (or JScript) to launch it.
Launching the script from the application itself would be extremely useful. Perhaps the developers could add an option to the device synchronization plug-in to allow it to run a script after each sync?
Guest

Re: Workaround for Zen MX Playlist Sync Issues

Post by Guest »

moatmai wrote:
Guest wrote:
moatmai wrote:Do you think you (or someone else) can package this as a MediaMonkey script?
Don't know about MM-Scripting. Can JScript be used ?
According to the documentation, it can: http://www.mediamonkey.com/wiki/index.p ... _scripting

The Wiki holds this caveat, though:
Scripting Wiki wrote:Although, in theory, MediaMonkey supports both of the VBScript (*.vbs) and JScript (*.js) scripting languages, the implementation for JScript is only partial, so only VBScript can be used for some purposes. Programmers not wishing to deal with the idiosyncrasies of VBScript may wish to create an external script or application using their preferred language and use a script written in VBScript (or JScript) to launch it.
Launching the script from the application itself would be extremely useful. Perhaps the developers could add an option to the device synchronization plug-in to allow it to run a script after each sync?
Of course I could rewrite this script in VBScript (well, I hate the language) if there is any demand.
moatmai
Posts: 16
Joined: Sat Oct 31, 2009 9:27 am

Re: Workaround for Zen MX Playlist Sync Issues

Post by moatmai »

Guest wrote:Of course I could rewrite this script in VBScript (well, I hate the language) if there is any demand.
I am rather positive that there is a demand for such a script. :)

(I couldn't script my way out of a paper bag, so at least I'd be immensely grateful for a neat solution.)
Guest

Re: Workaround for Zen MX Playlist Sync Issues

Post by Guest »

moatmai wrote:
Guest wrote:Of course I could rewrite this script in VBScript (well, I hate the language) if there is any demand.
I am rather positive that there is a demand for such a script. :)

(I couldn't script my way out of a paper bag, so at least I'd be immensely grateful for a neat solution.)
Well, I don't know much about MM Automation Objects. The script must run after a playlist was synced to the device, or during the sync process itself, or on MM shutdown. Any MM Scripting guru here?
Guest

Re: Workaround for Zen MX Playlist Sync Issues

Post by Guest »

Ok, here we go again ;-)

1.) Copy FixZenMXPlaylist.js to C:\<PRG>\MediaMonkey\Scripts. Set OutDrive to your ZenMX Drive Letter !!!
2.) Edit script.ini in C:\<PRG>\MediaMonkey\Scripts. Add:

[FixZenMXPlaylist]
FileName=FixZenMXPlaylist.js
ProcName=FixZenMXPlaylist
Order=1
DisplayName=Fix dumb ZEN MX playlist
Description=Fix dumb ZEN MX playlist
Language=JScript
ScriptType=0

4.) Restart MM
3.) Run Script from Tools > Scripts submenu.

Have fun ;-)

------------------------------------------

FixZenMXPlaylist.js:

// Fix stupid ZEN MX Bug: Playlists must defined their tracks in 8.3 DOS style
// Convert every playlist <name> found in /playlist to <name>_mx

var OutDrive = "D:", // Your Drive letter here!
OutDir = "\\Playlist",
Scriptname = "FixZenMXPlaylist.js",
objFso = new ActiveXObject("Scripting.FileSystemObject"),
fc,
fin,
fout,
re = /\.m3u$/,
re2 = /_mx\.m3u$/,
re3 = /^#/,
newsuff = "_mx",
nrfiles = 0,
C_ForReading = 1;

// some utillity functions

function JS2VBArray(objJSArray) {
var dictionary = new ActiveXObject( "Scripting.Dictionary" ),
i = 0;
for ( ; i < objJSArray.length; i++ ) {
dictionary.add(i,objJSArray);
}
return dictionary.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 = e.item();
}
return ret;
}

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);
var stop = ret.lastIndexOf(".");
if (stop==-1) return ret;
return ret.slice(0,stop);
}

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

function genNewPlaylistname(filespec) {
return getPath(filespec) + "\\" + getFilenamePrefix(filespec) + newsuff + "." + getFilenameSuffix(filespec);
}
// ---

function FixZenMXPlaylist() {

objDir = objFso.GetFolder(OutDrive + OutDir);

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

fin = objFso.OpenTextFile(ele.Path, C_ForReading, false);
fout = objFso.CreateTextFile(genNewPlaylistname(ele.Path), true);
while (!fin.AtEndOfLine) {
l = fin.ReadLine();
if (!re3.test(l)) {
sn = getShortPath(OutDrive + l, true);
l = sn;
}
fout.WriteLine(l);

}
fin.Close();
fout.Close();
}
}
SDB.MessageBox(Scriptname + " : " + nrfiles + " Playlists converted to short Tacknames.", mtInformation, JS2VBArray( new Array(mbOk) ));
}
stoffel

Re: Workaround for Zen MX Playlist Sync Issues

Post by stoffel »

You can find a new improved version in:

http://www.mediamonkey.com/forum/viewto ... 19&t=44380
moatmai
Posts: 16
Joined: Sat Oct 31, 2009 9:27 am

Re: Workaround for Zen MX Playlist Sync Issues

Post by moatmai »

stoffel wrote:You can find a new improved version in:
http://www.mediamonkey.com/forum/viewto ... 19&t=44380
Great! Thank you very much.

Could you add the usage/install instructions to your post in the other thread, so people will not have to search two threads?
Post Reply