The Ultimate Home Jukebox
by Charlie Munro and Mark Nelson

Figure 3: Contents of "Radiohead - The Bends.m3u"

\\mark\d\My Music\Radiohead\The Bends\1_Planet Telex.mp3
\\mark\d\My Music\Radiohead\The Bends\2_The Bends.mp3
\\mark\d\My Music\Radiohead\The Bends\3_High And Dry.mp3
\\mark\d\My Music\Radiohead\The Bends\4_Fake Plastic Trees.mp3
\\mark\d\My Music\Radiohead\The Bends\5_Bones.mp3
\\mark\d\My Music\Radiohead\The Bends\6_(Nice Dream).mp3
\\mark\d\My Music\Radiohead\The Bends\7_Just.mp3
\\mark\d\My Music\Radiohead\The Bends\8_My Iron Lung.mp3
\\mark\d\My Music\Radiohead\The Bends\9_Bullet Proof..I Wish I Was.mp3
\\mark\d\My Music\Radiohead\The Bends\10_Black Star.mp3
\\mark\d\My Music\Radiohead\The Bends\11_Sulk.mp3
\\mark\d\My Music\Radiohead\The Bends\12_Street Spirit (Fade Out).mp3

Example 1:

idx = fileName.indexOf(" - ");    // find the delimiter separating artist 
title = fileName.substring(idx + 3, fileName.length - 4);
title = jTrim(title);
    
href = rootPath + pathSeparator + Server.URLPathEncode(fileName);
Response.Write("<DD><A HREF=\"" + href + "\">" + title + "</A></DD>\n");


Listing One
<%@ LANGUAGE=JavaScript %>
<%
// Script to generate an alphabetical listing of files with links to 
// each file done in JavaScript to take advantage of the built-in 
// sorting capability for JavaScript arrays

var m3uRoot = "/Playlists";  // Virtual directory for M3U files
var lastArtist = " ";        // used to check for unique artist names
var thisLetter = "";         // current letter for index and listing

var artist;                  // current artist's name from file name
var title;                   // current album title from file name
var href;                    // complete path to M3U file

// get a listing of playlist files in the specified folder
var fileList = GetFileList(m3uRoot);

// sort the file list (in ASCII order, so A-Z is before a-z!)
fileList = fileList.sort();

// get the number of playlist files to show a count in the page title
var fileCount = fileList.length;

// get the first letter of the first file - we'll need this to know
// when we're at the top of the listing
var firstLetter = fileList[0].charAt(0);

// find out which browser is being used to view the page so that we 
// can write the URLs correctly
var browser = Request.ServerVariables("HTTP_USER_AGENT").Item
var isIE = (browser.indexOf("MSIE") != -1)

// - - - start of the HTML document - - - %>
<HTML>
<HEAD>
<META NAME="GENERATOR" CONTENT="Microsoft Visual Studio 6.0">
<!-- using one of the themes that comes with VInterDev 6.0 -->
<LINK REL="stylesheet" TYPE="text/css" HREF="THEME.CSS">
<LINK REL="stylesheet" TYPE="text/css" HREF="GRAPH0.CSS">
<LINK REL="stylesheet" TYPE="text/css" HREF="COLOR0.CSS">
<LINK REL="stylesheet" TYPE="text/css" HREF="CUSTOM.CSS">
<TITLE>The M3U Project</TITLE>
</HEAD>
<BODY>
<H1>The M3U Project</H1>
<H2><%= fileCount %> Titles for Your Enjoyment<BR>
 <SMALL>(listed by artist and albums)</SMALL></H2>
<%
Response.Write("<P><FONT FACE=\"Georgia,Times New Roman,Times\">");
// loop through files to get a list of first characters, and generate 
// links to headings
for (var i = 0; i < fileList.length; i++)
{
  fileName = fileList[i];
  if (fileName.charAt(0) != thisLetter) {
    thisLetter = fileName.charAt(0);
    Response.Write("<A HREF=\"#" + thisLetter + "\">" + thisLetter 
                  + "</A>\n");
  }
}
Response.Write("</FONT></P>\n")

for (i = 0; i < fileList.length; i++)
{
  fileName = fileList[i];
  
  // find the delimiter separating artist and album title
  idx = fileName.indexOf(" - ");                  
  if (idx != -1)
  {
    // get the artist name with leading and trailing spaces removed
    artist = jTrim(fileName.substring(0, idx));   
    if (artist != lastArtist)
    {
      // for each new artist, check to see if a new first character
      // is present, and start a new section if needed.
      if (artist.charAt(0) != lastArtist.charAt(0))
        doNextLetter(artist.charAt(0));
      Response.Write("<DT><B>" + artist + "</B></DT>\n");
      lastArtist = artist;
    }
    title = fileName.substring(idx + 3, fileName.length - 4);
    title = jTrim(title);
    
    href = m3uRoot + "/" + fileName;
    if (!isIE) jReplace(fileName, " ", "%20", 1, -1, 1);
    Response.Write("<DD><A HREF=\"" + href + "\">" + title 
                   + "</A></DD>\n");
  }
}
%>
</DL><A HREF="default.asp#top">back to top</A></BLOCKQUOTE>
</BODY>
</HTML>
<SCRIPT LANGUAGE="javascript" RUNAT="server">
//
// function doNextLetter - closes the current list and starts the
// next list with the letter heading as an anchor
function doNextLetter(nextLetter)
{
  var c = nextLetter.toUpperCase();
  var lc = (c.toLowerCase() == c) ? "" : c.toLowerCase();
    
  // close the previous section if not at top of page
  if (nextLetter != firstLetter)
    Response.Write("</DL><A HREF=\"#top\">back to top</A>" 
                   + "</BLOCKQUOTE>\n");
  // start the next section
  Response.Write("<H3><A NAME=\"" + c + "\">" + c + lc + "</A></H3>\n"
                 + "<BLOCKQUOTE><DL>\n");
}
function GetFileList(vRoot)
{
  var folderName = Server.MapPath(vRoot);
  var avarFileList = new Array();
  var fileCount = 0;
  var f;
  
  // Use ASP's FileSystemObject to get list of files in the playlist folder
  var objFS = Server.CreateObject("Scripting.FileSystemObject");
  var objSourceFolder = objFS.GetFolder(folderName);

  // since we want to acces the Files collection from the folder
  // object, we use the JScript Enumerator object to hold the files
  var objFiles = new Enumerator(objSourceFolder.Files);   

  // Using the files collection, create an array for list of playlist files.
  for (; !objFiles.atEnd(); objFiles.moveNext())
  {
    // Since we need the format of the playlist file name to have the 
    // artist and album title separated with a space-dash-space 
    // combination, we'll use that to filter out unwanted files 
    // (in addition to looking for the .m3u extension)
    
    f = objFiles.item();  // gets the current file

    if ((f.name.indexOf(" - ") != -1) && 
        (f.name.lastIndexOf(".m3u") == f.name.length - 4))
    {
      // put the file name in the list (array)
      avarFileList[fileCount] = f.name;
      fileCount++;
    }
  }
  return avarFileList;
}
</SCRIPT>
<SCRIPT LANGUAGE="vbscript" RUNAT="server">
'// It's easier to do a Trim in VBScript, so just create a wrapper for
'// calling it in JavaScript
Function jTrim(strTemp)
  If strTemp = "" Or strTemp = Null Then
    jTrim = ""
  Else
    jTrim = Trim(strTemp)
  End If

End Function

'// It's easier to do the replace with VB than working with JScript's regular
'// expressions, so again, use VBScript to create a wrapper for Replace method
Function jReplace(sSource, sFind, sReplace, iStart, iCount, iCompare)

jReplace = Replace(sSource, sFind, sReplace, iStart, iCount, iCompare)

End Function

</SCRIPT>




4


