sshrum Posted June 5, 2007 Share Posted June 5, 2007 (edited) Has anyone written one? I have something I tossed together but I'm having a hard time trying to figure out how to handle relative pathnames: \..\..\..\..\..\this\is\a\path\to\a\song.mp3 Also, there is the issue of dealing with accented chars (see the code below for examples). Here is what I have which works great as long as the paths in the playlist are absolute: expandcollapse popupFunc _ImportPlaylist($sPlaylist) ConsoleWrite("Processing playlist: '" & $sPlaylist & "'" & @CRLF) $sPlaylistDrive = StringTrimRight($sPlaylist, StringLen($sPlaylist) - 2) $sPlaylistPath = StringTrimRight($sPlaylist, StringInStr($sPlaylist, "\", 0, -1)) $aPlaylist = StringSplit($sPlaylist, "\") $aPlaylistType = StringSplit($aPlaylist[$aPlaylist[0]], ".") $sPlaylistType = StringLower($aPlaylistType[$aPlaylistType[0]]) $aEntries = _ArrayCreate (0) If FileExists($sPlaylist) == 0 Then ConsoleWrite("(_ImportPlaylist) Supplied playlist file does not exist: " & $sPlaylist & @CRLF) SetError(1); file does not exist Return $aEntries EndIf $hFile = FileOpen($sPlaylist, 0) If $hFile == -1 Then ConsoleWrite("(_ImportPlaylist) Playlist file exists; but cannot open file: " & $sPlaylist & @CRLF) SetError(2); unable to open file Return $aEntries EndIf ConsoleWrite("(_ImportPlaylist) Opening playlist: " & $sPlaylist & @CRLF) Select Case $sPlaylistType = "m3u" ConsoleWrite("(_ImportPlaylist) Processing M3U file" & @CRLF) $sCommentChars = "#;" While 1 $sLine = FileReadLine($hFile) If @error = -1 Then ExitLoop $sLine = StringStripCR(StringStripWS($sLine, 3)) If StringInStr($sCommentChars, StringTrimRight($sLine, StringLen($sLine) - 1)) Then ContinueLoop If $sLine = "" Then ContinueLoop If StringLeft($sLine, 1) = "\" Then if StringLeft($sLine, 2) <> "\\" Then $sLine = $sPlaylistDrive & $sLine endif If StringLeft($sLine, 2) = ".." Then $sLine = $sPlaylistDrive & $sPlaylistPath & "\" & $sLine _ArrayAdd($aEntries, $sLine) WEnd FileClose($hFile) Case $sPlaylistType = "pls" ConsoleWrite("(_ImportPlaylist) Processing PLS file" & @CRLF) $sCommentChars = "#;" FileClose($hFile) $iEntryCount = IniRead($sPlaylist, "Playlist", "NumberOfEntries", "") If $iEntryCount = "" Then SetError(4); bad playlist Return $aEntries EndIf For $i = 1 To $iEntryCount $sLine = IniRead($sPlaylist, "Playlist", "File" & $i, "") If StringInStr($sCommentChars, StringTrimRight($sLine, StringLen($sLine) - 1)) Then ContinueLoop If $sLine = "" Then ContinueLoop If StringLeft($sLine, 1) = "\" Then if StringLeft($sLine, 2) <> "\\" Then $sLine = $sPlaylistDrive & $sLine endif If StringLeft($sLine, 2) = ".." Then $sLine = $sPlaylistDrive & $sPlaylistPath & "\" & $sLine _ArrayAdd($aEntries, $sLine) Next Case $sPlaylistType = "wpl" ConsoleWrite("(_ImportPlaylist) Processing WPL file" & @CRLF) $sCommentChars = "#;" While 1 $sLine = FileReadLine($hFile) If @error = -1 Then ExitLoop $sLine = StringStripCR(StringStripWS($sLine, 3)) If StringInStr($sCommentChars, StringTrimRight($sLine, StringLen($sLine) - 1)) Then ContinueLoop If $sLine = "" Then ContinueLoop If StringInStr($sLine, "<media") Then $sLine = StringTrimLeft($sLine, StringInStr($sLine, "src=") + 4) $sLine = StringLeft($sLine, StringInStr($sLine, '"') - 1) $sLine = StringReplace($sLine, "'", "'") $sLine = StringReplace($sLine, "&", "&") _ArrayAdd($aEntries, $sLine) EndIf WEnd FileClose($hFile) Case $sPlaylistType = "asx" ConsoleWrite("(_ImportPlaylist) Processing ASX file" & @CRLF) $sCommentChars = "#;" While 1 $sLine = FileReadLine($hFile) If @error = -1 Then ExitLoop $sLine = StringStripCR(StringStripWS($sLine, 3)) If StringInStr($sCommentChars, StringTrimRight($sLine, StringLen($sLine) - 1)) Then ContinueLoop If $sLine = "" Then ContinueLoop If StringInStr($sLine, "SourceURL") Then $sLine = StringTrimLeft($sLine, StringInStr($sLine, "value")) $sLine = StringTrimLeft($sLine, StringInStr($sLine, '"')) $sLine = StringLeft($sLine, StringInStr($sLine, '"') - 1) _ArrayAdd($aEntries, $sLine) EndIf WEnd FileClose($hFile) Case $sPlaylistType = "xml" ConsoleWrite("(_ImportPlaylist) Processing XML file" & @CRLF) $sCommentChars = "#;" While 1 $sLine = FileReadLine($hFile) If @error = -1 Then ExitLoop $sLine = StringStripCR(StringStripWS($sLine, 3)) If StringInStr($sCommentChars, StringTrimRight($sLine, StringLen($sLine) - 1)) Then ContinueLoop If $sLine = "" Then ContinueLoop If StringInStr($sLine, "<key>Location") Then $sLine = StringTrimLeft($sLine, StringInStr($sLine, "<string>") + 7) $sLine = StringLeft($sLine, StringInStr($sLine, "</string>") - 1) If StringInStr($sLine, "file://localhost/") Then $sLine = StringTrimLeft($sLine, 17) $sLine = StringReplace($sLine, "'", "'") $sLine = StringReplace($sLine, "/", "\") $sLine = StringReplace($sLine, "%20", " ") $sLine = StringReplace($sLine, "&", "&") $sLine = StringReplace($sLine, "&", "&") _ArrayAdd($aEntries, $sLine) EndIf WEnd FileClose($hFile) Case Else ConsoleWrite("(_ImportPlaylist) Playlist file type unsupported: " & $sPlaylistType & @CRLF) SetError(3); unknown playlist type EndSelect $aEntries[0] = ubound($aEntries) - 1 ConsoleWrite("(_ImportPlaylist) Playlist entries extracted: " & $aEntries[0] & @CRLF) Return $aEntries EndFunc Any help would be great. TIA. Edited June 5, 2007 by sshrum Sean Shrum :: http://www.shrum.net All my published AU3-based apps and utilities 'Make it idiot-proof, and someone will make a better idiot' Link to comment Share on other sites More sharing options...
lod3n Posted June 6, 2007 Share Posted June 6, 2007 So, you're trying to read playlist files into an array? Why not just do a directory listing, and skip the playlists all together? [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
sshrum Posted June 6, 2007 Author Share Posted June 6, 2007 So, you're trying to read playlist files into an array? Why not just do a directory listing, and skip the playlists all together?My project already supports dir-based and dir+subdir-based calls. But when you have close to 30,000 files, play lists are a necessity. I'm also currently working on a meta tag filter function that will allow one to do cumulative AND comparisons of 'is', 'is not', and 'contains' type filtering on any of the meta tag results (working on the GUI right now). Think: 'Artist' [is] 'Celine Dion' AND 'WM/Genre' [is not] 'Christmas' AND 'Album' [contains] 'Mountians'. The filter writeup I can do. I just want to find out if someone has tackled the play list import as that seemed like a more common topic. I can do the playlist import too, but it's just more time I have to spend debugging. Sean Shrum :: http://www.shrum.net All my published AU3-based apps and utilities 'Make it idiot-proof, and someone will make a better idiot' Link to comment Share on other sites More sharing options...
lod3n Posted June 6, 2007 Share Posted June 6, 2007 I don't know about the relative path names. Relative to what? Can you post a sample? You can't have a relative reference without also having the parent information somehow available to correlate against. Also, I'd suggest you load these playlists into a SQL Lite DB. It's already good at doing what you're talking about with the AND and OR and IS NOT stuff. [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
sshrum Posted June 6, 2007 Author Share Posted June 6, 2007 (edited) I don't know about the relative path names. Relative to what? Can you post a sample? You can't have a relative reference without also having the parent information somehow available to correlate against.This is the problem with how WMP generates playlists. If a playlist is stored in 'c:\foo\bar\playlist.wpl', and the song file is in 'c:\this\that\other\Oingo Boingo-Goodbye, Goodbye.mp3', the play list entry is typically written as: '\..\..\this\that\other\Oingo Boingo-Goodbye, Goodbye.mp3'. The location of the playlist is the starting point...but what happens when the playlist is MOVED!?!?! The file now contains invalid references. For those cases, the file is just bad at that point and there is nothing anyone can do to *quickly* get things moving.Now I'm not sure (haven't tried but assume) that playlists that are stored in another drive letter (say, drive P:) then the content they reference will be written with a fully qualified URL: 'n:\public\media\music\Oingo Boingo-Goodbye, Goodbye.mp3'I just wish that they would always use a full URL in the playlists.Also, I'd suggest you load these playlists into a SQL Lite DB. It's already good at doing what you're talking about with the AND and OR and IS NOT stuff.Databases?....Databases?...We don't need no stinking databases!!!Aw, dewd, you just LOST geek points with me. The filter I'm doing is pretty simplistic and I can write a func to handle that. Besides, I want to stay away for too many things getting into the fray. Edited June 6, 2007 by sshrum Sean Shrum :: http://www.shrum.net All my published AU3-based apps and utilities 'Make it idiot-proof, and someone will make a better idiot' Link to comment Share on other sites More sharing options...
lod3n Posted June 7, 2007 Share Posted June 7, 2007 So, what, you're going to store 30,000 records, including full file paths, potentially multiple playlist tags, genre, artist, rating and album information in a multidimensional array? Listen, I once vehemently deplored anything resembling a "database" as you appear to, but experience has taught me that they definitely have their place. And this is one of them. TRUST ME. I transitioned out of doing things the way you are describing, and it has saved me SO MUCH development time. I'm sure that whatever time it takes you to get up to speed on SQL will be far less than what will be required for the behemoth you are preparing to write. Honestly, once your data is loaded into the DB, your end of the code looks something like this: $recordset = query("select * from songs where (Artist = 'Celine Dion') AND (Genre != 'Christmas') AND Album like '%Mountians%') for $i = 1 to $recordset.length write($recordset[$i].filepath) next I'm not kidding. Like 4 lines of code. It's worth learning how to do this. Explain how any other way is faster or easier: I'd love to be wrong on this. Oh, and if your database is persistent, meaning you don't recreate it each time you start, you don't need playlists anymore. It can contain all the information and functionality that the playlists were providing. Regarding the relative paths, if you know the playlist is on C:\, and the "\..\..\.." always resolves to C:\ then just do this: If instr($sLine,"\..) then $sLine = stringReplace($sLine,"\..","") $sLine = "C:\" & $sLine endif However, if the entry is something like "\..\Songs\Dir\file.mp3" then take the playlist filename, stringSplit it by "\" into an array, do the same for the relative link, count the number of ".." entries, and count that far back in the playlist filename array, and you have path's starting point. Easy peasy. [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
sshrum Posted June 7, 2007 Author Share Posted June 7, 2007 I'm just storing the filenames in an array, $aFiles. After I WMOPENFILE, I'm querying via WMGet(). The filter is easy enuff....a 'stringinstr()' [contains], a '==' [is], and a '<>' [is not] does the trick. Not the fastest thing to do but it works well enough. Granted, when the filter is restrictive, there are periods of silence between songs as my util loops to find a song that passes. It beats trying to query 30,000 records each time and is fast enough that the user (me) doesn't notice the processing time. Sean Shrum :: http://www.shrum.net All my published AU3-based apps and utilities 'Make it idiot-proof, and someone will make a better idiot' Link to comment Share on other sites More sharing options...
lod3n Posted June 7, 2007 Share Posted June 7, 2007 (edited) Hey, take a look though this, it's really interesting and could help you: http://www.microsoft.com/technet/scriptcen...one/player.mspx Set objPlayer = CreateObject("WMPlayer.OCX" ) Set objMediaCollection = objPlayer.MediaCollection Set colSongList = objMediaCollection.getByAuthor("Dire Straits") For i = 0 to colSongList.Count - 1 Set objSong = colSongList.Item(i) Wscript.Echo objSong.Name Next Edited June 7, 2007 by lod3n [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now