'========================================================================== ' ' MediaMonkey Script ' ' NAME: TopTracks ' DESCRIPTION: Enqueue artist tracks based on last fm charts ' AUTHOR: Teknojnky/RedX ' Maintained by RedX ' Some code courtesy of psyXonova, thanks! ' ' INSTALL: ' - Copy script to MM directory scripts\auto ' ' TODO: ' - check for existing duplicate tracks in now playing' ' LATEST CHANGES: ' 1.10d - 20071006 ' * #### Last version compatible with MM2 #### ' * added missing % escape char to fixurl ' 1.10c - 20070928 ' * added . to allowed chars in url allowing for correct data retrieval from last.fm ' 1.10b ' * error in SortPlaylist fixed ' 1.10 ' * toptracks ordered now really returns the top tracks :-) ' 1.09 ' * Fixed Shuffle button ' 1.08 ' * now shows hides buttons w/o restarting MM ' * added option to try not to use albums with certain keywords ' 1.07 ' * added option to choose which buttons to show ' 1.06 ' *replaced URLencode with improved version by Trixmoto (fixurl) ' 1.05 ' * supports multiple artists selection ' 1.04 ' * updated + substitution with better solution ' 1.03b ' * Fixed problems with [ and ] in sql statement ' 1.03 ' * Added option panel for comfort setup ' * Added another button to toolbar for easy selection between shuffle and normal ' * Added status bar ' * started working on future auto enqueue ' * Added two custoim icons ' 1.02 ' * handles artist with + in their name (thx Trixmoto) ' 1.01 ' * function URLEncode() added to better handle artist names for last.fm ' * Some logging changes/tweaks ' 1.0 ' * separated logging and debug, this allows you to continue to log even if ' debug pop up's are disabled ' * Removed max counts from get top tracks, and match top tracks functions. ' This allows the full set of last.fm tracks to be added, queried, matched to ' the library instead of being limited to the max tracks. ' * added a final "EnqueueTracks" loop to create the final list of tracks with ' the max of MaxTracks. ' This allows this the shuffle function to generate a wider variety ' (based on the larger last.fm list) while still being able to restrict the ' final result to a smaller subset. ' It's working very well for me thus far. ' ------------------------------------------------------------------------ ' I'd like very much to thank RedX for his help, and Trixmoto for initial query info. ' I also want to thank psyXonova for his permission to use some bits of code from scrobblerdj! ' ' I consider this to be basically functionally complete, however there are ' still a few things on the TODO list I may address in the future. '========================================================================== ' Option Explicit Randomize Timer Const iTT = "TT.ico" Const iTTshuffle = "TTshuffle.ico" Const ForReading = 1, ForWriting = 2, ForAppending = 8 'Needed for toptracks toolbar buttons Dim Debug, Shuffle, MaxTracks, StatusBar, Logging, Bar,BarText,MinQueue Dim showTBB,showTBS Dim ObjTBB,ObjTBS Dim Timeout,WarningTimeout Dim xmlDoc,xmlUrl Dim AvoidWords : AvoidWords= Split("") 'Default settings for enqueued Timeout=15 'seconds Timeout = Timeout*2 WarningTimeOut = True 'Messgebox on timeout 'Default setup for Toptracks buttons Debug = False 'pop up message boxes' Logging = True 'log file on/off' Shuffle = True 'True to shuffle the list, False for popularity' MaxTracks = 5 'max tracks to enqueue' StatusBar = true 'show status progress bar' showTBB= True showTBS = True logme "" logme "############" '---------------- Add buttons and set options pane -------------- Sub OnStartUp logme ">>OnStartUp" Dim ini: Set ini = sdb.IniFile If ini.StringValue("TopTracks","Debug") = "" Then ini.StringValue("TopTracks","Debug") = Debug End If If ini.StringValue("TopTracks","Logging") = "" Then ini.StringValue("TopTracks","Logging") = Logging End If If ini.StringValue("TopTracks","StatusBar") = "" Then ini.StringValue("TopTracks","StatusBar") = StatusBar End If If ini.StringValue("TopTracks","MaxTracks") = "" Then ini.StringValue("TopTracks","MaxTracks") = MaxTracks End If 'If ini.StringValue("TopTracks","Shuffle") = "" Then ' ini.StringValue("TopTracks","Shuffle") = Shuffle 'End If If ini.StringValue("TopTracks","showTBB") = "" Then ini.stringvalue("TopTracks","showTBB") = 1 End If If ini.StringValue("TopTracks","showTBS") = "" Then ini.stringvalue("TopTracks","showTBS") = 1 End If If ini.StringValue("TopTracks","AvoidWords") = "" Then ini.stringvalue("TopTracks","AvoidWords") = Join(AvoidWords,";") End If showTBS=ini.intValue("TopTracks","showTBS") showTBB=ini.intValue("TopTracks","showTBB") 'Add toolbar buttons logme " Adding ToolBar Buttons" Set ObjTBB = sdb.objects("TBB") If ObjTBB Is Nothing Then Dim TT : TT = SDB.RegisterIcon("Scripts\Auto\"&iTT,0) ini.StringValue("TopTracks","TT") = TT Set ObjTBb = SDB.UI.AddMenuItem(SDB.UI.Menu_TBStandard,0,0) objtbb.Caption = SDB.Localize("Top Artist Tracks from Last.FM") ObjTBB.OnClickFunc = "TopTracksOrder" objtbb.UseScript = Script.ScriptPath If FileExists(iTT) Then objtbb.IconIndex = TT Else objtbb.IconIndex = 14 End If If CBool(showTBB) = True Then ObjTBB.visible = True Else ObjTBB.visible = False End If Set SDB.objects("TBB") = ObjTBB Else logme("nothing TBB") End If Set ObjTBS = sdb.objects("TBS") If objtbs Is Nothing Then Dim TTshuffle : TTshuffle = SDB.RegisterIcon("Scripts\Auto\"&iTTshuffle,0) ini.StringValue("TopTracks","TTshuffle") = TTshuffle Set objtbs = SDB.UI.AddMenuItem(SDB.UI.Menu_TBStandard,0,0) objtbs.Caption = SDB.Localize("Top Artist Tracks from Last.FM (shuffled)") objtbs.OnClickFunc = "TopTracksShuffle" objtbs.UseScript = Script.ScriptPath If FileExists(iTT) Then objtbs.IconIndex = TTshuffle else objtbs.IconIndex = 14 End If If CBool(showTBS) = True Then objtbs.visible = True Else objtbs.visible = False End If Set SDB.objects("TBS") = ObjTBS Else logme("nothing TBS") End If logme " adding option pane" Dim index : index = SDB.UI.AddOptionSheet("TopTracks Settings", Script.ScriptPath, "InitSheet", "SaveSheet", -2) 'logme " Registering events" 'Script.RegisterEvent SDB, "OnPlay", "AutoTopTracks" logme "<>InitSheet" Dim ini:Set ini = sdb.IniFile 'Shuffle = ini.IntValue("TopTracks","Shuffle") Debug = ini.IntValue("TopTracks","Debug") logging= ini.IntValue("TopTracks","Logging") MaxTracks= ini.StringValue("TopTracks","MaxTracks") minqueue= ini.StringValue("TopTracks","MinQueue") StatusBar = ini.IntValue("TopTracks","StatusBar") showTBS=ini.intValue("TopTracks","showTBS") showTBb=ini.intValue("TopTracks","showTBB") AvoidWords = Split(ini.StringValue("TopTracks","AvoidWords"),";") 'Dim ui : Set ui = SDB.UI Dim Label1 : Set Label1 = SDB.UI.NewLabel(Sheet) Label1.Caption = "Number of tracks to enqueue:" Label1.Common.ControlName = "TTlbl" Label1.Common.SetRect 5,20,150,17 Label1.Common.Anchors = 6 Label1.Common.Hint = "If possible this is the max amount of songs that will be enqueued" Set Label1 = Nothing Dim Edit1 : Set Edit1 = SDB.UI.NewEdit(Sheet) Edit1.Text = MaxTracks Edit1.Common.ControlName = "TTmaxTracks" Edit1.Common.SetRect 160,15,50,21 Edit1.Common.Anchors = 6 Set Edit1 = Nothing Set Label1 = SDB.UI.NewLabel(Sheet) Label1.Caption = "Avoid album with these words:" Label1.Common.ControlName = "TTlbl2" Label1.Common.SetRect 5,55,150,17 Label1.Common.Anchors = 6 Label1.Common.Hint = "Only use songs from albums that do not contain these words if possible." Set Label1 = Nothing Set Label1 = SDB.UI.NewLabel(Sheet) Label1.Caption = "; separated list" Label1.Common.ControlName = "TTlbl3" Label1.Common.SetRect 370,55,150,17 Label1.Common.Anchors = 6 Set Label1 = Nothing Set Edit1 = SDB.UI.NewEdit(Sheet) Edit1.Text = Join(AvoidWords,";") Edit1.Common.ControlName = "TTAW" Edit1.Common.SetRect 160,50,200,21 Edit1.Common.Anchors = 6 'Dim CheckBox1 : Set CheckBox1 = SDB.UI.NewCheckBox(Sheet) 'CheckBox1.Caption="Shuffle results" 'CheckBox1.Common.ControlName = "TTshuffle" 'CheckBox1.Common.SetRect 158,39,121,21 'CheckBox1.checked = Shuffle Dim CheckBox1 : Set CheckBox1 = SDB.UI.NewCheckBox(Sheet) CheckBox1.Caption = "Show Toptracks button" CheckBox1.Common.ControlName = "TTB" CheckBox1.Common.SetRect 8,105,150,20 CheckBox1.checked = showTBB Dim CheckBox2 : Set CheckBox2 = SDB.UI.NewCheckBox(Sheet) CheckBox2.Caption = "Show Toptracks button shuffled" CheckBox2.Common.ControlName = "TTBS" CheckBox2.Common.SetRect 8,131,170,20 CheckBox2.checked = showTBS Dim CheckBox3 : Set CheckBox3 = SDB.UI.NewCheckBox(Sheet) CheckBox3.Caption = "Show status bar" CheckBox3.Common.ControlName = "TTstatusbar" CheckBox3.Common.SetRect 8,210,98,20 CheckBox3.checked = StatusBar Dim CheckBox4 : Set CheckBox4 = SDB.UI.NewCheckBox(Sheet) CheckBox4.Caption = "Log Debug to file" CheckBox4.Common.ControlName = "TTlogging" CheckBox4.Checked = Logging CheckBox4.Common.SetRect 8,184,115,20 Dim CheckBox5 : Set CheckBox5 = SDB.UI.NewCheckBox(Sheet) CheckBox5.Caption = "Show Debug Messageboxes" CheckBox5.Common.ControlName = "TTDebug" CheckBox5.Common.SetRect 8,158,160,20 CheckBox5.checked=Debug logme"<>SaveSheet" Dim ini : Set ini = SDB.IniFile ini.StringValue("TopTracks","MaxTracks") = Sheet.Common.ChildControl("TTmaxTracks").Text ini.StringValue("TopTracks","AvoidWords") = Sheet.Common.ChildControl("TTAW").Text 'If Sheet.Common.ChildControl("TTshuffle").checked Then ' ini.IntValue("TopTracks","Shuffle") = 1 'Else ' ini.IntValue("TopTracks","Shuffle") = 0 'End If If Sheet.Common.ChildControl("TTdebug").Checked Then ini.IntValue("TopTracks","Debug") = 1 Else ini.IntValue("TopTracks","Debug") = 0 End If If Sheet.Common.ChildControl("TTlogging").Checked Then ini.IntValue("TopTracks","Logging") = 1 Else ini.IntValue("TopTracks","Logging") = 0 End If If Sheet.Common.ChildControl("TTstatusbar").Checked Then ini.IntValue("TopTracks","StatusBar") = 1 Else ini.IntValue("TopTracks","StatusBar") = 0 End If If Sheet.Common.ChildControl("TTBS").Checked Then ini.IntValue("TopTracks","showTBS") = 1 Set ObjTBS = sdb.objects("TBS") If objtbs Is Nothing Then Dim TTshuffle : TTshuffle = SDB.RegisterIcon("Scripts\Auto\"&iTTshuffle,0) ini.StringValue("TopTracks","TTshuffle") = TTshuffle Set objtbs = SDB.UI.AddMenuItem(SDB.UI.Menu_TBStandard,0,0) objtbs.Caption = SDB.Localize("Top Artist Tracks from Last.FM (shuffled)") objtbs.OnClickFunc = "TopTracksShuffle" objtbs.UseScript = Script.ScriptPath If FileExists(iTT) Then objtbs.IconIndex = TTshuffle Else objtbs.IconIndex = 14 End If If CBool(showTBS) = True Then objtbs.visible = True Else objtbs.visible = False End If Set SDB.objects("TBS") = ObjTBS Else objtbs.visible = true End If Else ini.IntValue("TopTracks","showTBS") = 0 Set ObjTBS = sdb.objects("TBS") If not ObjTBS Is Nothing Then objtbS.visible = false end if End If If Sheet.Common.ChildControl("TTB").Checked Then ini.IntValue("TopTracks","showTBB") = 1 Set ObjTBB = sdb.objects("TBB") If ObjTBB Is Nothing Then Dim TT : TT = SDB.RegisterIcon("Scripts\Auto\"&iTT,0) ini.StringValue("TopTracks","TT") = TT Set ObjTBb = SDB.UI.AddMenuItem(SDB.UI.Menu_TBStandard,0,0) objtbb.Caption = SDB.Localize("Top Artist Tracks from Last.FM") ObjTBB.OnClickFunc = "TopTracksOrder" objtbb.UseScript = Script.ScriptPath If FileExists(iTT) Then objtbb.IconIndex = TT Else objtbb.IconIndex = 14 End If If CBool(showTBB) = True Then ObjTBB.visible = True Else ObjTBB.visible = False End If Set SDB.objects("TBB") = ObjTBB Else ObjTBB.visible = True End If Else ini.IntValue("TopTracks","showTBB") = 0 Set ObjTBB = sdb.objects("TBB") If not ObjTBB Is Nothing Then objtbb.visible = false end if End If logme"<>TopTracks" Dim ini:Set ini = sdb.IniFile 'Shuffle = ini.IntValue("TopTracks","Shuffle") Debug = ini.IntValue("TopTracks","Debug") logging= ini.IntValue("TopTracks","Logging") MaxTracks= ini.StringValue("TopTracks","MaxTracks") minqueue= ini.StringValue("TopTracks","MinQueue") StatusBar = ini.IntValue("TopTracks","StatusBar") AvoidWords = Split(ini.StringValue("TopTracks","AvoidWords"),";") logme " Shuffle: " & Shuffle logme " MaxTracks: " & MaxTracks logme " Statusbar: " & Statusbar logme " Debug: " & Debug logme " minQueue: " & MinQueue logme " AvoidWords: " & Join(AvoidWords,";") Dim Artist, Selected, NowPlaying, Song, TopTracksList, MatchedTracks , TopTracksListTotal Dim EnqueueTracks, temppl,i,j,artistlst Set EnqueueTracks = SDB.NewSongList Set artistlst = New DynamicArray Set TopTracksListTotal = CreateObject("scripting.dictionary") If StatusBar Then Set bar = sdb.Progress Bar.MaxValue = 100 Bar.Value = 100 logme " StatusBar enabled!" Else logme " StatusBar disabled!" End if 'find the artist of current song or current selection' Set Selected = SDB.CurrentSongList Set NowPlaying = SDB.Player.CurrentSong If Selected.Count > 0 Then Set Song = Selected 'Artist = Song.ArtistName For i = 0 To Selected.count-1 artistlst.Data(i) = Selected.item(i).artistname Next Else 'Artist = NowPlaying.ArtistName artistlst.Data(0)= NowPlaying.artistname End If If Debug Then msgbox ("Selected Artist: " & Artist) 'show me current artist' If StatusBar Then bartext= "Selected Artist: " & Artist : bar.text = BarText 'find the artist on last.fm and return the dictionary of selected list of tracks' If StatusBar Then BarText= "Getting TopTracks from Last.fm" : bar.text = BarText Set MatchedTracks = sdb.newsonglist Dim alreadyinlist:Set alreadyinlist = New DynamicArray 'let's get for all artists logme " artistinlist count:"& artistlst.Count For i=0 To artistlst.Count-1 If alreadyinlist.Count = 0 Then MsgBox "alreadyinlist.Count"&alreadyinlist.Count alreadyinlist.Add 0,artistlst.Data(i) End If If Not alreadyinlist.Exists(artistlst.Data(i)) Then alreadyinlist.Data(alreadyinlist.Count)=artistlst.Data(i) If StatusBar Then BarText="Getting Data from Last.fm" : bar.text = BarText Set TopTracksList = GetTopTracks(artistlst.Data(i)) If Not TopTracksList is Nothing Then 'join for later sorting Set TopTracksListTotal = JoinDict(TopTracksListTotal,TopTracksList) If StatusBar Then BarText="Matching to local library" : bar.text = BarText 'process list and make a playlist of it' Set temppl = MatchTopTracks(artistlst.Data(i),TopTracksList) logme " temppl.count:"&temppl.count For j=0 To temppl.count-1 MatchedTracks.add(temppl.item(j)) Next If MatchedTracks.count = 0 Then logme " no tracks added!" Exit for End If logme " MatchedTracks.count:"&MatchedTracks.count End If End If SDB.ProcessMessages Next 'randomize the final list if enabled' If Shuffle Then If statusbar Then bartext= "Shuffling tracks" : bar.text = BarText Set MatchedTracks = ShufflePlaylist(MatchedTracks) Else If statusbar Then bartext= "Sorting tracks" : bar.text = BarText 'sort list according to last fm Set MatchedTracks = SortPlaylist(MatchedTracks,TopTracksListTotal) End If 'enqueue final list to now playing' If MatchedTracks.count = 0 Then If Debug Then msgbox ("Hmm didn't get any matched tracks to enqueue...") logme "Hmm didn't get any matched tracks to enqueue..." If StatusBar Then BarText = "Hmm didn't get any matched tracks to enqueue..." : Bar.Text=bartext Else If debug then msgbox ("Entering final enqueue") If Int(MatchedTracks.count) < int(MaxTracks) Then MaxTracks = Int(MatchedTracks.count) logme " final queue of " & MaxTracks If StatusBar Then bartext="Adding "& MaxTracks & "songs to to now playing" : Bar.Text=bartext For i = 0 To MaxTracks -1 EnqueueTracks.add MatchedTracks.item(i) logme " " & i+1 & ": " & EnqueueTracks.item(i).artistname & " - " & EnqueueTracks.item(i).title ' logme EnqueueTracks.Item(i) Next If debug then MsgBox ("debug mode, enqueue disabled, check log for enqueue list") Else SDB.Player.PlaylistAddTracks(EnqueueTracks) End if End If If StatusBar Then Set Bar = Nothing End If logme "<>LoadXML:" & Mode Dim XMLName Set xmlDoc = CreateObject("Microsoft.XMLDOM") 'Mode gives what i want to get from the feed! Select Case Mode Case "SimArtist" 'Similar Artists logme " SimArtist:" xmlURL = "http://ws.audioscrobbler.com/1.0/artist/" & fixurl(input) & "/similar.xml" Mode = "SimArtist" Case "Tracks" 'Artist's top tracks xmlURL = "http://ws.audioscrobbler.com/1.0/artist/" & fixurl(input) & "/toptracks.xml" Mode = "TopTrack" End Select logme " LoadXML set Mode to " & mode logme " URL: " & xmlUrl xmlDoc.async = True 'I don't see any real disadvantage in linear execution! xmlDoc.Load (xmlURL) Dim starttime:starttime=Timer Do While xmlDoc.readyState <> 4 And (Timer-starttime)>GetTopTracks" 'find the artist and return the track chart from last.fm' 'last.fm xml url @ http://ws.audioscrobbler.com/1.0/artist/" & Artist & "/toptracks.xml' If Debug Then msgbox ("entering GetTopTracks()") 'query lastfm data feed Dim xmlArtistTopTracksFeedURL, TopTracksDict Set TopTracksDict = CreateObject("Scripting.Dictionary") If LoadXML(artist,"Tracks") Then 'http return code for ok :) If Debug then msgbox ("artist top tracks feed loaded") logme " TopTracksFeed loaded successfully" 'let's make this a playlist 'Set TopTracksDict = SDB.NewSongList Dim ele,TrackTitle,count, count2 count = 0 count2 = 0 For Each ele In xmlDoc.getElementsByTagName("name") TrackTitle = ele.ChildNodes.Item(0).Text 'If debug then msgbox ("Top Track " & count & ": " & TrackTitle) logme " tracktitle:" & TrackTitle If Not TopTracksDict.Exists(TrackTitle) And InDB(artist,TrackTitle,True) Then TopTracksDict.Add count, TrackTitle count = count+1 End If count2 = count2 + 1 Next If debug then msgbox ("Lastfm Top tracks returned:" & count2 & vblf &_ "Tracks added to dictionary count: " & count) logme " lastfm returned: " & count2 logme " dictionary added: " & count Set GetTopTracks = TopTracksDict logme " toptracksdict" Dim i For i =0 To TopTracksDict.Count -1 logme " " & i & ".- " &TopTracksDict.item(i) Next logme "<>MatchTopTracks(" & artist & ")" Set MatchTopTracks = SDB.NewSongList Dim j,i: i=0:j=0 Dim QueryMatch:QueryMatch = "" Dim AlreadyUsed : Set AlreadyUsed = CreateObject("scripting.dictionary") logme " toptrackslist.count:" & toptrackslist.count 'Sort list so that album with unwanted words land at the bottom Dim Select_start,Select_where, Select_order, Select_order_b ,Select_order_m,Select_order_e, Select_from Select_start = "SELECT Songs.*, Albums.*, Artists.Artist " Select_from = " FROM (Songs INNER JOIN Albums ON Songs.IDAlbum = Albums.ID) INNER JOIN Artists ON Songs.IDArtist = Artists.ID WHERE " Select_where = "Artists.Artist LIKE '" & CorrectSt(artist) & "'" If UBound(AvoidWords) >= 0 Then Select_order_b = ", IIF( " For i= 0 To UBound(AvoidWords) Select_order_m = Select_order_m & " LCase([Albums].[Album]) LIKE '%" & LCase(CorrectSt(Trim(AvoidWords(i)))) & "%' OR " Next Select_order_m = Left(Select_order_m,Len( Select_order_m)-3) Select_order_e = ", 1,0) AS Rating " Select_order = Select_order_b & Select_order_m & Select_order_e Select_order = " ORDER BY " & Right(Left(Select_order,Len(Select_order)-10),Len(Left(Select_order,Len(Select_order)-10))-2) & ",Songs.Songtitle ASC" Else Select_order = "" End If logme(" select field:" & Select_order) logme(" sql:" & Select_start & Select_from & Select_where & Select_order ) Dim iter : Set iter = Sdb.Database.opensql(Select_start & Select_from & Select_where & select_order) If Not iter.eof Then i=0 Do logme " " & iter.stringbyname("Album") & " - " & iter.stringbyname("ID") & " - " & iter.stringbyname("songTitle") For j = TopTracksList.count - 1 to 0 Step -1 'toptracks is a dictionary If LCase(iter.stringbyname("songTitle")) = LCase(TopTracksList.item(j)) And _ Not InDic(AlreadyUsed,iter.stringbyname("songTitle")) Then 'Remove track from list logme " AlreadyUsed.add:"& AlreadyUsed.Count & "," & iter.stringbyname("songTitle") AlreadyUsed.Add AlreadyUsed.Count, iter.stringbyname("songTitle") Set QueryMatch = SDB.Database.QuerySongs ("AND Songs.ID = " & iter.stringbyname("ID") ) If Not QueryMatch.EOF Then logme " " & iter.stringbyname("Album") & " - " & iter.stringbyname("ID") & " - " & iter.stringbyname("songTitle") & " _ _ matched" MatchTopTracks.Add (QueryMatch.Item) i=i+1 Exit For Else logme " ERROR!!" End If End If SDB.ProcessMessages Next iter.next Loop While Not iter.eof Else logme " SQL was empty!" End If logme "" logme " TopTracksList:"& TopTracksList.count logme " Matched:" & i logme "<>ShufflePlaylist()" Dim i,j,temp: Set temp = SDB.NewSongList Dim alreadyused 'logme " Playlist" 'For i=0 To Playlist.count-1 ' logme " " & Playlist.item(i).title 'Next Randomize Timer If Debug Then MsgBox "Playlist.count:" & Playlist.count For i=Playlist.count-1 To 0 Step -1 'Do j=Int((Playlist.count-1) * Rnd) temp.add Playlist.item(j) Playlist.delete j SDB.processmessages Next Set ShufflePlaylist = temp logme "<>SortPlaylist()" Dim Temp: Set Temp = SDB.NewSongList Dim i,item For Each item In Order.items For i=0 To playlist.count-1 If LCase(Playlist.item(i).Title) = LCase(item) Then Temp.add playlist.item(i) Exit For End If Next Next Set SortPlaylist = Temp logme "<>JoinDict()" Dim Dic3: Set Dic3 = CreateObject("scripting.dictionary") Dim item For Each item In dic1.items Dic3.Add Dic3.Count,item Next For Each item In dic2.items Dic3.Add Dic3.Count, item Next Set JoinDict = Dic3 Set Dic3 = nothing logme "<>IsAccessible:(" & SongObj.ID & ") " & SongObj.ArtistName & " - " & SongObj.Title If SongObj Is Nothing Then If Debug Then MsgBox "SongObj was empty" logme " SongObj empty!" IsAccessible = False logme "< "?") Or (SongObj.Cached) Then IsAccessible = True Else IsAccessible = False End If 'If Debug Then MsgBox "Isaccesible: " & IsAccessible & " " &songobj.title logme "<>InDB:" & artist & "-" & songtitle & " Access:"& checkaccess InDB = False Dim SQL If artist = "" And songtitle = "" Then logme "artist and songtitle empty!" InDB = False logme "< "" Then SQL = " AND Artists.Artist = '" & CorrectSt(artist) & "' " End If If Songtitle <> "" Then SQL = sql & " AND songs.songtitle = '" & CorrectSt(songtitle) & "' " End If 'escape [ and ] with [] int the query! songtitle = Replace(songtitle,"[","[[]") songtitle = Replace(songtitle,"]","[]]") artist = Replace(artist,"[","[[]") artist = Replace(artist,"]","[]]") 'logme " "&SQL 'only do for 1 item! Dim QueryMatch Set QueryMatch = SDB.Database.QuerySongs (SQL) if Not QueryMatch.EOF Then If checkaccess = True Then 'we check until we get positive Do While Not QueryMatch.eof If IsAccessible(QueryMatch.item) Then InDB = True logme "<>CorrectSt() has started with parameters " & inString CorrectSt = Replace(inString, "'", "''") 'logme "< 0 Then Dim i : i = 1 Do While i < Len(sRawURL)+1 Dim s : s = Mid(sRawURL,i,1) If InStr(1,sValidChars,s,0) = 0 Then Dim d : d = Asc(s) If d = 32 Or d > 2047 Then s = "+" Else If d < 128 Then s = DecToHex(d) Else s = DecToUtf(d) End If s = "%" & s End If Else Select Case s Case "&" s = "%2526" Case "/" s = "%252F" Case "\" s = "%5C" Case ":" s = "%3A" End Select End If fixurl = fixurl&s i = i + 1 Loop End If End Function Function HexToDec(h) HexToDec = 0 Dim i : i = 0 For i = Len(h) To 1 Step -1 Dim d : d = Mid(h,i,1) d = Instr("0123456789ABCDEF",UCase(d))-1 If d >= 0 Then HexToDec = HexToDec+(d*(16^(Len(h)-i))) Else HexToDec = 0 Exit For End If Next End Function Function DecToBin(intDec) DecToBin = "" Dim d : d = intDec Dim e : e = 1024 While e >= 1 If d >= e Then d = d - e DecToBin = DecToBin&"1" Else DecToBin = DecToBin&"0" End If e = e / 2 Wend End Function Function BinToHex(strBin) Dim d : d = 0 Dim i : i = 0 For i = Len(strBin) To 1 Step -1 Select Case Mid(strBin,i,1) Case "0" 'do nothing Case "1" d = d + (2^(Len(strBin)-i)) Case Else BinToHex = "00" Exit Function End Select Next BinToHex = DecToHex(d) End Function Function DecToHex(d) If d < 16 Then DecToHex = "0"&CStr(Hex(d)) Else DecToHex = CStr(Hex(d)) End If End Function Function DecToUtf(d) Dim b : b = DecToBin(d) Dim a : a = "110"&Left(b,5) b = "10"&Mid(b,6) DecToUtf = "%"&BinToHex(a)&"%"&BinToHex(b) End Function 'Must be in same folder as script, filename without slashes! Function FileExists(Filename) logme ">>FileExits:"&script.scriptpath&":"&filename 'get the last \ from path Dim File, myRegExp, myMatches, myMatch Set myRegExp = New RegExp myRegExp.IgnoreCase = True myRegExp.Pattern = "(\b[a-z]:|\\\\[a-z0-9]+)\\([^/:*?""<>|\r\n]*\\)?([^\\/:*?""<>|\r\n]*)" Set myMatches = myRegExp.Execute(script.scriptpath) If myMatches.Count >= 1 Then Set myMatch = myMatches(0) If myMatch.SubMatches.Count >= 3 Then File = myMatch.SubMatches(3-1) End If End If Dim fso Set fso = CreateObject("scripting.filesystemobject") If fso.FileExists(Replace(script.scriptpath,File,filename)) Then FileExists = True Else FileExists=False End If Set fso = nothing logme "< UBound(aData) then Exit Property 'Invalid range End If Data = aData(iPos) End Property Public Property Get DataArray() DataArray = aData End Property '**************************************** '************ Property Let ************** Public Property Let Data(iPos, varValue) 'Make sure iPos >= LBound(aData) If iPos < LBound(aData) Then Exit Property If iPos > UBound(aData) then 'We need to resize the array Redim Preserve aData(iPos) aData(iPos) = varValue Else 'We don't need to resize the array aData(iPos) = varValue End If End Property '**************************************** '************** Methods ***************** Public Function StartIndex() StartIndex = LBound(aData) End Function Public Function StopIndex() StopIndex = UBound(aData) End Function Public Function Count() Count = (UBound(aData)-LBound(aData)+1) End Function Public Function Exists(item) Dim i For i=LBound(aData) To ubound(aData) If aData(i)=item Then Exists =True Exit Function End if Next Exists=False End Function Public Sub Delete(iPos) 'Make sure iPos is within acceptable ranges If iPos < LBound(aData) or iPos > UBound(aData) then Exit Sub 'Invalid range End If Dim iLoop For iLoop = iPos to UBound(aData) - 1 aData(iLoop) = aData(iLoop + 1) Next Redim Preserve aData(UBound(aData) - 1) End Sub '**************************************** End Class