Last.FM Node: dynamic node based on last.fm 2020.04.19 [MM3][MM4]

Download and get help for different MediaMonkey for Windows 4 Addons.

Moderators: Peke, Gurus

nightflight

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by nightflight »

Thanks for your reply! Yes, bad song choice, but that was not the problem.
The problem was that I lost the settings, and no amount of installation could bring them back.
Apparently, one really needs a tick next to the "Time out" box and have its value set on something larger than zero. As it was, Last.Fm Node was not waiting long enough for last.fm to return (takes just over a second for me).

Another problem with the settings I noticed is that the box "limits the available tracks" should be equal or higher than the "number of tracks to enqueue". Logical once you understand what is happening, but would be easier if the tooltip contained that info.

Great log file though!
Teknojnky
Posts: 5537
Joined: Tue Sep 06, 2005 11:01 pm
Contact:

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by Teknojnky »

I would recommend you keep the 'limit available tracks' to 30 to 50 for best results.

In most cases, lastfm will return a list of about 250 tracks, the above option will limit the number of tracks *found in your library*. So if lastfm returns 250, your library has 100 of those 250, and you set that option to 5, you will only get the top 5 found in your library.

The lower the number, you will get less tracks for the script to randomly choose from. If you have already played those tracks/artists, it can cause it to not find tracks it should normally be able to.

I will look into the time out next time I get around to updating.

Thanks for the info and glad you got it working again.
odyss3y
Posts: 22
Joined: Fri Jun 10, 2011 2:37 am

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by odyss3y »

booblers wrote:Are you still developing this script at all? I ask because I've made some changes that others might be interested in and that I'd like to see in any future release so I don't have to try to merge them again and again.

When I get a similar tracks response from Last.FM I check to see if I have the similar track. If not I perform a request to get the mbid of the release that the track appears on. From there I'd like to be able to input that to a URL somewhere to take further action (build a list of missing albums I might like - or do other, more robust things like calculate preference levels, etc - but sending it to a URL is enough to get it out of MediaMonkey).

I have all of this working just fine but if you want to include it in future releases it should probably get some config options that I haven't/don't know how to make in the UI.

If you don't plan on working on this at all then I'll just keep it the way that it is - if you do and want the changes let me know and I'll try to post them here.
Please do post that change. I was looking for something exactly like you describe.
thefaceman
Posts: 367
Joined: Sun Aug 28, 2005 10:43 pm

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by thefaceman »

Has anyone tried this in MM4 yet? I want an 'iGenius' feature and this one looks like it is the best choice.
Antono
Posts: 10
Joined: Sat Apr 11, 2009 10:53 am

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by Antono »

thefaceman wrote:Has anyone tried this in MM4 yet? I want an 'iGenius' feature and this one looks like it is the best choice.
Yes, it works fine for audio. I haven't tested it with video files yet.
Hargrove

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by Hargrove »

With the latest update of Last.FM my Last.FM DJ Mode is no longer working. That function is one of the reasons I chose to buy mediamonkey over other players and I dearly miss it. It worked fine for six years... Is it acting up for others?
brianon
Posts: 78
Joined: Wed Dec 07, 2005 4:48 am

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by brianon »

Same issue here. Would be great if this could be fixed/updated.
Image
Teknojnky
Posts: 5537
Joined: Tue Sep 06, 2005 11:01 pm
Contact:

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by Teknojnky »

Hi,

I'm sorry to hear the last.fm node dj is not working properly, it looks like last.fm has changed their website around alot since the last time I visited.

I don't know if this issue is only temporary, of if what I suspect may be happening;

Last.fm node and dj mode are based upon the original last.fm public API, I suspect they either intentionally removed this old API, or it has some how broke due to the aforementioned website changes.

Unfortunately, to update the script to last.fm's current API would require a complete rewrite, which I haven't, and don't forsee having the time to do any time in the forseeable future.

Of course, any one else could take the same concepts or similar that this script does and implement them into a new script using the current last.fm api.

I hope everyone has enjoyed the script, I know that I got many many hours of great music from the script and want to thank everyone that ever used it or provided any help or feedback, and to thank the MediaMonkey dev's for making such a great music manager.
jvian
Posts: 11
Joined: Tue May 27, 2008 6:31 pm

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by jvian »

I totally hacked the heck outta your script to make it work with last.fm version 2.0 api. It really wasn't that hard, although I haven't got everything working 100% yet. I have gotten the similar tracks, similar artist, and artist top tracks working. The tags search will work if there is only one tag. It needs a loop to do a search one tag at a time. In my library I have multiple tags separated by a space and ; The similar tracks works but not completely, sometimes the artist node in the xml is element 5 but most the time it is element 7. I hard coded it for element 7 but a search for the artist node would be better. The user, group, and geo(location) searches are broke. I didn't look too hard at fixing those because I got the DJ working which was really my goal. I think I fixed the loadXML function so those searches can work, but I don't think they are getting the proper input. Again, I didn't look too hard at the other searches. You'll need an api key from last.fm, I used my own key and don't want it floating around out there. Just replace all the hashtags in loadXML with your api key.

I've had to split the code into three replies due to character limit.
Here's my hacked version of your code:

Code: Select all

Option Explicit
'==========================================================================
'
' MediaMonkey Script
'
' SCRIPTNAME: LastFM Node
' DEVELOPMENT STARTED: 2008.01.16
  Dim Version : Version = "2009.08.17.1000"

' DESCRIPTION: Creates a node where artists/tracks listed based on LastFM charts
' FORUM THREAD: http://www.mediamonkey.com/forum/viewtopic.php?t=24879
' 
' INSTALL:
' - download install package @ http://teknojnky.googlepages.com/LastFMNode.mmip

' Recent Updates:
' 2009.8.14
' * added QuickQueue from last.fm menu, selected tracks will be queried and
'     each of their similar tracks will be queued (using the queue # in options)
' * added dj queue option (queue a bunch of similar tracks)
' * added avoid twofers option (only applies to PAST and CURRENT artists, not QUEUED'

' 2009.01.25'
' * Optimized auto-dj mode retries (hopefully)'
' * Last.FM node now indicates what track will be used if you click the root node'
' * Misc stuff I've forgotten'

' * fixed a couple event errors'
' * disabled some unnecessary database transactions'

' 2009.01.15'
' * implemented favorites saving and usage (edit/remove not yet functional)'
' * favorite nodes are stored in Auto\LastFmNode.vbs.ini'
' * added menu and dialog to save favorites on the Last.FM toolbar button/menu'

' 2008.12.09
' * updated ini handling to better support mm 3.1'

' * Fixed control names in options sheet
' * Fixed dropdown lists in options sheet and added a couple more sorts'
' * Partially fixed enable dj mode from option sheet (still works from the toolbar menu)'

' * Updated SQL's to use current filter settings. Useful if you want to prevent
'     in-accessible or other tracks from being queried'
' * Finally implemented preference saving to ini, you no longer need to manually
'     modify the variables at the top of the script. Options > Library > Last.FM Node

' * Updated QueryLibrary() to avoid some case sensitivity and increase speed.
'     thx to Bex, ZvezanD and thx for the interesting discussion about it
' * added check for similar artist exists in library before trying to find their
'     tracks when similar tracks fails (prevents searching for tracks not in lib)

' * added Order variable to set the preferred sort order when searching for tracks'
'     must be a valid ORDER BY <songfield> sql qualifier, default is sort by bitrate
'     DESC so the highest bitrate track is used first. Other alternatives might be
'     Rating DESC, DateAdded ASC/DESC, PlayCounter ASC/DESC, Year ASC/DESC,  
'     or Random(). Sort order only matters when you might have multiple copies
'     of a track. The previous unspecified behavior appeared to be by songid.
'     NOTE: if you choose Random(), you might get a repeat play of a track early
'     because a different version may have been played previously.'

' * added db commits before sql iterators to avoid some database errors when 
'     multiple scripts are running or tags are being updated in the background

' * tweaked default min ratings for better compatibility with some scripts and other
'     apps that use slightly different rating values'

' * updated the sql query with many thanks to Bex for a much much faster and less
'   resource intensive query'

' * fixed artist check so that differing case doesn't matter (I noticed NoFX vs NOFX)'
' * implemented group tracks/artists, enjoy and don't forget to join "Media Monkey"
' * updated most of the last.fm nodes to be more consistent with stuff I learned later
' * should use new events instead of old onclick stuff'
' * added default variables to customize the prompts to your preferences,
'     saving options to ini should be coming soon I hope.
' * added get current track artist/tags to those node, just click fav artist or tags node'
' * I think I have all functionality I originally envisioned and even some I didn't.
'     Work soon to start on save/load nodes, optionsheet and whatever optimzations'

' * added a real PAINT IT BLACK icon based on image from Spacefish, Thanks!'
' * functionalized the dj restrictions (shouldn't really have any discernable effect)
' * add qry check for artist before searching artist+title
'     I am interested in knowing if this is any noticible improvement
'     especially for smaller libraries (shouldn't search for artists you don't have)
' * added check for min rating and size in qry (rating uses 'djminrating' variable)
'     this affects the regular nodes to keep crappy tracks out, feedback requested'
' * misc improvements & logging tweaks/details (be sure to delete log occasionally)'

' * implemented related artist + random related artist top tracks failover
'     if related tracks comes up empty.
' * implemented last chance add random track from library if all else fails'
' * implemented artist time limit (keeps artist from repeating within # hours)
' * implemented retry counter, script will now try to find more tracks by temporarily
'   loosening restrictions (track/artist repeat timer, turn off dupe avoidance)'

' * last.fm node now adds a menu icon to the standard toolbar,
'     more stuff will later be added to it'
' * added 'Last.FM DJ Mode... when enabled, this will auto-enqueue related tracks
'     similar to auto-dj/scrobblerdj. Currently some options can be set
'     script with variable start with DJ. Script uses 'related tracks' feed
'     from last.fm, this is different from how scrobblerdj works. In the future
'     options will add search similar to SDJ. DJ Mode picks random track from top
'     related tracks found library. Be sure to disable SDJ or Auto-DJ.'
' * previously added: tracklist to root Last.FM Node which will display
'     all related tracks (in your library) to the current play track. This list
'     is the basis on which the dj mode is made.
' * improved status bar info
' * created MMIP install pack, should be able to inplace update without restart.'
'     http://teknojnky.googlepages.com/LastFMNode.mmip

' TODO: Lots
' * add ability to save/load at least the first level artist/tags/user'
' * add duplicate filters to prevent having duplicate children within a tree'
' * add caching of each of the tracklists (with a manual refresh option) using sdb.objects
' * cache also probly usable to prevent dupes in trees
' * add dynamic context menus --> enter artist/tag(textbox), add/remove artist/tag
' * add option sheet/panel
' * make black last.fm icon option'

' * add any other feasible views/feeds not yet implemented'
' * there is some kind of problem with KoRn, lastfm returns KoRn with
'     a backwards R which causes errors
' * need to check xml result somehow if error 404 (artist/tag/user/etc not found)
' * improve modularity and efficiency by combining like sections etc



Randomize Timer
Const ForReading = 1, ForWriting = 2, ForAppending = 8

' Dim Logging       : Logging       = False
' Dim Status        : Status        = True
' Dim Enabled       : Enabled       = True
' Dim Timeout       : Timeout       = 25 ' seconds'
' Dim ShowTimeOut:  : ShowTimeOut   = True 'Messgebox on timeout
' Dim AvoidDupes    : AvoidDupes    = True  'prevent multiple tracks of same name'
' Dim IconPref      : IconPref      = "PaintItBlack" 'choose "paintitblack" or "simplyred"'
' Dim DefArtist     : DefArtist     = "Nine Inch Nails" 'enter your on preferred default'
' Dim DefTag        : DefTag        = "Rock"
' Dim DefUser       : DefUser       = "teknojnky"
' Dim DefGroup      : DefGroup      = "Media Monkey"
' Dim DefLocale     : DefLocale     = "United States"
' Dim MaxNodes      : MaxNodes      = 10 ' limit expanded related nodes to #'
' Dim Order1        : Order1        = "Bitrate" 'search sort field'
' Dim Order2        : Order2        = "Desc" 'search sort order'

' misc DJ mode settings, I've set the defaults to be pretty good mix'
' Dim AutoDJMode    : AutoDJMode    = True
' Dim DJMinRating   : DJMinRating   = 46 'from -1 to 100, 50 = 2.5 star'
' Dim DJMinDays     : DJMinDays     = 3.5 'days for track repeat'
' Dim DJMinHours    : DJMinHours    = 6.5 'hours for artist repeat'
' Dim DJMaxCount    : DJMaxCount    = 30 'limits the dj mode tracks to top ## found'
' Dim DJRandom      : DJRandom      = True 'pick random (variety) or top (similar) usable track'
' Dim DJTwoFurs     : DJTwoFurs     = 1 '# to enqueue from related list (not done)'
' Dim DJShowInfo    : DJShowInfo    = True 'show statusbar summary info (not done)'
' Dim DJInfoTime    : DJInfoTime    = 10 'show summary info # seconds (not done)'
' Dim DJRetryMax    : DJRetryMax    = 2 'retry # times if insufficient tracks'
Dim DJRetryCount  : DJRetryCount  = 0 'counter for retries, do not modify'
' Dim DJQueue       : DJQueue       = 3 '# of similar tracks to queue'
' Dim DJAvoidTwofers: DJAvoidTwofers= True  'prevent adding current tracks artist'

Dim Tree          : Set Tree      = SDB.MainTree
Dim Tracks        : Set Tracks    = SDB.MainTracksWindow

' Dim Ini           : Set Ini       = SDB.IniFile
Dim UI            : Set UI        = SDB.UI
Dim Prefs         : Prefs         = "LastFMNode"
Dim Favorites
Set Favorites = SDB.Tools.IniFileByPath(Script.ScriptPath & ".ini" )

Sub OnStartUp()

  Do While Not SDB.IsRunning
    SDB.Tools.Sleep 100
    SDB.ProcessMessages
  Loop

  InitPrefs

  Call SDB.UI.AddOptionSheet("Last.FM Node",Script.ScriptPath,"InitSheet","SaveSheet",-3)

  If SDB.IniFile.BoolValue(Prefs,"Enabled") = True Then
    logme "LastFMNode: OnStartUp mode = Enabled, Version:> " & Version
    InitLastFMNode
  Else
    logme "LastFMNode: OnStartUp mode = Disabled, Version:> " & Version
  End If

End Sub

Sub InitLastFMNode()
  logme "InitLastFMNode() was called, Version:> " & Version

  Dim Node
  Set Node = SDB.Objects("LastFMNode")

' this is supposed to check for existing lastfm node and unregister everything
  If SDB.Objects("LastFMNode") Is Nothing Then
'     msgbox ("no lastfm node object") 'do nothing'
  Else
'     msgbox ("last fm node object exists, needs reset now")
    Script.UnRegisterAllEvents
'     msgbox(Node.Caption)
    Tree.RemoveNode Node
    Set Node = Nothing
    SDB.Objects("LastFMNode") = Nothing
    'all should be reset now hopefully'
  End If
  
  Set Node = Tree.CreateNode

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Root Node'
  
  If SDB.RegisterIcon ("Scripts\Auto\"& SDB.IniFile.StringValue(Prefs,"IconPref") & ".ico",1) <> -1 Then
    Node.IconIndex = SDB.RegisterIcon ("Scripts\Auto\" & SDB.IniFile.StringValue(Prefs,"IconPref") & ".ico",1)
  Else
    Node.IconIndex = 37
  End If

  Node.Caption = "Last.FM Node"
  Node.UseScript = Script.ScriptPath
'   Node.OnFillTracksFunct = "FillNode" 'selection trigger'
'   Node.OnFillChildren = "ExpandNode"
  Script.RegisterEvent Node, "OnFillTracks", "FillNode"
  Script.RegisterEvent Node, "OnFillChildren", "ExpandNode"
'   Script.RegisterEvent SDB, "OnPlay", "UpdateCaption"
  Tree.AddNode Tree.Node_Library, Node, 1
  Node.HasChildren = True
  
  LastFMNodeMenu
  
  If SDB.IniFile.BoolValue(Prefs,"AutoDJMode") = True Then
    Script.RegisterEvent SDB, "OnPlay", "LastFMDJEvent"
  End If

  Set SDB.Objects("LastFMNode") = Node
  logme "InitLastFMNode() finished"
End Sub

Sub UpdateCaption()
  If SDB.IniFile.BoolValue(Prefs,"Enabled") = True Then
    SDB.Objects("LastFMNode").Caption = "Last.FM Node" &_
      " (" & SDB.Player.CurrentSong.ArtistName &_
      " - " & SDB.Player.CurrentSong.Title & ")"
    SDB.MainTree.Refresh
  End If
End Sub

Sub FillNode(obj) 'root last.fm node select'
  logme "FillNode: started"
'   msgbox ("Last.FM node Selected")

  obj.HasChildren = True

  Dim NowPlaying : Set NowPlaying = SDB.Player.CurrentSong
  Dim NodeSongList
  
  If Not (NowPlaying Is Nothing) Then
    Set NodeSongList = GetSimilarTracks(NowPlaying.ArtistName,NowPlaying.Title)
  End if
  If Not (NodeSongList Is Nothing) Then
    If NodeSonglist.Count > 0 Then
      Dim x
      For x = 0 to NodeSongList.Count-1
        Tracks.AddTrack NodeSongList.Item(x)
        SDB.ProcessMessages
      Next
      Tracks.FinishAdding
    Else
'       msgbox("SongList was empty, wasn't able to get any tracks")
    End If
  Else
'     msgbox("GetSimilarTracks returned invalid object")
  End If

  logme "FillNode: Ended"
End Sub

Sub ExpandNode(obj) 'root last.fm node expand'
  logme "ExpandNode: Started"
'   msgbox("Last.FM Node Expanded")
'   Node.Expanded = True 
  obj.HasChildren = False
  obj.HasChildren = True
'   msgbox("Ok add fav/tag/user/Location nodes now")

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Last.FM Child nodes'
' Favorite Artists' 'SimArts/TopTracks/TopAblums'
' Lists Artists -> Top artist tracks
'   Expands to Related Artists -->
' May eventually also add expand for top albums and related top tags
  logme " Adding Favorite Artists Node"
  Dim Subnode : Set Subnode = Tree.CreateNode
  Subnode.Caption = "Artists"
  Subnode.UseScript = Script.ScriptPath
  Subnode.IconIndex = 0  
'   Subnode.OnFillTracksFunct = "FillFavoriteArtistNode" 'selection trigger'
'   Subnode.OnFillChildren = "ExpandFavoriteArtistNode" 'expand trigger'
  Script.RegisterEvent SubNode, "OnFillTracks", "FillFavoriteArtistNode"
  Script.RegisterEvent SubNode, "OnFillChildren", "ExpandFavoriteArtistNode"
'   Script.RegisterEvent SDB, "OnPlay", "UpdateCaption"
  Tree.AddNode obj, Subnode, 3
  Subnode.HasChildren = True  

  logme " Adding Favorite Tags Node"
' Favorite Tags' 'TopArtists/TopAlbums/TopTracks'
' Lists Tags -> Top Tracks in that tag'
'   Expands to Related Tags ->
' May eventually add top artists per tag -> that artists tracks 
  Set Subnode = Tree.CreateNode
  Subnode.Caption = "Tags"
  Subnode.UseScript = Script.ScriptPath
  Subnode.IconIndex = 32
'   Subnode.OnFillTracksFunct = "FillFavoriteTagsNode" 'selection trigger'
'   Subnode.OnFillChildren = "ExpandFavoriteTagsNode" 'expand trigger'
  Script.RegisterEvent SubNode, "OnFillTracks", "FillFavoriteTagsNode"
  Script.RegisterEvent SubNode, "OnFillChildren", "ExpandFavoriteTagsNode"
'   Script.RegisterEvent SDB, "OnPlay", "UpdateCaption"
  Tree.AddNode obj, Subnode, 3
  Subnode.HasChildren = True
'
  logme " Adding User Charts Node"
' User Charts' Weekly Artists/Tracks, Top Artists/Tracks, SysRecommended
' User  -> Weekly Tracks
'           -> Weekly Artists + Tracks'
' User  -> Top Tracks'
'           -> Top Artists + Tracks
' User  -> System Recommended Tracks'
  Set Subnode = Tree.CreateNode
  Subnode.Caption = "Users"
  Subnode.UseScript = Script.ScriptPath
  Subnode.IconIndex = 33
'   Subnode.OnFillTracksFunct = "FillUserChartsNode" 'selection trigger'
'   Subnode.OnFillChildren = "ExpandUserChartsNode" 'expand trigger'
  Script.RegisterEvent SubNode, "OnFillTracks", "FillUserChartsNode"
  Script.RegisterEvent SubNode, "OnFillChildren", "ExpandUserChartsNode"
  Tree.AddNode obj, Subnode, 3
  Subnode.HasChildren = True

  logme " Adding Group Charts Node"
  Set Subnode = Tree.CreateNode
  Subnode.Caption = "Groups"
  Subnode.UseScript = Script.ScriptPath
  Subnode.IconIndex = 48
'   Subnode.OnFillTracksFunct = "FillGroupChartsNode" 'selection trigger'
'   Subnode.OnFillChildren = "ExpandGroupChartsNode" 'expand trigger'
  Script.RegisterEvent SubNode, "OnFillTracks", "FillGroupChartsNode"
  Script.RegisterEvent SubNode, "OnFillChildren", "ExpandGroupChartsNode"

  Tree.AddNode obj, Subnode, 3
  Subnode.HasChildren = True


  logme " Adding Location Charts Node"
' Location Weekly Charts - TopArtists/Tracks -- unknown/no xml avail
' Location Weekly Top Tracks
'       -> Weekly Top Artists + Tracks'
  Set Subnode = Tree.CreateNode
  Subnode.Caption = "Locations"
  Subnode.UseScript = Script.ScriptPath
  Subnode.IconIndex = 48
'   Subnode.OnFillTracksFunct = "FillLocationChartsNode" 'selection trigger'
'   Subnode.OnFillChildren = "ExpandLocationChartsNode" 'expand trigger'
  Script.RegisterEvent SubNode, "OnFillTracks", "FillLocationChartsNode"
  Script.RegisterEvent SubNode, "OnFillChildren", "ExpandLocationChartsNode"
  Tree.AddNode obj, Subnode, 3
  Subnode.HasChildren = True
  logme "ExpandNode: Ended"
End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Artist Node Section'
Sub FillFavoriteArtistNode(obj)
  logme "FillFavoriteArtistNode: entered"
'   msgbox("should be in favorite artists node")
'   If obj.Expanded = True Then
'     logme " Calling AddArtist()"
'     AddArtist(obj)
'   End If
  obj.HasChildren = True

  Dim NowPlaying : Set NowPlaying = SDB.Player.CurrentSong
  Dim NodeSongList
  If Not (NowPlaying Is Nothing) Then
    Set NodeSongList = GetArtistTopTracks(NowPlaying.ArtistName)
  End If
  If Not (NodeSongList Is Nothing) Then
    If NodeSonglist.Count > 0 Then
      Dim x
      For x = 0 to NodeSongList.Count-1
        Tracks.AddTrack NodeSongList.Item(x)
        SDB.ProcessMessages
      Next
      Tracks.FinishAdding
    Else
'       msgbox("SongList was empty, wasn't able to get any tracks")
    End If
  Else
'     msgbox("GetArtistTopTracks returned invalid object")
  End If


  logme "FillFavoriteArtistNode: exited"
End Sub

Sub ExpandFavoriteArtistNode(obj)
  logme "ExpandFavoriteArtistNode(obj): started"
  obj.HasChildren = False 'clear old children'  
  obj.HasChildren = True
  ReadFavs(obj)

'   msgbox("Expanded Favorite Artists, artists should be visible")
  logme "ExpandFavoriteArtistNode(obj): finished"
End Sub

Sub ReadFavs(obj)
  'read saved favorites for expanded node'
  Dim FavList : Set FavList = Favorites.Keys(obj.Caption)
  If FavList.Count > 0 Then
    Dim C, Child, Cap
    For C = 0 to FavList.Count-1
      Cap = Split(FavList.Item(C),"=")
      Set Child = Tree.CreateNode
      Child.Caption = Cap(1)
      Child.IconIndex = obj.IconIndex
      Child.SortCriteria = 0
      Script.RegisterEvent Child, "OnFillTracks", "Fill" & obj.Caption & "Node"
      Script.RegisterEvent Child, "OnFillChildren", "Expand" & obj.Caption & "Node"
      Tree.AddNode obj, Child, 3
      Child.HasChildren = True
    Next
  Else
'     AddFavs(obj)
'     obj.HasChildren = False
'     obj.HasChildren = True
  End If
End Sub

' Sub AddFavs(obj)
'   Dim Input
'   Input = InputBox(SDB.Localize("Add new " & obj.Caption))
'   If Input <> "" Then
'     Dim FavList : Set FavList = Favorites.Keys(obj.Caption)
'     Favorites.StringValue(obj.Caption,"Fav" & FavList.Count) = Input
'     'Favorites.Flush
'   End If
' End Sub

Sub AddArtist(obj)
  logme "AddArtist: Begin"
'   msgbox("AddArtist(obj)")
  Dim Input 
  Input = InputBox("Enter Artist Name: ","Add an Artist",SDB.IniFile.StringValue(Prefs,"DefArtist"))
  Dim ArtistNode : Set ArtistNode = Tree.CreateNode
  If Input <> "" Then
    logme " Adding Artist Node: " & Input
    ArtistNode.Caption = Input
    ArtistNode.IconIndex = 0
    ArtistNode.SortCriteria = 0
    ArtistNode.UseScript = Script.ScriptPath
'     ArtistNode.OnFillTracksFunct = "FillArtistNode"
'     ArtistNode.OnFillChildren = "ExpandArtistNode"
    Script.RegisterEvent ArtistNode, "OnFillTracks", "FillArtistsNode"
    Script.RegisterEvent ArtistNode, "OnFillChildren", "ExpandArtistNode"
    Tree.AddNode obj, ArtistNode, 3
    ArtistNode.HasChildren = True
    Favorites.StringValue("Artists",Input) = Input
    'Favorites.Flush
  Else
    logme " Invalid Artist, node not added"
  End If
  logme "AddArtist: finished"
End Sub

Sub FillArtistsNode(obj)
  logme "FillArtistsNode: begin"
'   msgbox ("Should be in an artist subnode")
  Dim NodeSongList, Item
  Set NodeSongList = GetArtistTopTracks(obj.Caption)
  SDB.ProcessMessages
  If NodeSonglist.Count > 0 Then
    logme " SongList Appears OK, going to add to track list"
    Dim x : x = 0
    obj.Caption = NodeSongList.Item(x).ArtistName 'makes node same caps as lib'
    For x = 0 to NodeSongList.Count-1
      Tracks.AddTrack (NodeSongList.item(x))
      SDB.ProcessMessages
    Next
    Tracks.FinishAdding
    logme " add to tracklist finished, total tracks: " & NodeSongList.Count
  Else
'     msgbox("Song List was empty")
    logme " Hmmm, songlist was empty... possibly requested artist not in library.."
  End If

  obj.HasChildren = True
  logme "FillArtistsNode: finished"
End Sub

Sub ExpandArtistsNode(obj)
  logme "ExpandArtistNode: Entered"
'   msgbox("Ok so an artist node got expanded, should be adding similar artists now")
  obj.HasChildren = False
  obj.HasChildren = True
  Dim SimilarArtistsNode, SimilarArtistsXML, Count
  Count = 0
  Set SimilarArtistsXML = LoadXML("&artist=" & fixurl(obj.Caption), "SimilarArtists")
  SDB.ProcessMessages
  If Not (SimilarArtistsXML Is Nothing) Then
    logme " SimilarArtistXML appears to be OK, proceeding with add sim artist nodes"
    Dim Ele
    For Each Ele in SimilarArtistsXML.GetElementsByTagName("name")
      Count = Count + 1
'       msgbox(ele.childnodes.item(0).text)
      Set SimilarArtistsNode = Tree.CreateNode
      SimilarArtistsNode.Caption = Ele.ChildNodes.Item(0).Text
      SimilarArtistsNode.IconIndex = 0
      SimilarArtistsNode.UseScript = Script.ScriptPath
'       SimilarArtistsNode.OnFillTracksFunct = "FillArtistsNode"
'       SimilarArtistsNode.OnFillChildren = "ExpandArtistNode"
      Script.RegisterEvent SimilarArtistsNode, "OnFillTracks", "FillArtistsNode"
      Script.RegisterEvent SimilarArtistsNode, "OnFillChildren", "ExpandArtistsNode"
      Tree.AddNode obj, SimilarArtistsNode, 3
      SimilarArtistsNode.HasChildren = True
'       obj.HasChildren = True
      logme " Added Similar Artist Node: " & SimilarArtistsNode.Caption
      SDB.ProcessMessages
      If Count => SDB.IniFile.IntValue(Prefs,"MaxNodes") Then
        logme " Similar Artist Count reached limit, exiting early"
        Exit For
      End If
    Next
'     obj.Expanded = True
  Else
    logme "SimilarArtistXML did not appear to load.. check loadxml() or network connection"
'     msgbox ("Failed to get XML from LoadXML()")
  End If
  logme "ExpandArtistNode: exited with " & Count & " Artist sub nodes"
End Sub



''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Favorite Tags Section'

Sub FillFavoriteTagsNode(obj)
  logme ">> Fill Favorite Tags Node: begin"
'   msgbox("fillfavtags")
'   If obj.Expanded = True Then
'     logme " Calling AddArtist()"
'     AddTag(obj)
'   End If


  Dim NowPlaying : Set NowPlaying = SDB.Player.CurrentSong
  Dim NodeSongList
  If Not (NowPlaying Is Nothing) Then
    Set NodeSongList = GetTopTracksByTag(NowPlaying.Genre)
  End If
  If Not (NodeSongList Is Nothing) Then
    If NodeSonglist.Count > 0 Then
      Dim x
      For x = 0 to NodeSongList.Count-1
        Tracks.AddTrack NodeSongList.Item(x)
        SDB.ProcessMessages
      Next
      Tracks.FinishAdding
    Else
'       msgbox("SongList was empty, wasn't able to get any tracks")
    End If
  Else
'     msgbox("GetTopTracksByTag returned invalid object")
  End If



  obj.HasChildren = True
  logme "<< Fill Favorite Tags Node: finish"
End Sub

Sub ExpandFavoriteTagsNode(obj)
  logme ">> Fill Favorite Tags Node: begin"
'   msgbox("favorite tags expanded")
  obj.HasChildren = False ' clear old children'
  obj.HasChildren = True
'   AddTag(obj)
  ReadFavs(obj)
  logme "<< Fill Favorite Tags Node: finish"
End Sub

Sub AddTag(obj)
  logme "AddTag: begin"
  Dim TagNode : Set TagNode = Tree.CreateNode
  Dim Input : Input = InputBox("Enter a Tag: ", "Add a Tag Node", SDB.IniFile.StringValue(Prefs,"DefTag"))
  If Input <> "" Then
    TagNode.Caption = Input
    TagNode.IconIndex = 32
    TagNode.SortCriteria = 0
    TagNode.UseScript = Script.ScriptPath
'     TagNode.OnFillTracksFunct = "FillTagNode" 'select trigger'
'     TagNode.OnFillChildren = "ExpandTagNode"  'expand trigger'
    Script.RegisterEvent TagNode, "OnFillTracks", "FillTagsNode"
    Script.RegisterEvent TagNode, "OnFillChildren", "ExpandTagsNode"
    Tree.AddNode obj, TagNode, 3
    TagNode.HasChildren = True
  Else
    logme " Invalid Tag, node not added"
  End If
  logme "AddTag: finished"
End Sub

Sub FillTagsNode(obj)
  logme "FillTagNode: begin"
'   msgbox("fill tag node")
  Dim NodeSongList, Item
  Set NodeSongList = GetTopTracksByTag(obj.Caption)
  SDB.ProcessMessages
  If NodeSonglist.Count > 0 Then
    logme " SongList Appears OK, going to add to track list"
    Dim x : x = 0
'     obj.Caption = NodeSongList.Item(x).ArtistName 'makes node same caps as lib'
    For x = 0 to NodeSongList.Count-1
      Tracks.AddTrack (NodeSongList.item(x))
      SDB.ProcessMessages
    Next
    Tracks.FinishAdding
    logme " add to tracklist finished, total tracks: " & NodeSongList.Count
  Else
'     msgbox("Song List was empty")
    logme " Hmmm, songlist was empty... possibly requested tracks not in library.."
  End If

  obj.HasChildren = True
  logme "FillTagNode: finished"
End Sub

Sub ExpandTagsNode(obj)
  logme "ExpandTagNode: begin"
'   msgbox ("Expand Tag Node()")
  obj.HasChildren = False
  obj.HasChildren = True
  Dim TagArtistsNode, TagArtistsXML, StartTimer
  StartTimer = Timer
  Set TagArtistsXML = LoadXML("&tag=" & fixurl(obj.Caption), "TopArtistsByTag")
  SDB.ProcessMessages
  If Not (TagArtistsXML Is Nothing) Then
    Dim Ele, TrackAttr, TrackTitle, ArtistAttr, ArtistName, NodeSongList
    logme " TagArtistsXML appears to be OK, proceeding"
    Dim Count : Count = 0
    For Each Ele in TagArtistsXML.GetElementsByTagName("artist")
      Count = Count + 1
      Set ArtistAttr = Ele.Attributes
			ArtistName = ArtistAttr.GetNamedItem("name").value 'get value of name attr'

      Set TagArtistsNode = Tree.CreateNode
      TagArtistsNode.Caption = ArtistName
      TagArtistsNode.IconIndex = 0
      TagArtistsNode.UseScript = Script.ScriptPath
'       TagArtistsNode.OnFillTracksFunct = "FillArtistsNode"
'       TagArtistsNode.OnFillChildren = "ExpandArtistTagNode" 'should be ExpandArtistTagNode'
      Script.RegisterEvent TagArtistsNode, "OnFillTracks", "FillArtistsNode"
      Script.RegisterEvent TagArtistsNode, "OnFillChildren", "ExpandArtistTagNode"
      Tree.AddNode obj, TagArtistsNode, 3
      TagArtistsNode.HasChildren = True
'       obj.HasChildren = True
      logme " Added Tag Artist Node: " & TagArtistsNode.Caption
      SDB.ProcessMessages
      If Count => SDB.IniFile.IntValue(Prefs,"MaxNodes") Then
        Exit For
      End If
    SDB.ProcessMessages
    Next
  Else
    logme "TagArtistXML did not appear to load.. check loadxml() or network connection"
'     msgbox ("Failed to get XML from LoadXML()")
  End If

  logme "ExpandTagNode: finished"
End Sub

Sub ExpandArtistTagNode(obj)
'   msgbox("expanding the artist top tags")
  logme "ExpandArtistTagNode: begin"
  obj.HasChildren = False ' clear existing subnodes'
  obj.HasChildren = True
  Dim ArtistTagNode, ArtistTagXML, StartTimer
  StartTimer = Timer
  Set ArtistTagXML = LoadXML("&artist=" & fixurl(obj.Caption), "ArtistTags")
  If NOT (ArtistTagXML Is Nothing) Then
    Dim Ele, ArtistAttr, ArtistName, Count
    logme " ArtistTagXML appears to be OK, proceeding"
    Count = 0
    For Each Ele In ArtistTagXML.GetElementsByTagName("tag")
      Count = Count + 1

      Set ArtistTagNode = Tree.CreateNode
      ArtistTagNode.Caption = Ele.ChildNodes.Item(0).Text
      ArtistTagNode.IconIndex = 32
      ArtistTagNode.UseScript = Script.ScriptPath
'       ArtistTagNode.OnFillTracksFunct = "FillTagNode"
'       ArtistTagNode.OnFillChildren = "ExpandTagNode"
      Script.RegisterEvent ArtistTagNode, "OnFillTracks", "FillTagsNode"
      Script.RegisterEvent ArtistTagNode, "OnFillChildren", "ExpandTagsNode"
      Tree.AddNode obj, ArtistTagNode, 3
      ArtistTagNode.HasChildren = True
      logme " Added Node: " & ArtistTagNode.Caption
      SDB.ProcessMessages
      If Count => SDB.IniFile.IntValue(Prefs,"MaxNodes") Then
        Exit For
      End If
    SDB.ProcessMessages
    Next
  Else
    logme "ArtistTagXML did not appear to load.. check loadxml() or network connection"
'     msgbox ("Failed to get XML from LoadXML()")
  End If

  logme "ExpandArtistTagNode: finished"
End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' User Charts Section'
Sub FillUserChartsNode(obj)
'   msgbox("fillusercharts")
  If obj.Expanded = True Then
    logme " Calling AddUser()"
    AddUser(obj)
  End If
  obj.HasChildren = True
End Sub

Sub ExpandUserChartsNode(obj)
'   msgbox("user charts expanded")
  obj.HasChildren = False ' clear old children'
  obj.HasChildren = True
'   AddUser(obj)
  ReadFavs(obj)
End Sub

Sub AddUser(obj)
  Dim UserChartNode : Set UserChartNode = Tree.CreateNode
  Dim Input : Input = InputBox("Enter a Last.FM User", "Add a User", SDB.IniFile.StringValue(Prefs,"DefUser"))
  If Input <> "" Then
    UserChartNode.Caption = Input
    UserChartNode.IconIndex = 33
    UserChartNode.SortCriteria = 0
    UserChartNode.UseScript = Script.ScriptPath
'     UserChartNode.OnFillTracksFunct = "FillUserNode"
'     UserChartNode.OnFillChildren = "ExpandUserNode"
    Script.RegisterEvent UserChartNode, "OnFillTracks", "FillUsersNode"
    Script.RegisterEvent UserChartNode, "OnFillChildren", "ExpandUsersNode"
    Tree.AddNode obj, UserChartNode, 3
    UserChartNode.HasChildren = True
  Else
    logme " Invalid Tag, node not added"
  End If

End Sub

Sub FillUsersNode(obj)
  logme "FillUserNode: begin"
'   msgbox("fill user node")
' user node needs weekly artists, weekly tracks, top artist, top tracks, top tags'
' not sure what to fill here since the tracks are filled in the subnodes'
  obj.HasChildren = True
'   If obj.Expanded = False Then ' no fill tracks here, so auto-expand'
'     obj.Expanded = True
'   End If
  logme "FillUserNode: finished"
End Sub

Sub ExpandUsersNode(obj)
  logme "ExpandUserNode: begin"
' Expand user node for sysrecartists, weekly/top artists and tags'
  obj.HasChildren = False
  obj.HasChildren = True
  Dim SubNode

  Set Subnode = Tree.CreateNode
  Subnode.Caption = "Weekly"
  Subnode.UseScript = Script.ScriptPath
  Subnode.IconIndex = 33
'   Subnode.OnFillTracksFunct = "FillUserWeeklyChartsNode" 'selection trigger'
'   Subnode.OnFillChildren = "ExpandUserWeeklyChartsNode" 'expand trigger'
  Script.RegisterEvent SubNode, "OnFillTracks", "FillUserWeeklyChartsNode"
  Script.RegisterEvent SubNode, "OnFillChildren", "ExpandUserWeeklyChartsNode"
  Tree.AddNode obj, Subnode, 3
  Subnode.HasChildren = True

  Set Subnode = Tree.CreateNode
  Subnode.Caption = "Overall"
  Subnode.UseScript = Script.ScriptPath
  Subnode.IconIndex = 33
'   Subnode.OnFillTracksFunct = "FillUserTopChartsNode" 'selection trigger'
'   Subnode.OnFillChildren = "ExpandUserTopChartsNode" 'expand trigger'
  Script.RegisterEvent SubNode, "OnFillTracks", "FillUserTopChartsNode"
  Script.RegisterEvent SubNode, "OnFillChildren", "ExpandUserTopChartsNode"
  Tree.AddNode obj, Subnode, 3
  Subnode.HasChildren = True

  Set Subnode = Tree.CreateNode
  Subnode.Caption = "Recommended Artists"
  Subnode.UseScript = Script.ScriptPath
  Subnode.IconIndex = 33
'   Subnode.OnFillTracksFunct = "FillRecommendedNode" 'selection trigger' not sure what to fill here
'   Subnode.OnFillChildren = "ExpandRecommendedNode" 'expand trigger'
  Script.RegisterEvent SubNode, "OnFillTracks", "FillRecommendedNode"
  Script.RegisterEvent SubNode, "OnFillChildren", "ExpandRecommendedNode"
  Tree.AddNode obj, Subnode, 3
  Subnode.HasChildren = True

  logme "ExpandUserNode: finished"
End Sub


Sub FillUserWeeklyChartsNode(obj)
  logme "FillUserWeeklyChartsNode: begin"
'   msgbox("fill user weekly charts node tracks " & obj.caption)
  Dim NodeSongList, Item, ParentNode
  Set ParentNode = Tree.ParentNode(obj)
  Set NodeSongList = GetChartTracks(ParentNode.Caption,"UserTracks")
  SDB.ProcessMessages
  If NodeSonglist.Count > 0 Then
    logme " SongList Appears OK, going to add to track list"
    Dim x : x = 0
'     obj.Caption = NodeSongList.Item(x).ArtistName 'makes node same caps as lib'
    For x = 0 to NodeSongList.Count-1
      Tracks.AddTrack (NodeSongList.item(x))
      SDB.ProcessMessages
    Next
    Tracks.FinishAdding
    logme " add to tracklist finished, total tracks: " & NodeSongList.Count
  Else
'     msgbox("Song List was empty")
    logme " Hmmm, songlist was empty... possibly requested tracks not in library.."
  End If

  obj.HasChildren = True

  logme "FillUserWeeklyChartsNode: finished"
End Sub

Sub ExpandUserWeeklyChartsNode(obj)
  logme "ExpandUserWeeklyChartsNode: begin"
  obj.HasChildren = False
  obj.HasChildren = True
  Dim WeeklyArtistNode, WeeklyArtistXML, StartTimer, ParentNode
  Set ParentNode = Tree.ParentNode(obj)
  StartTimer = Timer
  Set WeeklyArtistXML = LoadXML("&user=" & ParentNode.Caption, "UserArtists")
  SDB.ProcessMessages
  If NOT (WeeklyArtistXML Is Nothing) Then
    Dim Ele, ArtistAttr, ArtistName, Count
    logme " WeeklyArtistXML appears to be OK, proceeding"
    Count = 0
    For Each Ele In WeeklyArtistXML.GetElementsByTagName("artist")
      Count = Count + 1

      Set WeeklyArtistNode = Tree.CreateNode
      WeeklyArtistNode.Caption = Ele.ChildNodes.Item(0).Text
      WeeklyArtistNode.IconIndex = 0
      WeeklyArtistNode.UseScript = Script.ScriptPath
'       WeeklyArtistNode.OnFillTracksFunct = "FillArtistsNode"
'       WeeklyArtistNode.OnFillChildren = "ExpandAlbumNode" 'havent decided what'
      Script.RegisterEvent WeeklyArtistNode, "OnFillTracks", "FillArtistsNode"
'       Script.RegisterEvent WeeklyArtistNode, "OnFillChildren", "ExpandArtistNode"
      Tree.AddNode obj, WeeklyArtistNode, 3
      WeeklyArtistNode.HasChildren = False
'       obj.HasChildren = True
      logme " Added Node: " & WeeklyArtistNode.Caption
      SDB.ProcessMessages
      If Count => SDB.IniFile.IntValue(Prefs,"MaxNodes") Then
        Exit For
      End If
    SDB.ProcessMessages
    Next
  Else
    logme "WeeklyArtistXML did not appear to load.. check loadxml() or network connection"
'     msgbox ("Failed to get XML from LoadXML()")
  End If

  logme "ExpandUserWeeklyChartsNode: finished"
End Sub

Sub FillUserTopChartsNode(obj)
  logme "FillUserTopChartsNode: begin"
'   msgbox("fill user Top charts node tracks " & obj.caption)
  Dim NodeSongList, Item, ParentNode
  Set ParentNode = Tree.ParentNode(obj)
  Set NodeSongList = GetChartTracks(ParentNode.Caption,"TopTracksChart")
  SDB.ProcessMessages
  If NodeSonglist.Count > 0 Then
    logme " SongList Appears OK, going to add to track list"
    Dim x : x = 0
'     obj.Caption = NodeSongList.Item(x).ArtistName 'makes node same caps as lib'
    For x = 0 to NodeSongList.Count-1
      Tracks.AddTrack (NodeSongList.item(x))
      SDB.ProcessMessages
    Next
    Tracks.FinishAdding
    logme " add to tracklist finished, total tracks: " & NodeSongList.Count
  Else
'     msgbox("Song List was empty")
    logme " Hmmm, songlist was empty... possibly requested tracks not in library.."
  End If

  obj.HasChildren = True

  logme "FillUserTopChartsNode: finished"
End Sub

Sub ExpandUserTopChartsNode(obj)
  logme "ExpandUserTopChartsNode: begin"
  obj.HasChildren = False
  obj.HasChildren = True
  Dim TopArtistNode, TopArtistXML, StartTimer, ParentNode
  Set ParentNode = Tree.ParentNode(obj)
  StartTimer = Timer
  Set TopArtistXML = LoadXML("&user=" & ParentNode.Caption, "TopArtistsChart")
  SDB.ProcessMessages
  If NOT (TopArtistXML Is Nothing) Then
    Dim Ele, ArtistAttr, ArtistName, Count
    logme " TopArtistXML appears to be OK, proceeding"
    Count = 0
    For Each Ele In TopArtistXML.GetElementsByTagName("artist")
      Count = Count + 1

      Set TopArtistNode = Tree.CreateNode
      TopArtistNode.Caption = Ele.ChildNodes.Item(0).Text
      TopArtistNode.IconIndex = 0
      TopArtistNode.UseScript = Script.ScriptPath
'       TopArtistNode.OnFillTracksFunct = "FillArtistsNode"
'       TopArtistNode.OnFillChildren = "ExpandAlbumNode" 'havent decided what'
      Script.RegisterEvent TopArtistNode, "OnFillTracks", "FillArtistsNode"
'       Script.RegisterEvent TopArtistNode, "OnFillChildren", "ExpandArtistNode"
      Tree.AddNode obj, TopArtistNode, 3
      TopArtistNode.HasChildren = False
      logme " Added Node: " & TopArtistNode.Caption
      SDB.ProcessMessages
      If Count => SDB.IniFile.IntValue(Prefs,"MaxNodes") Then
        Exit For
      End If
    SDB.ProcessMessages
    Next
  Else
    logme "TopArtistXML did not appear to load.. check loadxml() or network connection"
'     msgbox ("Failed to get XML from LoadXML()")
  End If

  logme "ExpandUserTopChartsNode: finished"
End Sub

Sub FillRecommendedNode(obj)
  logme "FillRecommendedNode: begin"
  obj.HasChildren = True
'   If obj.Expanded = False Then ' no fill tracks here, so auto-expand'
'     obj.Expanded = True
'   End If
  logme "FillRecommendedNode: finished"
End Sub

Sub ExpandRecommendedNode(obj)
  logme "ExpandRecommendedNode: begin"
  obj.HasChildren = False
  obj.HasChildren = True
  Dim RecommendedArtistNode, RecommendedArtistXML, StartTimer, ParentNode
  Set ParentNode = Tree.ParentNode(obj)
  StartTimer = Timer
  Set RecommendedArtistXML = LoadXML("&user=" & ParentNode.Caption, "Recommended")
  SDB.ProcessMessages
  If NOT (RecommendedArtistXML Is Nothing) Then
    Dim Ele, ArtistAttr, ArtistName, Count
    logme " RecommendedArtistXML appears to be OK, proceeding"
    Count = 0
    For Each Ele In RecommendedArtistXML.GetElementsByTagName("artist")
      Count = Count + 1

      Set RecommendedArtistNode = Tree.CreateNode
      RecommendedArtistNode.Caption = Ele.ChildNodes.Item(0).Text
      RecommendedArtistNode.IconIndex = 0
      RecommendedArtistNode.UseScript = Script.ScriptPath
'       RecommendedArtistNode.OnFillTracksFunct = "FillArtistsNode"
'       RecommendedArtistNode.OnFillChildren = "ExpandAlbumNode" 'havent decided what'
      Script.RegisterEvent RecommendedArtistNode, "OnFillTracks", "FillArtistsNode"
'       Script.RegisterEvent RecommendedArtistNode, "OnFillChildren", "ExpandArtistNode"
      Tree.AddNode obj, RecommendedArtistNode, 3
      RecommendedArtistNode.HasChildren = True
      logme " Added Node: " & RecommendedArtistNode.Caption
      SDB.ProcessMessages
      If Count => SDB.IniFile.IntValue(Prefs,"MaxNodes") Then
        Exit For
      End If
    SDB.ProcessMessages
    Next
  Else
    logme "RecommendedArtistXML did not appear to load.. check loadxml() or network connection"
'     msgbox ("Failed to get XML from LoadXML()")
  End If

  logme "ExpandRecommendedNode: finished"

End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Group Charts Section'
'   Script.RegisterEvent SubNode, "OnFillTracks", "FillGroupChartsNode"
'   Script.RegisterEvent SubNode, "OnFillChildren", "ExpandGroupChartsNode"

Sub FillGroupChartsNode(obj)
  logme "FillGroupChartsNode: begin"
'   msgbox("fill group charts node event fired")
  
  obj.HasChildren = True
'   AddGroupNode(obj)
  logme "FillGroupChartsNode: finished"
End Sub

Sub ExpandGroupChartsNode(obj)
  logme "ExpandGroupChartsNode: begin"
'   msgbox("expand group charts node event fired")

  obj.HasChildren = False
  obj.HasChildren = True
  
'   AddGroupNode(obj)
  ReadFavs(obj)
  logme "ExpandGroupChartsNode: finished"
End Sub

Function AddGroupNode(obj)
  logme "AddGroupNode: begin "
  Dim Input : Input = InputBox("Enter Group Name: ", "Add a Group",SDB.IniFile.StringValue(Prefs,"DefGroup"))
  If Input <> "" Then
    logme " Adding Group Node: " & Input
    Dim GroupNode : Set GroupNode = Tree.CreateNode
    GroupNode.Caption = Input
    GroupNode.IconIndex = 48
    GroupNode.SortCriteria = 0
    GroupNode.UseScript = Script.ScriptPath
'     GroupNode.OnFillTracksFunct = "FillGroupNode"
'     GroupNode.OnFillChildren = "ExpandGroupNode"
    Script.RegisterEvent GroupNode, "OnFillTracks", "FillGroupsNode"
    Script.RegisterEvent GroupNode, "OnFillChildren", "ExpandGroupsNode"
    Tree.AddNode obj, GroupNode, 3
    GroupNode.HasChildren = True
  Else
    logme " Invalid Group, node not added"
  End If
  logme "AddGroupNode: finished with :> " & Input
End Function

Sub FillGroupsNode(obj)
  logme "FillGroupNode: begin"
  
  Dim NodeSongList, Item
  Set NodeSongList = GetChartTracks(obj.Caption,"GroupTracks")
  SDB.ProcessMessages
  If NodeSonglist.Count > 0 Then
    logme " SongList Appears OK, going to add to track list"
    Dim x : x = 0
'     obj.Caption = NodeSongList.Item(x).ArtistName 'makes node same caps as lib'
    For x = 0 to NodeSongList.Count-1
      Tracks.AddTrack (NodeSongList.item(x))
      SDB.ProcessMessages
    Next
    Tracks.FinishAdding
    logme " add to tracklist finished, total tracks: " & NodeSongList.Count
  Else
'     msgbox("Song List was empty")
    logme " Hmmm, songlist was empty... possibly requested tracks not in library.."
  End If

  obj.HasChildren = True

  logme "FillGroupNode: finished"
End Sub

Sub ExpandGroupsNode(obj)
  logme "ExpandGroupNode: begin"
'   msgbox("expandgroupnode")
  obj.HasChildren = False
  obj.HasChildren = True
  Dim GroupNode, GroupXML, StartTimer, ParentNode
  Set ParentNode = Tree.ParentNode(obj)
  StartTimer = Timer
  logme " calling LoadXML with :> " & obj.Caption & ", GroupArtists"
  Set GroupXML = LoadXML("&group=" & fixurl(obj.Caption), "GroupArtists")
  SDB.ProcessMessages
  If NOT (GroupXML Is Nothing) Then
    Dim Ele, ArtistAttr, ArtistName, Count
    logme " GroupXML appears to be OK, proceeding"
    Count = 0
    For Each Ele In GroupXML.GetElementsByTagName("artist")
      Count = Count + 1
'       msgbox(ele.childnodes.item(0).text)
      Set GroupNode = Tree.CreateNode
      GroupNode.Caption = Ele.ChildNodes.Item(0).Text
      GroupNode.IconIndex = 0
      GroupNode.UseScript = Script.ScriptPath
      Script.RegisterEvent GroupNode, "OnFillTracks", "FillArtistsNode"
'       Script.RegisterEvent GroupNode, "OnFillChildren", "ExpandArtistNode"
      Tree.AddNode obj, GroupNode, 3
      GroupNode.HasChildren = True
      logme " Added Node: " & GroupNode.Caption
      SDB.ProcessMessages
      If Count => SDB.IniFile.IntValue(Prefs,"MaxNodes") Then
        Exit For
      End If
    SDB.ProcessMessages
    Next
  Else
    logme "GroupXML did not appear to load.. check loadxml() or network connection"
'     msgbox ("Failed to get XML from LoadXML()")
  End If

  
  
  logme "ExpandGroupNode: finished"
End Sub


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Location Charts Section'
'there is no overall charts, but there are top artist/tracks by PLACE (UK/US etc)
Sub FillLocationChartsNode(obj)
  logme "FillLocationChartsNode: begin"
'   msgbox("fillLocationcharts not yet implemented")
  If obj.Expanded = True Then
'     AddLocation(obj)
  End If
  obj.HasChildren = True
  logme "FillLocationChartsNode: finished"
End Sub

Sub ExpandLocationChartsNode(obj)
  logme "ExpandLocationChartsNode: begin"
'   msgbox("Location charts expanded")
  obj.HasChildren = False
  obj.HasChildren = True
'   AddLocation(obj)
  ReadFavs(obj)
  logme "ExpandLocationChartsNode: finished"
End Sub

Sub AddLocation(obj)
  logme "AddLocation: begin"
  Dim Input : Input = InputBox("Enter Location Name: ", "Add a Location",SDB.IniFile.StringValue(Prefs,"DefLocale"))
  If Input <> "" Then
    logme " Adding Location Node: " & Input
    Dim LocationNode : Set LocationNode = Tree.CreateNode
    LocationNode.Caption = Input
    LocationNode.IconIndex = 48
    LocationNode.SortCriteria = 0
    LocationNode.UseScript = Script.ScriptPath
'     LocationNode.OnFillTracksFunct = "FillLocationNode"
'     LocationNode.OnFillChildren = "ExpandLocationNode"
    Script.RegisterEvent LocationNode, "OnFillTracks", "FillLocationsNode"
    Script.RegisterEvent LocationNode, "OnFillChildren", "ExpandLocationsNode"
    Tree.AddNode obj, LocationNode, 3
    LocationNode.HasChildren = True
  Else
    logme " Invalid Location, node not added"
  End If
  logme "AddLocation: finished"
End Sub

Sub FillLocationsNode(obj)
  logme "FillLocationNode: begin"

  Dim LocationTracks, LocationTracksXML, StartTimer, StatusBar
  Set StatusBar = SDB.Progress
  StatusBar.MaxValue = 100
  StartTimer = Timer
  StatusBar.Text = "Last.FM Node:> Elapsed Time:> " & Int(Timer-StartTimer) &_
   " Calling LoadXML with: " & obj.Caption & ", LocationTracks"
  Set LocationTracksXML = LoadXML("&geo=" & fixrl(obj.Caption),"LocationTracks")
  SDB.ProcessMessages
  If NOT (LocationTracksXML Is Nothing) Then
    logme " LocationTracksXML appears to be OK, proceeding"
    StatusBar.Text = "Last.FM Node:> Elapsed Time: " & Int(Timer-StartTimer) & " LoadXML Returned OK"
    Dim Ele, TrackAttr, TrackTitle, ArtistAttr, ArtistName, NodeSongList, Count
    Count = 0
    Set NodeSonglist = SDB.NewSongList
    For Each Ele in LocationTracksXML.GetElementsByTagName("track")
      'Set TrackAttr = Ele.Attributes
      'TrackTitle = TrackAttr.GetNamedItem("name").Value 'get value of name attr'
      'Set ArtistAttr = Ele.ChildNodes(7).Attributes
      'ArtistName = ArtistAttr.GetNamedItem("name").Value 'get value of name attr'
      TrackTitle = Ele.ChildNodes(0).Text
			ArtistName = Ele.ChildNodes(7).ChildNodes(0).Text
      'Set TrackAttr = Ele.Attributes
      'TrackTitle = TrackAttr.GetNamedItem("name").Value 'get value of name attr'

      'Set ArtistAttr = TrackAttr.GetNamedItem("artist").Value
      'ArtistName = ArtistAttr.GetNamedItem("name").Value 'get value of name attr'

 			StatusBar.Text = "Last.FM Node:> Elapsed Time: " & Int(Timer-StartTimer) &_
        " < Found:> " & Count & " < Searching for:> " &_
           ArtistName & " - " & TrackTitle
      logme StatusBar.Text
      StatusBar.Increase
      SDB.ProcessMessages
      'ok should have artist - title, now need to query database and add..'
      Set NodeSongList = QueryLibrary (ArtistName,TrackTitle)
      If NodeSongList.Count > 0 Then
        Dim x
        For x = 0 to NodeSongList.Count-1
          Tracks.AddTrack (NodeSongList.Item(x))
          Count = Count +1

          SDB.ProcessMessages
        Next

        End If

        If StatusBar.Terminate Then
          Exit Sub
      End If
      SDB.ProcessMessages
    Next
  End If
  Tracks.FinishAdding

  obj.HasChildren = True
  logme "FillLocationNode: finished"
End Sub

Sub ExpandLocationsNode(obj)
  logme "ExpandLocationsNode: begin"
  obj.HasChildren = False
  obj.HasChildren = True
'   msgbox("expand location artists here")

  Dim LocationArtistsNode, LocationArtistsXML, StartTimer
  StartTimer = Timer
  Set LocationArtistsXML = LoadXML("&geo=" & fixurl(obj.Caption), "LocationArtists")
  SDB.ProcessMessages
  If Not (LocationArtistsXML Is Nothing) Then
    logme " LocationArtistsXML appears to be OK, proceeding"
    Dim Count : Count = 0
    Dim Ele, TrackAttr, TrackTitle, ArtistAttr, ArtistName, NodeSongList
    For Each Ele in LocationArtistsXML.GetElementsByTagName("artist")
      Count = Count + 1
      Set ArtistAttr = Ele.Attributes
			ArtistName = ArtistAttr.GetNamedItem("name").value 'get value of name attr'

      Set LocationArtistsNode = Tree.CreateNode
      LocationArtistsNode.Caption = ArtistName
      LocationArtistsNode.IconIndex = 0
      LocationArtistsNode.UseScript = Script.ScriptPath
'       LocationArtistsNode.OnFillTracksFunct = "FillArtistsNode"
'       LocationArtistsNode.OnFillChildren = "ExpandArtistNode"
      Script.RegisterEvent LocationArtistsNode, "OnFillTracks", "FillArtistsNode"
      Script.RegisterEvent LocationArtistsNode, "OnFillChildren", "ExpandArtistsNode"
      Tree.AddNode obj, LocationArtistsNode, 3
      LocationArtistsNode.HasChildren = True
      logme " Added Location Artist Node: " & LocationArtistsNode.Caption
      SDB.ProcessMessages
      If Count => SDB.IniFile.IntValue(Prefs,"MaxNodes") Then
        Exit For
      End If
    SDB.ProcessMessages
    Next
  Else
    logme "LocationArtistXML did not appear to load.. check loadxml() or network connection"
'     msgbox ("Failed to get XML from LoadXML()")
  End If

  logme "ExpandLocationNode: finished"
End Sub

'=============================================================================='
' Menu Functions'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' add context menus' 'note not completed yet'
' commented out until further work can be done'
'   Dim Sep : Set Sep = SDB.UI.AddMenuItemSep(SDB.UI.Menu_Pop_Tree,0,0)
'   Set SDB.Objects("mAddArt") = SDB.UI.AddMenuItem(SDB.UI.Menu_Pop_Tree,0,0)
'   SDB.Objects("mAddArt").Caption = "Add Artist to Last.FM Node"
'   SDB.Objects("mAddArt").OnClickFunc = "AddArtist"
'
'   Set SDB.Objects("mRemArt") = SDB.UI.AddMenuItem(SDB.UI.Menu_Pop_Tree,0,0)
'   SDB.Objects("mRemArt").Caption = "Remove Artist from Last.FM Node"
'   SDB.Objects("mRemArt").OnClickFunc = "RemoveArtist"
'
'   Set SDB.Objects("mAvoidDupes") = SDB.UI.AddMenuItem(SDB.UI.Menu_Pop_Tree,0,0)
'   SDB.Objects("mAvoidDupes").Caption = "Toggle Avoid Dupes"
'   SDB.Objects("mAvoidDupes").OnClickFunc = "ToggleAvoidDupes"
'
'   Set SDB.Objects("mRefresh") = SDB.UI.AddMenuItem(SDB.UI.Menu_Pop_Tree,0,0)
'   SDB.Objects("mRefresh").Caption = "Re-Query Last.FM servers"
'   SDB.Objects("mRefresh").OnClickFunc = "ReQuery"
'
'   Set SDB.Objects("mGetRelated") = SDB.UI.AddMenuItem(SDB.UI.Menu_Pop_Tree,0,0)
'   SDB.Objects("mGetRelated").Caption = "Get Related Artists"
'   SDB.Objects("mGetRelated").OnClickFunc = "GetRelated"
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'''''' Toolbar Menu Mockup '''''''''''''''''''''''''''''''''''''''''''''''''''''
' Last.FM Icon toolbar menu >
'   Similar (selected track) Tracks / Artists
'   Top (selected track) > ArtistTracks / ArtistTags / ArtistListeners
'   Save To > Favorite Artists > Favorite Tags (library genre or top artist tag?)
' ----------'
'   Last.FM DJ Mode (checkmark enable/disable)
' ----------'
'   Refresh Selected Node'
'   Remove Selected Node'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

jvian
Posts: 11
Joined: Tue May 27, 2008 6:31 pm

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by jvian »

Code: Select all

Sub LastFMNodeMenu()

  Dim oMenu : Set oMenu = SDB.Objects("LastFMMenu")
  
  If oMenu Is Nothing Then
    Set oMenu = SDB.UI.AddMenuItemSub(SDB.UI.Menu_TBStandard,0,0)

    Dim mnuIcon
    mnuIcon = SDB.RegisterIcon("Scripts\Auto\" & SDB.IniFile.StringValue(Prefs,"IconPref") & ".ico",0)
    If mnuIcon < 0 Then
      mnuIcon = SDB.RegisterIcon("Scripts\Auto\" & SDB.IniFile.StringValue(Prefs,"IconPref") & ".ico",0)
      If mnuIcon < 0 Then
        mnuIcon = 55 'globe icon if SimplyRed.ico not found'
      End If
    End If

    oMenu.IconIndex = mnuIcon
    oMenu.Caption = "Last.FM Node Menu"
    oMenu.UseScript = Script.ScriptPath
'     oMenu.OnClickFunc = "ValidateSelection"
    Script.RegisterEvent oMenu, "OnClick", "ValidateSelection"

    Dim oMenuQuickQueue : Set oMenuQuickQueue = UI.AddMenuItem(oMenu,1,6)
    oMenuQuickQueue.Caption = "Queue tracks similar to selected track(s)"
    oMenuQuickQueue.Hint = "Adjust # queued in last.fm nodes options"
    Script.RegisterEvent oMenuQuickQueue, "OnClick", "DJQuickQueue"

    Dim oMenuLastFMDJ : Set oMenuLastFMDJ = UI.AddMenuItem(oMenu,1,6)
    oMenuLastFMDJ.Caption = "Last.FM DJ Mode"
    oMenuLastFMDJ.Hint = "Enables Last.FM Node to enqueue related" &_
      " tracks and artists automatically (auto-dj style)"
    oMenuLastFMDJ.UseScript = Script.ScriptPath
'     oMenuLastFMDJ.OnClickFunc = "LastFMDJToggle"
    Script.RegisterEvent oMenuLastFMDJ, "OnClick", "LastFMDJToggle"
'     oMenuLastFMDJ.IconIndex = mnuIcon 'checkbox doesnt work with icon'

    Dim oMenuAddSub : Set oMenuAddSub = UI.AddMenuItemSub(oMenu,2,1)
    oMenuAddSub.Caption = "Add Favorite"
    
    Dim oMenuAddArtist : Set oMenuAddArtist = UI.AddMenuItem(oMenuAddSub,1,1)
    oMenuAddArtist.Caption = "Temp"
    oMenuAddArtist.Hint = "Add selected artist to last.fm artist node"
    Script.RegisterEvent oMenuAddArtist, "OnClick", "MenuAddArtist"
    
    Dim oMenuAddTag : Set oMenuAddTag = UI.AddMenuItem(oMenuAddSub,1,2)
    oMenuAddTag.Caption = "Temp"
    oMenuAddTag.Hint = "Add selected tag to last.fm tag node"
    Script.RegisterEvent oMenuAddTag, "OnClick", "MenuAddTag"
    
    Dim oMenuAddOther : Set oMenuAddOther = UI.AddMenuitem(oMenuAddSub,1,3)
    oMenuAddOther.Caption = "Add Other"
    oMenuAddOther.Hint = "Open dialog to enter a node manually"
    Script.RegisterEvent oMenuAddOther, "OnClick", "AddOther"

    SDB.Objects("LastFMMenu") = oMenu
    SDB.Objects("LastFMDJ") = oMenuLastFMDJ
    SDB.Objects("LastFMAddArtist") = oMenuAddArtist
    SDB.Objects("LastFMAddTag") = oMenuAddTag
  End If
End Sub

Sub ValidateSelection(arg)

  If SDB.IniFile.BoolValue("LastFMNode","AutoDJMode") = True Then
    SDB.Objects("LastFMDJ").Checked = True
  Else
    SDB.Objects("LastFMDJ").Checked = False
  End If

  If SDB.SelectedSongList.Count > 0 Then
    SDB.Objects("LastFMAddArtist").Caption = SDB.CurrentSongList.Item(0).ArtistName
  Else
    SDB.Objects("LastFMAddArtist").Caption = SDB.Player.CurrentSong.ArtistName
  End If
  
  If SDB.SelectedSongList.Count > 0 Then
    SDB.Objects("LastFMAddTag").Caption = SDB.CurrentSongList.Item(0).Genre
  Else
    SDB.Objects("LastFMAddTag").Caption = SDB.Player.CurrentSong.Genre
  End If

End Sub

Sub MenuAddArtist(obj)
'   msgbox("add artist")
  If obj.Caption <> "" Then
    Dim FavList : Set FavList = Favorites.Keys("Artists")
    Favorites.StringValue("Artists","Fav" & FavList.Count) = obj.Caption
    If NOT SDB.Objects("LastFMNode") Is Nothing AND SDB.Objects("LastFMNode").Expanded Then
      Dim ParentNode, Child
      Set ParentNode = SDB.MainTree.FirstChildNode(SDB.Objects("LastFMNode"))
      Set Child = SDB.MainTree.CreateNode
      Child.Caption = obj.Caption
      Child.IconIndex = ParentNode.IconIndex
      Script.RegisterEvent Child, "OnFillTracks", "FillArtistsNode"
      Script.RegisterEvent Child, "OnFillChildren", "ExpandArtistsNode"
      SDB.MainTree.AddNode ParentNode, Child, 3
      Child.HasChildren = True
    End If      
    'Favorites.Flush
  End If
End Sub

Sub MenuAddTag(obj)
'   msgbox("add tag")
  If obj.Caption <> "" Then
    Dim FavList : Set FavList = Favorites.Keys("Tags")
    Favorites.StringValue("Tags","Fav" & FavList.Count) = obj.Caption
    'Favorites.Flush
  End If
End Sub

Sub AddOther(obj)
    Dim MainForm
    Set MainForm = SDB.UI.NewForm
      MainForm.Caption = "Add a new Last.FM Node"
      MainForm.Common.SetRect 200, 200, 400, 70
      MainForm.FormPosition = 4
      MainForm.BorderStyle = 3
      MainForm.StayOnTop = True
      MainForm.SavePositionName = "LastFMNodeOther"

    Dim DropAction
    Set DropAction = SDB.UI.NewDropDown(MainForm)
      DropAction.Common.ControlName = "Type"
      DropAction.Common.Hint = "Which Node Type"
      DropAction.Style = 2
      DropAction.Common.SetRect 10, 14, 70, 30
      DropAction.AddItem("Artists")
      DropAction.AddItem("Tags")
      DropAction.AddItem("Users")
      DropAction.AddItem("Groups")
      DropAction.AddItem("Locations")
      DropAction.ItemIndex = 0

    Dim edtUser
    Set edtUser = SDB.UI.NewEdit(MainForm)
      edtUser.Common.ControlName = "Name"
      edtUser.Common.Hint = "Name of node you wish to add"
      edtUser.Common.SetRect 85, 14, 190, 30

    Dim btnDoIt
    Set btnDoIt = SDB.UI.NewButton(MainForm)
      btnDoIt.Caption = "&Ok"
      btnDoit.Default = True
      btnDoIt.ModalResult = 1
      btnDoIt.Common.SetRect 285,10,50,30

    Dim btnClose
    Set btnClose = SDB.UI.NewButton(MainForm)
      btnClose.Caption = "&Cancel"
      btnClose.Cancel = True
      btnClose.ModalResult = 2
      btnClose.Common.SetRect 340,10,50,30

    If MainForm.ShowModal = 1 Then
      Dim FavList : Set FavList = Favorites.Keys(DropAction.ItemText(DropAction.ItemIndex))
      Favorites.StringValue(DropAction.ItemText(DropAction.ItemIndex),"Fav"&FavList.Count) = edtUser.Text
      Favorites.Flush
    End If
End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''' DJ MODE STUFF '''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Sub LastFMDJToggle(arg)
  If arg.Checked = True Then
    arg.Checked = False
    SDB.IniFile.BoolValue("LastFMNode","AutoDJMode") = False
    Script.UnregisterEvents SDB
  Else
    arg.Checked = True
    SDB.IniFile.BoolValue("LastFMNode","AutoDJMode") = True
    Script.RegisterEvent SDB, "OnPlay", "LastFMDJEvent"
  End If
  
End Sub

Sub LastFMDJEvent
  logme ""
  logme ">> DJ event: begin"
  If SDB.IniFile.BoolValue("LastFMNode","AutoDJMode") = True Then
    If (SDB.Player.CurrentSongIndex + 1) => SDB.Player.PlaylistCount Then
      logme " last track in now playing, starting dj"
      LastFMAutoDJ SDB.Player.CurrentSong.ArtistName, SDB.Player.CurrentSong.Title
    Else
      logme " not last track yet, exiting event"
    End If

  Else
    Script.UnregisterEvents SDB
    logme " DJ Disabled, unloading event"
  End If
  UpdateCaption()  
  logme "<< DJ event: finished"
End Sub

Sub DJQuickQueue(arg)
  If SDB.SelectedSonglist.Count > 0 Then
    Dim QuickArtist, QuickTitle, x, Statusbar
    Set Statusbar = SDB.Progress
    Statusbar.MaxValue = SDB.SelectedSongList.Count
    For x = 0 to SDB.SelectedSongList.Count-1
      QuickArtist = SDB.SelectedSongList.Item(x).ArtistName
      QuickTitle = SDB.SelectedSongList.Item(x).Title
      Statusbar.Text = ">> QuickQueue calling LastFMAutoDJ with " & QuickArtist & " - " & QuickTitle
      logme Statusbar.Text
      Call LastFMAutoDJ (QuickArtist, QuickTitle)
      Statusbar.Increase
      If Statusbar.Terminate Then
        Exit Sub
      End If
    Next
  End If
End Sub

Sub LastFMAutoDJ(inArtist,inTitle)
  logme ""
  logme "<<<<<<<<<<<<<<<<-------   Start Here   --------->>>>>>>>>>>>>>>>>>>"
  logme ">> AutoDJ:> "&version&" :> attempt :> " & DJRetryCount & " : " &_
    inArtist & " - " & inTitle
  Randomize Timer
' msgbox("autodjmode")

  GenerateRecentArtists 'get recent artists and store to object'

  Dim DJSongList, Pruned, x
    Set DJSonglist = GetSimilarTracks(inArtist,inTitle)
  If DJSongList.Count > 0 Then
    logme " DJSongList has tracks, trying prune"
    DJRetryCount = 0

      Set Pruned = Prune(DJSongList)
      DJRetryCount = DJRetryCount + 1

    If Pruned.Count < 1 Then
      logme " Pruned similar tracks did not return any tracks, lets try less restricts"

      Do
        Set Pruned = Prune(DJSongList)
        DJRetryCount = DJRetryCount + 1
        SDB.ProcessMessages
      Loop Until (Pruned.Count > 0) OR DJRetryCount > SDB.IniFile.IntValue(Prefs,"DJRetryMax")
      DJRetryCount = 0
    End If
  Else
    logme " GetSimilarTracks Failed to return any results, DJSongList Empty try similar artists"
    Set Pruned = DJSongList
  End If

  If Pruned.Count < 1 Then
    logme " Prune SimilarTracks did not return any valid tracks, trying Similar artists"
    Dim SimilarArtists : Set SimilarArtists = GetSimilarArtists(inArtist)
    SDB.ProcessMessages
    If SimilarArtists.Count > 0 Then
      logme " Similar Artists appears to be OK, finding tracks from random Similar artist"
      Dim Max, RndArtist
      x = 0

        Max = SimilarArtists.Count-1
      Do
        RndArtist = SimilarArtists.Item(x)'(int((Max)*Rnd()))
        If ArtistExists(RndArtist) AND (NOT ArtistTooSoon(RndArtist)) Then
          Set Pruned = Prune(GetArtistTopTracks(RndArtist))
        End If
        x = x + 1
        SDB.ProcessMessages
      Loop Until (Pruned.Count > 1) OR (x > Max)
    Else
      logme " Similar Artists appears empty, adding a random track and exiting"
      GenerateNewTrack
      Exit Sub
    End If
  End If

  If Pruned.Count < 1 Then
    GenerateNewTrack
    Exit Sub
  End If

  logme " Pruned appears OK with :> " & Pruned.Count
  Dim DJQueue : DJQueue = SDB.Inifile.IntValue(Prefs,"DJQueue")
  x = 0
  Do 
    If SDB.IniFile.BoolValue(Prefs,"DJRandom") = True Then
      Dim RandomTrack : RandomTrack = Int((Pruned.Count-1)*Rnd())
      ' picking a random track from returned songlist and enqueue it'
      SDB.Player.PlaylistAddTrack(Pruned.Item(RandomTrack))
      logme "Queued random usable :> " &_
        Pruned.Item(RandomTrack).ArtistName &_
        " - " & Pruned.Item(RandomTrack).Title
      Pruned.Delete(RandomTrack) ' remove track from list so no dupes added'
    Else 'or pick top usable track and enqueue it'
      logme "Queued top usable :> " &_
        Pruned.Item(x).ArtistName & " - " & Pruned.Item(x).Title
      SDB.Player.PlaylistAddTrack(Pruned.Item(x))
    End If
    x = x + 1
  Loop Until (x >= DJQueue) or (x >= Pruned.Count)

  logme "<< AutoDJ: finished"
  logme "^^^^^^^^^^^^^^^^^^^^ END HERE ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
End Sub

Sub GenerateNewTrack()
  logme " all else failed, adding random track"
  Dim Iter, ID, GenerateNewTrack 'borrowed from sample auto-dj script'
'   SDB.Database.Commit
'   SDB.Database.BeginTransaction
  Set Iter = SDB.Database.OpenSQL("SELECT ID, Rating "&_
    "FROM Songs  "&_
    "WHERE Rating >= 66 " & AddFilter &_
    " ORDER BY random(*)")
  ID = Iter.ValueByIndex(0)
  Set Iter = SDB.Database.QuerySongs( "ID=" & ID)
'   SDB.Database.Commit
  Set GenerateNewTrack = Iter.Item
  SDB.Player.PlaylistAddTrack GenerateNewTrack
  Set Iter = Nothing
End Sub

Sub GenerateRecentArtists() 'get list of recently played artists'
  logme "GenerateRecentArtists: begin"
  Dim x, y, TooSoonList, Iter, Qry : x = 0

  'qry gets the list of artists played in the last # hours, Thanks to Bex!'
  Qry = "SELECT DISTINCT Artists.Artist "&_
    "FROM ArtistsSongs, Artists "&_
    "WHERE Artists.ID=ArtistsSongs.IDArtist "&_
    "AND PersonType=1 AND IDSong "&_
    "IN (SELECT ID FROM Songs "&_
    "WHERE LastTimePlayed > " &_
    "(julianday('now','localtime','-" & SDB.IniFile.IntValue(Prefs,"DJMinHours")-(DJRetryCount*2) &_
    " Hours')-2415018.5)" & AddFilter & ")"
  Set TooSoonList = SDB.NewStringList
'   SDB.Database.Commit
'   SDB.Database.BeginTransaction
  Set Iter = SDB.Database.OpenSQL(Qry)
  SDB.ProcessMessages
  Dim DJAvoidTwofers  : DJAvoidTwofers = SDB.Inifile.BoolValue(Prefs,"DJAvoidTwofers")
  Do
    TooSoonList.Add Iter.StringByIndex(0)
    logme "  TooSoonList :> " & Iter.StringByIndex(0)
    Iter.Next
    SDB.ProcessMessages
  Loop While Not Iter.EOF
'   SDB.Database.Commit

  Dim NowPlaying : Set NowPlaying = SDB.Player.CurrentSong

  If DJAvoidTwofers = True And Not (NowPlaying Is Nothing) Then 'add current track's artist to toosoon list'
    TooSoonList.Add SDB.Player.CurrentSong.ArtistName
    logme "  TooSoonList adding current track artist :> " &_
      SDB.Player.CurrentSong.ArtistName
  End if
  SDB.Objects("ArtistsTooSoon") = TooSoonList
  Set Iter = Nothing
  logme "GenerateRecentArtists: finished with " & TooSoonList.Count
End Sub

Function ArtistTooSoon(inArtist)
  ArtistTooSoon = False
  Dim TooSoonList, y
  Set TooSoonList = SDB.Objects("ArtistsTooSoon")
  For y = 0 to TooSoonList.Count-1
    If lcase(inArtist) = lcase(TooSoonList.Item(y)) Then
      ArtistTooSoon = True
      logme "  Artist too soon:> " & inArtist 
      Exit For
    End If
    SDB.ProcessMessages
  Next
End Function

Function CheckMinRating(inSong)

  CheckMinRating = False
  If inSong.Rating < SDB.IniFile.IntValue(Prefs,"DJMinRating") Then
    CheckMinRating = True
    logme "  Track rating too low:> " & inSong.ArtistName & " - " &_
      inSong.Title 
  End If
  SDB.ProcessMessages
End Function

Function SongTooSoon(inSong)

  SongTooSoon = False
  If (DateDiff("d", inSong.LastPlayed, Now) < SDB.IniFile.IntValue(Prefs,"DJMinDays")-(DJRetryCount/2)) Then
    SongTooSoon = True
    logme "  Track played too soon:> " & inSong.ArtistName & " - " &_
      inSong.Title 
  End If
  SDB.ProcessMessages
End Function

Function Prune(inSongList) 'takes a songlist and returns songlist with only desirable tracks'
  'probly temporary until a better qry can be determined'
  logme "Prune: DJRetryCount @ " & DJRetryCount
  Dim outSongList : Set outSongList = SDB.NewSongList
  
  If (inSongList Is Nothing) OR (inSongList.Count < 1) Then
    logme "Prune: exited with invalid inSongList"
    Set Prune = outSongList    
    Exit Function
  End If  
  logme " inSongList appears valid and has tracks:> " & inSongList.Count

    Dim x
    For x = 0 To inSongList.Count-1
      If NOT (ArtistTooSoon(inSongList.Item(x).ArtistName)) Then
        If NOT (CheckMinRating(inSongList.Item(x))) Then
          If NOT(SongTooSoon(inSongList.Item(x))) = True Then
            logme " Track IS added:> " & inSongList.Item(x).ArtistName & " - " &_
              inSongList.Item(x).Title
            outSongList.Add inSongList.Item(x)
            If outSongList.Count >= SDB.IniFile.IntValue(Prefs,"DJMaxCount") Then
              logme "  Prune reached max count, exiting early"
              Exit For
            End If
          End If
        End If
      Else
        logme "   Track NOT added:> " & inSongList.Item(x).ArtistName & " - " &_
          inSongList.Item(x).Title
      End If
      SDB.ProcessMessages
    Next

  Set Prune = outSongList
'   msgbox(prune.count)
  logme " Prune: finished with # of tracks :> " & outSongList.Count
End Function

Function GetSimilarTracks(inArtist,inTitle) 'returns songlist
  logme "GetSimilarTracks: begin"
  Dim ReturnSongList : Set ReturnSongList = SDB.NewSongList
  Dim SimilarTracks, SimilarTracksXML, StartTimer, StatusBar, ArtistWithTrack
  Set StatusBar = SDB.Progress : StatusBar.MaxValue = 200
  StartTimer = Timer
'  ArtistWithTrack = fixurl(inArtist) & "/" & fixurl(inTitle)'
  ArtistWithTrack = "&artist=" & fixurl(inArtist) & "&track=" & fixurl(inTitle)
  'applying fixurl to individual artist & title now so we can keep the / in loadxml'
  StatusBar.Text = "Last.FM Node Similar Tracks:> Elapsed Time:> " & Int(Timer-StartTimer) &_
   " Calling LoadXML with: " & ArtistWithTrack & ", SimilarTracks"

  Set SimilarTracksXML = LoadXML(ArtistWithTrack,"SimilarTracks")
  SDB.ProcessMessages
  StartTimer = Timer  
  If NOT (SimilarTracksXML Is Nothing) Then
    logme "SimilarTracksXML appears to be OK, proceeding"
    Dim Ele, TrackAttr, TrackTitle, ArtistAttr, ArtistName, TmpSongList, Count, ArtistAttrName, ArtistAttrValue, s, t, Child
    Count = 0
    For Each Ele in SimilarTracksXML.GetElementsByTagName("track")
      Count = Count + 1
			TrackTitle = Ele.ChildNodes(0).Text
			ArtistName = Ele.ChildNodes(7).ChildNodes(0).Text
      
 			StatusBar.Text = "  Last.FM Node Similar Tracks:> Elapsed Time: " & Int(Timer-StartTimer) &_
        " < Found:> " & ReturnSonglist.Count & "/" & Count & " < Searching for:> " &_
           ArtistName & " - " & TrackTitle
      logme StatusBar.Text
			StatusBar.Increase
			
			Set TmpSongList = QueryLibrary(ArtistName,TrackTitle)
      SDB.ProcessMessages
      If TmpSongList.Count > 0 Then
        Dim x
        For x = 0 to TmpSongList.Count-1
          ReturnSonglist.Add (TmpSongList.Item(x))
          SDB.ProcessMessages
        Next
      End If
      SDB.ProcessMessages
      If (Timer-StartTimer) => SDB.IniFile.IntValue(Prefs,"TimeOut") OR StatusBar.Terminate Then
        Exit For
      End If
    Next
  Else
'     msgbox("did not get any matches from similar tracks xml")
  End If

  Set GetSimilarTracks = ReturnSongList
  logme " GetSimilarTracks: finished with # of tracks :> " & ReturnSongList.Count
End Function


Function GetSimilarArtists(inArtist) 'input an artist, output stringlist of related artist'
  logme "GetSimilarArtists: begin with :> " & inArtist
  Dim SimilarArtistsXML, outArtistList
  Set outArtistList = SDB.NewStringList
  Set SimilarArtistsXML = LoadXML("&artist=" & fixurl(inArtist), "SimilarArtists")
  SDB.ProcessMessages
  If Not (SimilarArtistsXML Is Nothing) Then
    logme " SimilarArtistXML appears to be OK, proceeding"
    Dim Ele, Count : Count = 0
    For Each Ele in SimilarArtistsXML.GetElementsByTagName("name")
      Count = Count + 1
      If Ele.ChildNodes.Item(0).Text <> "" Then
        logme " Adding artist to ArtistList :> " & Ele.ChildNodes.Item(0).Text
        outArtistList.Add Ele.ChildNodes.Item(0).Text
      Else
        logme " No Artist Name detected in xml @ count :> " & Count
      End If
    SDB.ProcessMessages
    Next
  Else
    logme " SimilarArtist returned as Nothing"
  End if
  Set GetSimilarArtists = outArtistList
  logme "GetSimilarArtists: finished with :> " & outArtistList.Count
End Function

Function GetArtistTopTracks(inArtist) 'input artist string, output top song list'
  logme "GetArtistTopTracks: begin with :> " & inArtist
  
  Dim TopTracksList, TopTracksXML, outSongList, StatusBar, StartTimer
  StartTimer = Timer
  Set StatusBar = SDB.Progress
  StatusBar.MaxValue = 200
  StatusBar.Text = "Last.FM Node Artist Top Tracks:> Elapsed Time:> " & Int(Timer-StartTimer) &_
   " Calling LoadXML with: " & inArtist & ", TopTracks"
  logme StatusBar.Text
  Set outSongList = SDB.NewSongList
  Set TopTracksXML = LoadXML("&artist=" & fixurl(inArtist),"TopTracks")
  SDB.ProcessMessages
  If Not (TopTracksXML Is Nothing) Then
    logme " TopTracksXML appears to be OK, proceeding"
    Dim Ele, TmpSongList, Count : Count = 0
    For Each Ele in TopTracksXML.GetElementsByTagName("name")
      Count = Count + 1
      If Ele.ChildNodes.Item(0).Text <> "" Then
        Dim TrackTitle : TrackTitle = Ele.ChildNodes.Item(0).Text

   			StatusBar.Text = "  Last.FM Node Artist Top Tracks:> Elapsed Time: " & Int(Timer-StartTimer) &_
          " < Found:> " & outSonglist.Count & "/" & Count & " < Searching for:> " &_
             inArtist & " - " & TrackTitle
        logme StatusBar.Text
  			StatusBar.Increase

  			Set TmpSongList = QueryLibrary(inArtist,TrackTitle)
        SDB.ProcessMessages
        If TmpSongList.Count > 0 Then
          Dim x
          For x = 0 to TmpSongList.Count-1
            outSonglist.Add (TmpSongList.Item(x))
            SDB.ProcessMessages
          Next
        End If
        SDB.ProcessMessages
        If (Timer-StartTimer) => SDB.IniFile.IntValue(Prefs,"TimeOut") OR StatusBar.Terminate Then
          logme " User Teriminated or TimeOut occured :> " & (Timer-StartTimer)
          Exit For
        End If
      Else
        logme " No Track Name detected in xml @ count :> " & Count
      End If
    SDB.ProcessMessages
    Next
  Else
    logme " TopTracksXML returned as Nothing"
  End if

  Set GetArtistTopTracks = outSongList
  logme "GetArtistTopTracks: finished with :> " & outSongList.Count
End Function

Function GetTopTracksByTag(inTag)
  logme "GetTopTracksByTag: begin with :> " & inTag
  Dim TagTracks, TagTracksXML, StartTimer, StatusBar, outSongList
  Set outSongList = SDB.NewSongList
  Set StatusBar = SDB.Progress
  StatusBar.MaxValue = 100
  StartTimer = Timer
  StatusBar.Text = "Last.FM Node Top Tracks By Tag :> Elapsed Time: " &_
   Int(Timer-StartTimer) & " Calling LoadXML with: " &_
    inTag & ", TopTracksByTag"
  logme StatusBar.Text
  Set TagTracksXML = LoadXML("&tag=" & fixurl(inTag),"TopTracksByTag")
  If NOT (TagTracksXML Is Nothing) Then
    logme " TagTracksXML appears to be OK, proceeding"
    Dim Ele, TrackAttr, TrackTitle, ArtistAttr, ArtistName, tmpSongList, Count
    Count = 0
    For Each Ele in TagTracksXML.GetElementsByTagName("track")
      Count = Count +1
      TrackTitle = Ele.ChildNodes(0).Text
			ArtistName = Ele.ChildNodes(7).ChildNodes(0).Text
        If (TrackTitle <> "") OR (ArtistName <> "") Then
          StatusBar.Text = "Last.FM Node Top Tracks By Tag :> Elapsed Time: " &_
           Int(Timer-StartTimer) &_
          " < Found:> " & outSonglist.Count & "/" & Count & " < Searching for:> " &_
          ArtistName & " - " & TrackTitle
          logme StatusBar.Text
          StatusBar.Increase
          'ok should have artist - title, now need to query database and add..'
          Set tmpSongList = QueryLibrary (ArtistName,TrackTitle)
          If tmpSongList.Count > 0 Then
            Dim x
            For x = 0 to tmpSongList.Count-1
              outSonglist.Add (tmpSongList.Item(x))
              SDB.ProcessMessages
            Next
          Else
            logme " QueryLibrary did not find any tracks"
          End If
          If (Timer-StartTimer) => SDB.IniFile.IntValue(Prefs,"TimeOut") OR StatusBar.Terminate Then
            logme " User Teriminated or TimeOut occured :> " & (Time-StartTimer)
            Exit For
          End If
        Else
          logme " TrackTitle or ArtistName appeared to be blank, possibly bad tag name"
        End If
      SDB.ProcessMessages
    Next
  Else
    logme " TagTracksXML was invalid, possibly last.fm timeout or bad tag name"
  End If
  Set GetTopTracksByTag = outSongList
  logme "GetTopTracksByTag: finished with " & outSongList.Count
End Function

Function GetChartTracks(inChartName,inChartMode) 'returns songlist
  logme "GetChartTracks: begin"
  Dim ReturnSongList : Set ReturnSongList = SDB.NewSongList
  Dim ChartTracks, ChartTracksXML, StartTimer, StatusBar
  Set StatusBar = SDB.Progress : StatusBar.MaxValue = 200
  StartTimer = Timer

  'applying fixurl to individual artist & title now so we can keep the / in loadxml'
  StatusBar.Text = "Last.FM Node Chart Tracks:> Elapsed Time:> " & Int(Timer-StartTimer) &_
   " Calling LoadXML with: " & inChartName & ", " & inChartMode

  Set ChartTracksXML = LoadXML(inChartName,inChartMode)
  
  
  SDB.ProcessMessages
  StartTimer = Timer
  If NOT (ChartTracksXML Is Nothing) Then
    logme "ChartTracksXML appears to be OK, proceeding"
    Dim Ele, TrackAttr, TrackTitle, ArtistAttr, ArtistName, TmpSongList, Count
    Count = 0
    For Each Ele in ChartTracksXML.GetElementsByTagName("track")
      Count = Count + 1
			TrackTitle = Ele.ChildNodes(0).Text
			ArtistName = Ele.ChildNodes(7).ChildNodes(0).Text

 			StatusBar.Text = "  Last.FM Node "&inChartMode&":> Elapsed Time: " & Int(Timer-StartTimer) &_
        " < Found:> " & ReturnSonglist.Count & "/" & Count & " < Searching for:> " &_
           ArtistName & " - " & TrackTitle
      logme StatusBar.Text
			StatusBar.Increase

			Set TmpSongList = QueryLibrary(ArtistName,TrackTitle)
      SDB.ProcessMessages
      If TmpSongList.Count > 0 Then
        Dim x
        For x = 0 to TmpSongList.Count-1
          ReturnSonglist.Add (TmpSongList.Item(x))
          SDB.ProcessMessages
        Next
      End If
      SDB.ProcessMessages
      If (Timer-StartTimer) => SDB.IniFile.IntValue(Prefs,"TimeOut") OR StatusBar.Terminate Then
        Exit For
      End If
    Next
  Else
'     msgbox("did not get any matches from Chart tracks xml")
  End If

  Set GetChartTracks = ReturnSongList
  logme " GetChartTracks: finished with # of tracks :> " & ReturnSongList.Count
End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Sub MnuLastFMNode(obj) 'context menu' 'possibly obsolete'
' Here's where we add context menu items for add/remove/options'
  logme ">> MnuLastFMNode: begin"
'   msgbox ("add mnu code")

'   Dim mnuAddArtist, mnuRemoveArtist, mnuAvoidDupes, mnuRefresh

  logme "<< MnuLastFMNode: finished"
End Sub

Sub RemoveArtist(obj)
  msgbox("RemoveArtist(obj)")
End Sub

Sub ToggleAvoidDupes(obj)
  msgbox("ToggleAvoidDupes(obj)")
End Sub

Sub Requery(obj)
  msgbox("Requery(obj)")
End Sub

Sub GetRelated(obj)
  msgbox("GetRelated(obj)")
End Sub

Function ArtistExists(inArtist)
  logme " ArtistExists: begin with :> " & inArtist
  ArtistExists = False
  Dim Qry, Iter

  Qry = "SELECT Artists.ID, Artists.Artist FROM Artists WHERE Artists.Artist LIKE '%" &_
    CorrectST(inArtist) & "' AND Artists.Tracks > 1"

'   SDB.Database.Commit
'   SDB.Database.BeginTransaction
  Set Iter = SDB.Database.OpenSQL(Qry)
  SDB.ProcessMessages
  Do While NOT Iter.EOF
    SDB.ProcessMessages
    'check artist exist'
    logme " ArtistExists found artist :> " & Iter.StringByIndex(1)
    ArtistExists = True
    Iter.Next
    SDB.ProcessMessages
  Loop
'   SDB.Database.Commit
  Set Iter = Nothing
  logme " ArtistExists: exit with :> " & ArtistExists
End Function


'=============================================================================='

Function AddFilter()
'   logme " AddFilter(): Begin"
  ' Add currently active filter to query if any'

  Dim GetFilter : GetFilter = SDB.Database.ActiveFilterQuery  
  If GetFilter <> "" Then
    AddFilter = " AND " & GetFilter
  End If
  
'   logme " AddFilter(): exit with :> " & AddFilter
End Function

Function QueryLibrary(qArtist, qTitle) 'input artist, title... output songlist'
  logme "QueryLibrary: begin with " & qArtist & ", " & qTitle
  Dim Iter, Iter2, Qry, Qry2, StatusBar, tmpSongList
  Set tmpSongList = SDB.NewSonglist

  Qry = "SELECT Artists.ID, Artists.Artist FROM Artists WHERE Artists.Artist LIKE '%" &_
    CorrectST(qArtist) & "'"

'   Thanks to Bex for the improved qrys
  Qry2 = "SongTitle = '" & CorrectST(qTitle) & "' "&_
        "AND SongLength > 60*1000 AND Rating >= " & SDB.IniFile.IntValue(Prefs,"DJMinRating") &" "&_
        "AND Songs.ID IN (SELECT IDSong FROM ArtistsSongs, Artists  WHERE "&_
        "IDArtist=Artists.ID AND PersonType=1 AND " &_
        "Artist = '" & CorrectST(qArtist) & "') " & AddFilter &_
        " ORDER BY " & SDB.IniFile.StringValue(Prefs,"Order1") & " " & SDB.IniFile.StringValue(Prefs,"Order2")

'        "UpperW(TRIM(Artist)) = UpperW('" & CorrectST(qArtist) & "'))" & " " & Order
'   logme " QRY2 :> " & Qry2
'   SDB.Database.Commit
'   SDB.Database.BeginTransaction
  Set Iter = SDB.Database.OpenSQL(Qry)
  SDB.ProcessMessages
  Do While NOT Iter.EOF
    SDB.ProcessMessages
    'check artist exist first'
    logme " found artist :> " & Iter.StringByIndex(1)

    Set Iter2 = SDB.Database.QuerySongs(Qry2)
'     SDB.Database.Commit
'     SDB.Database.BeginTransaction
    SDB.ProcessMessages
    Do While Not Iter2.EOF
      SDB.ProcessMessages
      tmpSongList.Add (Iter2.Item)
      logme " -->> Added: --->>> " & Iter2.Item.ArtistName & " - " & Iter2.Item.Title
'       logme Qry2
  '           msgbox("pause")
      SDB.ProcessMessages
      If SDB.IniFile.BoolValue(Prefs,"AvoidDupes") AND DJRetryCount < SDB.IniFile.IntValue(Prefs,"DJRetryMax") Then 'add only first result'
        logme " Adding only first result :> " & SDB.IniFile.BoolValue(Prefs,"AvoidDupes") & " - " & DJRetryCount & " - " & SDB.IniFile.IntValue(Prefs,"DJRetryMax")
        Exit Do
      End If
      SDB.ProcessMessages
      Iter2.Next
      SDB.ProcessMessages
    Loop
'     SDB.Database.Commit
      If SDB.IniFile.BoolValue(Prefs,"AvoidDupes") AND DJRetryCount < SDB.IniFile.IntValue(Prefs,"DJRetryMax") Then 'add only first result'
'         logme " Adding only first result :> " & SDB.IniFile.BoolValue(Prefs,"AvoidDupes") & " - " & DJRetryCount & " - " & SDB.IniFile.IntValue(Prefs,"DJRetryMax")
        Exit Do
      End If
    Iter.Next
    SDB.ProcessMessages
  Loop
'   SDB.Database.Commit
  Set Iter = Nothing
  Set Iter2 = Nothing
  Set QueryLibrary = tmpSongList
End Function

jvian
Posts: 11
Joined: Tue May 27, 2008 6:31 pm

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by jvian »

Code: Select all

' Function QueryLibrary(qArtist, qTitle) 'input artist, title... output songlist'
'   logme "QueryLibrary: begin with " & qArtist & ", " & qTitle
'   Dim Iter, Iter2, Qry, StatusBar, tmpSongList,i,ArtistIDs
'   Set tmpSongList = SDB.NewSonglist
'
'   Qry = "SELECT ID, Artist FROM Artists " &_
'         "WHERE Tracks>0 AND (Artist = '" & CorrectST(qArtist) & "'" &_
'                       "OR Artist LIKE '" & CorrectST(qArtist) & " %'" &_
'                     "OR Artist LIKE '% " & CorrectST(qArtist) & "')"
' '   logme " Qry = " & Qry
'   SDB.Database.Commit
'   SDB.Database.BeginTransaction
'   Set Iter = SDB.Database.OpenSQL(Qry)
'   Do While NOT Iter.EOF
'     i=i+1
'     SDB.ProcessMessages
'     'check artist exist first'
'     logme " found artist :> " & Iter.StringByIndex(0)&","& Iter.StringByIndex(1)
'     ArtistIDs = ArtistIDs &","& Iter.StringByIndex(0)
'     Iter.Next
'     SDB.ProcessMessages
'   Loop
'   Set Iter = Nothing
'   If i=0 Then
'    logme " artist "& qArtist &" not found:> "
'    Exit Function
'   End If
' '------Find Songs-------------------------------------------------------------
' '   Thanks to Bex for the improved qry '
'     Qry = "SongTitle = '" & CorrectST(qTitle) & "' "&_
'           "AND SongLength > 60*1000 AND Rating >= " & DJMinRating &" "&_
'           "AND Songs.ID IN (SELECT IDSong FROM ArtistsSongs  WHERE "&_
'           "PersonType=1 AND  IDArtist IN ("& Mid(ArtistIDs,2) &")) " & Order
'
'     Set Iter2 = SDB.Database.QuerySongs(Qry)
'     SDB.Database.Commit
'     SDB.ProcessMessages
'     Do While Not Iter2.EOF
'       SDB.ProcessMessages
'       tmpSongList.Add (Iter2.Item)
'       logme " -->> Added: --->>> " & Iter2.Item.ArtistName & " - " & Iter2.Item.Title
'   '           msgbox("pause")
'       SDB.ProcessMessages
'       If SDB.IniFile.BoolValue(Prefs,"AvoidDupes") AND DJRetryCount < DJRetryMax Then 'add only first result'
'         logme " Adding only first result :> " & SDB.IniFile.BoolValue(Prefs,"AvoidDupes") & " - " & DJRetryCount & " - " & DJRetryMax
'         Exit Do
'       End If
'       SDB.ProcessMessages
'       Iter2.Next
'       SDB.ProcessMessages
'     Loop
'     Set Iter2 = Nothing
' '   SDB.Database.Commit
' '     If SDB.IniFile.BoolValue(Prefs,"AvoidDupes") AND DJRetryCount < DJRetryMax Then 'add only first result'
' ' '     logme " Adding only first result :> " & SDB.IniFile.BoolValue(Prefs,"AvoidDupes") & " - " & DJRetryCount & " - " & DJRetryMax
' '       Exit Do
' '     End If
'   SDB.Database.Commit
'   Set QueryLibrary = tmpSongList
' End Function


Function LoadXML(Input,Mode)
  'LoadXML accepts input string and mode, returns xmldoc of requested string and mode'
  'http://msdn2.microsoft.com/en-us/library/aa468547.aspx'
	logme ">> LoadXML: Begin with " & Input & " & " & Mode
'
'   If SDB.Objects("CachedInput") = Input Then
'     If SDB.Objects("CachedMode") = Mode Then
'       Set LoadXML = SDB.Objects(Input & Mode)
'       Exit Function
'     End If
'   Else
' '     Set SDB.Objects(SDB.Objects("CachedInput") & SDB.Objects("CachedMode")) = Nothing
'   End If


  Dim xmlDoc, xmlURL, StatusBar, LoadXMLBar, StartTimer, lmt
  StartTimer = Timer
  lmt = 100
  If SDB.IniFile.BoolValue(Prefs,"Status") then Set LoadXMLBar = SDB.Progress
  LoadXMLBar.MaxValue = 250 ' 500000
  Select Case Mode
    Case "SimilarArtists"		'Similar Artists
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=artist.getSimilar" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"
    Case "TopTracks"		'Artist's top tracks
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=artist.getTopTracks" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "SimilarTracks"		'Similar Tracks **** must also include "artist/" in the INPUT string
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=track.getSimilar" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"
    ' fixurl must be ran on the pre-combined artist & title'
    ' 			msgbox("pause")
    Case "TopTracksByTag"		'  Top Tracks per tag
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=tag.getTopTracks" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"
    Case "TopArtistsByTag"	'  Top Artists per tag
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=tag.getTopArtists" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"
    Case "TopAlbumsByTag"		'  Top Albums per tag
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=tag.getTopAlbums" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "UserArtists"		'User Weekly Artists Chart
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=user.getWeeklyArtistChart" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"
    Case "UserTracks"		'User Weekly Tracks Chart
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=user.getWeeklyTrackChart" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "TopArtistsChart"		'User Top 50 Artists Chart
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=user.getTopArtists&user=" & fixurl(input) & "&api_key=###############################&limit=" & lmt & "&callback=?"
    Case "TopTracksChart"		'User Top 50 Tracks Chart
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=user.getTopTracks&user=" & fixurl(input) & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "Recommended"		'Recommended by Last.FM
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=user.getRecommendedArtists" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "ArtistAlbums"		'Artist Top Albums
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=artist.getTopAlbums" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "ArtistTags"		'Artist Top Tags
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=artist.getTopTags" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "TrackTags"		'Top Tags for track 'must include "artist/" in INPUT
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=track.getTopTags" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "LocationTracks"		'top tracks by location
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=geo.getTopTracks" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"
    Case "LocationArtists"		'top artists by location
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=geo.getTopArtists" & Input & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case "GroupTracks"	'top weekly tracks for group'
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=group.getWeeklyTrackChart&group=" & fixurl(input) & "&api_key=###############################&limit=" & lmt & "&callback=?"
    Case "GroupArtists" 'top weekly artists for group'
      xmlURL = "http://ws.audioscrobbler.com/2.0/?method=group.getWeeklyArtistChart&group=" & fixurl(input) & "&api_key=###############################&limit=" & lmt & "&callback=?"

    Case Else
      msgbox("Invalid MODE was passed to LoadXML(Input, Mode)")
      Exit Function
  End Select

  Set xmlDoc = CreateObject("Microsoft.XMLDOM")
  LoadXMLBar.Text = "LoadXML: Init Query Last.FM"
  logme " xmlDoc.Load: Init Query Last.FM: " & xmlURL
  xmlDoc.async = True
  xmlDoc.Load (xmlURL) ' <<<<---- load last.fm xml occurs here
  logme " xmlDoc.Load: Waiting for Last.FM to return " & Mode & " of " & Input
  LoadXMLBar.Text = "LoadXML: Waiting for Last.FM to return " & Mode & " of " & Input
  SDB.ProcessMessages

  Do While xmlDoc.readyState <> 4 And Int(Timer-StartTimer) < SDB.IniFile.IntValue(Prefs,"TimeOut")
    '     SDB.ProcessMessages
    SDB.Tools.Sleep 100
    SDB.ProcessMessages
    LoadXMLBar.Increase
    LoadXMLBar.Text = "LoadXML: Waiting " & Int(Timer-StartTimer) - SDB.IniFile.IntValue(Prefs,"TimeOut") &_
    " for Last.FM to return " & Mode & " of " & Input & " "
    '     LoadXMLBar.Text = "LoadXML: Waiting " & LoadXMLBar.Value & " for Last.FM to return " & Mode & " of " & Input
    If LoadXMLBar.Terminate Then
      msgbox("User Terminated @ Query LastFM xml")
      Exit Function
    End If
    SDB.ProcessMessages
  Loop

  logme " xmlDoc: returned from loop in: " & (Timer - StartTimer)

  If xmlDoc.readyState = 4 Then 'all ok
    Set LoadXML = xmlDoc
'     Set SDB.Objects("CachedInput") = Input
'     Set SDB.Objects("CachedMode") = Mode
'     Set SDB.Objects(Input & Mode) = xmlDoc
    LoadXMLBar.Text = "Last.FM Query Succeeded in: " & (Timer - StartTimer)
    '     msgbox("Last.FM query took: " & (timer-starttime))
  Else
    LoadXMLBar.Text = "Last.FM Query Failed, server may be down or busy..."
    logme "Last.FM Query Failed @ " & Int(Timer-StartTimer) &_
    "ReadyState: " & xmlDoc.ReadyState & " URL: " & xmlURL
    '     msgbox("Last.FM Timed Out @ " & Int(Timer-StartTimer))
    Set LoadXML = Nothing
  End If

  logme "<< LoadXML: Finished in --> " & Int(Timer-StartTimer)
End Function


'******************************************************************
'**************** Auxillary Functions *****************************
'******************************************************************

Sub logme(msg)
	'by psyXonova'
	If SDB.IniFile.BoolValue(Prefs,"Logging") Then
		Dim fso, logf
  On Error Resume Next
		Set fso = CreateObject("Scripting.FileSystemObject")
		Set logf = fso.OpenTextFile(Script.ScriptPath&".log",ForAppending,True)
		logf.WriteLine Now() & ": " & msg
		Set fso = Nothing
		Set logf = Nothing
	End If
End Sub

Function CorrectSt(inString)
' 	logme ">> CorrectSt() has started with parameters: " & inString
	CorrectSt = Replace(inString, "'", "''")
	CorrectSt = Replace(CorrectSt, """", """""")
' 	logme "<< CorrectSt() will return: " & CorrectSt & " and exit"
End Function


Function fixurl(sRawURL)
	' Original psyxonova improved by trixmoto
  logme ">> fixurl() entered with: " & sRawURL
	Const sValidChars = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\/!&:."
	sRawURL = Replace(sRawURL,"+","%2B")

  If UCase(Right(sRawURL,6)) = " (THE)" Then
    sRawURL = "The "&Left(sRawURL,Len(sRawURL)-6)
  End If
  If UCase(Right(sRawURL,5)) = ", THE" Then
    sRawURL = "The "&Left(sRawURL,Len(sRawURL)-5)
  End If

	If Len(sRawURL) > 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
		SDB.ProcessMessages
    Loop
	End If
	logme "<< fixurl will return with: " & fixurl
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
	SDB.ProcessMessages
  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
	SDB.ProcessMessages
  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
	SDB.ProcessMessages
  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


' 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



'************************************************************'
Sub InitPrefs
  logme "Initializing Preferences"

  If NOT SDB.Tools.FileSystem.FileExists(Script.ScriptPath & ".ini") Then
    SDB.Tools.FileSystem.CreateTextFile Script.ScriptPath & ".ini",False
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"Logging") Then
    SDB.IniFile.BoolValue(Prefs,"Logging") = False
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"Status") Then
    SDB.IniFile.BoolValue(Prefs,"Status") = True
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"Enabled") Then
    SDB.IniFile.BoolValue(Prefs,"Enabled") = True
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"Timeout") Then
    SDB.IniFile.IntValue(Prefs,"Timeout") = 25
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"ShowTimeOut") Then
    SDB.IniFile.BoolValue(Prefs,"ShowTimeOut") = True
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"AvoidDupes") Then
    SDB.IniFile.BoolValue(Prefs,"AvoidDupes") = True
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"IconPref") Then
    SDB.IniFile.StringValue(Prefs,"IconPref") = "PaintItBlack"
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"MaxNodes") Then
    SDB.IniFile.IntValue(Prefs,"MaxNodes") = 10
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"Order1") Then
    SDB.IniFile.StringValue(Prefs,"Order1") = "Bitrate"
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"Order2") Then
    SDB.IniFile.StringValue(Prefs,"Order2") = "Desc"
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DefArtist") Then
    SDB.IniFile.StringValue(Prefs,"DefArtist") = "Nine Inch Nails"
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DefTag") Then
    SDB.IniFile.StringValue(Prefs,"DefTag") = "Rock"
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DefUser") Then
    SDB.IniFile.StringValue(Prefs,"DefUser") = "Teknojnky"
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DefGroup") Then
    SDB.IniFile.StringValue(Prefs,"DefGroup") = "Media Monkey"
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DefLocale") Then
    SDB.IniFile.StringValue(Prefs,"DefLocale") = "United States"
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"AutoDJMode") Then
    SDB.IniFile.BoolValue(Prefs,"AutoDJMode") = False
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJMinRating") Then
    SDB.IniFile.IntValue(Prefs,"DJMinRating") = -1
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJMinDays") Then
    SDB.IniFile.IntValue(Prefs,"DJMinDays") = 4
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJMinHours") Then
    SDB.IniFile.IntValue(Prefs,"DJMinHours") = 7
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJMaxCount") Then
    SDB.IniFile.IntValue(Prefs,"DJMaxCount") = 30
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJRandom") Then
    SDB.IniFile.BoolValue(Prefs,"DJRandom") = True
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJTwoFurs") Then
    SDB.IniFile.IntValue(Prefs,"DJTwoFurs") = 1
  End If

'   If NOT SDB.IniFile.ValueExists(Prefs,"DJShowInfo") Then
'     SDB.IniFile.BoolValue(Prefs,"DJShowInfo") = True
'   End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJInfoTime") Then
    SDB.IniFile.IntValue(Prefs,"DJInfoTime") = 10
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJRetryMax") Then
    SDB.IniFile.IntValue(Prefs,"DJRetryMax") = 2
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJQueue") Then
    SDB.IniFile.IntValue(Prefs,"DJQueue") = 1
  End If

  If NOT SDB.IniFile.ValueExists(Prefs,"DJAvoidTwofers") Then
    SDB.IniFile.BoolValue(Prefs,"DJAvoidTwofers") = True
  End If

  'SDB.IniFile.Flush
  logme "Preferences Initialized"
End Sub


'*******************************************************************'
'* Form produced by MMVBS Form Creator (http://trixmoto.net/mmvbs) *'
'*******************************************************************'

Sub InitSheet(Sheet1)
  Dim Label1 : Set Label1 = SDB.UI.NewLabel(Sheet1)
  Label1.Common.SetRect 6,7,65,17
  Label1.Common.ControlName = "Label1"
  Label1.Caption = "Last.FM Node -- Version " & Version

  
  Dim CheckBox1 : Set CheckBox1 = SDB.UI.NewCheckBox(Sheet1)
  CheckBox1.Checked = SDB.IniFile.BoolValue(Prefs,"Enabled")
  CheckBox1.Common.SetRect 6,28,98,20
  CheckBox1.Common.ControlName = "chkEnabled"
  CheckBox1.Caption = "Enabled"
  CheckBox1.Common.Hint = "Enable/Disable Last.FM Nodes"

  Dim CheckBox2 : Set CheckBox2 = SDB.UI.NewCheckBox(Sheet1)
  CheckBox2.Checked = SDB.IniFile.BoolValue(Prefs,"Logging")
  CheckBox2.Common.SetRect 6,50,98,20
  CheckBox2.Common.ControlName = "chkLogging"
  CheckBox2.Caption = "Logging"
  CheckBox2.Common.Hint = "Logs debug info to scripts\auto\last.fmnode.vbs.log"

'   Dim CheckBox3 : Set CheckBox3 = SDB.UI.NewCheckBox(Sheet1)
'   CheckBox3.Checked = SDB.IniFile.BoolValue(Prefs,"Status")
'   CheckBox3.Common.SetRect 6,117,98,20
'   CheckBox3.Common.ControlName = "chkStatus"
'   CheckBox3.Caption = "Status"
'   CheckBox3.Common.Enabled = True
'   CheckBox3.Common.Hint = "Show Status Bar (Not Yet Implemented)"

  Dim CheckBox4 : Set CheckBox4 = SDB.UI.NewCheckBox(Sheet1)
  CheckBox4.Checked = SDB.IniFile.BoolValue(Prefs,"ShowTimeOut")
  CheckBox4.Common.SetRect 6,93,98,20
  CheckBox4.Common.ControlName = "chkShowTimeOut"
  CheckBox4.Caption = "Time Out"
  CheckBox4.Common.Hint = "Pop up message if last.fm times out"

  Dim CheckBox5 : Set CheckBox5 = SDB.UI.NewCheckBox(Sheet1)
  CheckBox5.Checked = SDB.IniFile.BoolValue(Prefs,"AvoidDupes")
  CheckBox5.Common.SetRect 6,71,98,20
  CheckBox5.Common.ControlName = "chkAvoidDupes"
  CheckBox5.Caption = "Avoid Dupes"
  CheckBox5.Common.Hint = "Prevent multiple copies of the same track from being added"

  Dim SpinEdit1 : Set SpinEdit1 = SDB.UI.NewSpinEdit(Sheet1)
  SpinEdit1.MaxValue = 60
  SpinEdit1.MinValue = 1
  SpinEdit1.Value = SDB.IniFile.IntValue(Prefs,"TimeOut")
  SpinEdit1.Common.SetRect 108,96,60,21
  SpinEdit1.Common.ControlName = "spinTimeOut"
  SpinEdit1.Common.Hint = "How long to wait for Last.FM to respond"
  
  Dim DropDown1 : Set DropDown1 = SDB.UI.NewDropDown(Sheet1)
  DropDown1.AddItem("PaintItBlack")
  DropDown1.AddItem("SimplyRed")
  DropDown1.ItemIndex = SDB.IniFile.IntValue(Prefs,"IconPref-IDX")
'   DropDown1.Text = SDB.IniFile.StringValue(Prefs,"IconPref")
  DropDown1.Style = 2
  DropDown1.Common.SetRect 108,27,121,21
  DropDown1.Common.ControlName = "dropIconPref"
  DropDown1.Common.Hint = "Select your icon color preference"

  Dim DropDown2 : Set DropDown2 = SDB.UI.NewDropDown(Sheet1)
  DropDown2.AddItem("Bitrate")
  DropDown2.AddItem("Year")
  DropDown2.AddItem("DateAdded")
  DropDown2.AddItem("LastTimePlayed")
  DropDown2.AddItem("Rating")
  DropDown2.AddItem("PlayCounter")
  DropDown2.AddItem("OrigYear")
  DropDown2.ItemIndex = SDB.IniFile.IntValue(Prefs,"Order1-IDX")
'   DropDown2.Text = SDB.IniFile.StringValue(Prefs,"Order1")
  DropDown2.Style = 2
  DropDown2.Common.SetRect 108,49,121,21
  DropDown2.Common.ControlName = "dropSort1"
  DropDown2.Common.Hint = "Choose how the sql query sorts track results"

  Dim DropDown3 : Set DropDown3 = SDB.UI.NewDropDown(Sheet1)
  DropDown3.AddItem("Asc")
  DropDown3.AddItem("Desc")
  DropDown3.ItemIndex = SDB.IniFile.IntValue(Prefs,"Order2-IDX")
'   DropDown3.Text = SDB.IniFile.StringValue(Prefs,"Order2")
  DropDown3.Style = 2
  DropDown3.Common.SetRect 229,49,60,21
  DropDown3.Common.ControlName = "dropSort2"
  DropDown3.Common.Hint = "Asc = Lower to higher, Desc = Higher to lower"

  Dim SpinEdit2 : Set SpinEdit2 = SDB.UI.NewSpinEdit(Sheet1)
  SpinEdit2.MaxValue = 100
  SpinEdit2.MinValue = 1
  SpinEdit2.Value = SDB.IniFile.IntValue(Prefs,"MaxNodes")
  SpinEdit2.Common.SetRect 108,72,60,21
  SpinEdit2.Common.ControlName = "spinMaxNodes"
  SpinEdit2.Common.Hint = "Limits the displayed subnodes when expanding"

  Dim CheckBox6 : Set CheckBox6 = SDB.UI.NewCheckBox(Sheet1)
  CheckBox6.Checked = SDB.IniFile.BoolValue(Prefs,"DJRandom")
  CheckBox6.Common.SetRect 105,151,98,20
  CheckBox6.Common.ControlName = "chkDJRandom"
  CheckBox6.Caption = "DJ Random"
  CheckBox6.Common.Hint = "Pick random valid tracks or use top tracks in order"

  Dim CheckBox7 : Set CheckBox7 = SDB.UI.NewCheckBox(Sheet1)
  CheckBox7.Checked = SDB.IniFile.BoolValue(Prefs,"DJAvoidTwofers")
  CheckBox7.Common.SetRect 7,176,98,20
  CheckBox7.Common.ControlName = "chkDJAvoidTwofers"
  CheckBox7.Caption = "DJ Avoid Twofers"
  CheckBox7.Common.Enabled = True
  Checkbox7.Common.Hint = "Avoids playing the same artist twice even though it is a similar track"

'   Dim SpinEdit3 : Set SpinEdit3 = SDB.UI.NewSpinEdit(Sheet1)
'   SpinEdit3.MaxValue = 100
'   SpinEdit3.MinValue = 1
'   SpinEdit3.Value = SDB.IniFile.IntValue(Prefs,"DJInfoTime")
'   SpinEdit3.Common.SetRect 111,175,60,21
'   SpinEdit3.Common.ControlName = "spinDJInfoTime"
'   SpinEdit3.Common.Enabled = False
'   SpinEdit3.Common.Hint = "How long to show DJ info"

  Dim CheckBox8 : Set CheckBox8 = SDB.UI.NewCheckBox(Sheet1)
  CheckBox8.Checked = SDB.IniFile.BoolValue(Prefs,"AutoDJMode")
  CheckBox8.Common.SetRect 6,151,98,20
  CheckBox8.Common.ControlName = "chkDJMode"
  CheckBox8.Caption = "DJ Mode"
  CheckBox8.Common.Hint = "Turns on or off the DJ Mode auto-enqueue to now playing"

  Dim SpinEdit4 : Set SpinEdit4 = SDB.UI.NewSpinEdit(Sheet1)
  SpinEdit4.MaxValue = 100
  SpinEdit4.MinValue = -1
  SpinEdit4.Value = SDB.IniFile.IntValue(Prefs,"DJMinRating")
  SpinEdit4.Common.SetRect 9,205,60,21
  SpinEdit4.Common.ControlName = "spinDJMinRating"
  SpinEdit4.Common.Hint = "Select Rating, from -1 (all including unrated), 0 to 100."

  Dim SpinEdit5 : Set SpinEdit5 = SDB.UI.NewSpinEdit(Sheet1)
  SpinEdit5.MaxValue = 999
  SpinEdit5.MinValue = 0
  SpinEdit5.Value = SDB.IniFile.IntValue(Prefs,"DJMinDays")
  SpinEdit5.Common.SetRect 79,205,60,21
  SpinEdit5.Common.ControlName = "spinDJMinDays"
  SpinEdit5.Common.Hint = "How many days before a track can repeat"

  Dim SpinEdit6 : Set SpinEdit6 = SDB.UI.NewSpinEdit(Sheet1)
  SpinEdit6.MaxValue = 999
  SpinEdit6.MinValue = 0
  SpinEdit6.Value = SDB.IniFile.IntValue(Prefs,"DJMinHours")
  SpinEdit6.Common.SetRect 147,205,60,21
  SpinEdit6.Common.ControlName = "spinDJMinHours"
  SpinEdit6.Common.Hint = "How many hours before an artist can repeat"

  Dim SpinEdit7 : Set SpinEdit7 = SDB.UI.NewSpinEdit(Sheet1)
  SpinEdit7.MaxValue = 100
  SpinEdit7.MinValue = 1
  SpinEdit7.Value = SDB.IniFile.IntValue(Prefs,"DJMaxCount")
  SpinEdit7.Common.SetRect 9,231,60,21
  SpinEdit7.Common.ControlName = "spinDJMaxCount"
  SpinEdit7.Common.Hint = "Limits the available valid tracks that can be choosen. Higher = More variety"

  Dim SpinEdit8 : Set SpinEdit8 = SDB.UI.NewSpinEdit(Sheet1)
  SpinEdit8.MaxValue = 100
  SpinEdit8.MinValue = 1
  SpinEdit8.Value = SDB.IniFile.IntValue(Prefs,"DJQueue")
  SpinEdit8.Common.SetRect 79,231,60,21
  SpinEdit8.Common.ControlName = "spinDJQueue"
  SpinEdit8.Common.Enabled = True
  SpinEdit8.Common.Hint = "Number of tracks to enqueue"

  Dim SpinEdit9 : Set SpinEdit9 = SDB.UI.NewSpinEdit(Sheet1)
  SpinEdit9.MaxValue = 4
  SpinEdit9.MinValue = 1
  SpinEdit9.Value = SDB.IniFile.IntValue(Prefs,"DJRetryMax")
  SpinEdit9.Common.SetRect 146,231,60,21
  SpinEdit9.Common.ControlName = "spinDJRetryMax"
  SpinEdit9.Common.Hint = "Number of times to retry with lowered restrictions if no suitable tracks found"

'   Dim 

End Sub

Sub SaveSheet(Sheet1)
  
  SDB.IniFile.BoolValue(Prefs,"Enabled") = Sheet1.Common.ChildControl("chkEnabled").Checked
  SDB.IniFile.BoolValue(Prefs,"Logging") = Sheet1.Common.ChildControl("chkLogging").Checked
'   SDB.IniFile.BoolValue(Prefs,"Status") = Sheet1.Common.ChildControl("chkStatus").Checked
  SDB.IniFile.BoolValue(Prefs,"ShowTimeOut") = Sheet1.Common.ChildControl("chkShowTimeOut").Checked
  SDB.IniFile.BoolValue(Prefs,"AvoidDupes") = Sheet1.Common.ChildControl("chkAvoidDupes").Checked
  SDB.IniFile.IntValue(Prefs,"TimeOut") = Sheet1.Common.ChildControl("spinTimeOut").Value
  SDB.IniFile.IntValue(Prefs,"MaxNodes") = Sheet1.Common.ChildControl("spinMaxNodes").Value
  SDB.IniFile.BoolValue(Prefs,"DJRandom") = Sheet1.Common.ChildControl("chkDJRandom").Checked
  SDB.IniFile.BoolValue(Prefs,"DJAvoidTwofers") = Sheet1.Common.ChildControl("chkDJAvoidTwofers").Checked
'   SDB.IniFile.IntValue(Prefs,"DJInfoTime") = Sheet1.Common.ChildControl("spinDJInfoTime").Value
  SDB.IniFile.BoolValue(Prefs,"AutoDJMode") = Sheet1.Common.ChildControl("chkDJMode").Checked
  SDB.IniFile.IntValue(Prefs,"DJMinRating") = Sheet1.Common.ChildControl("spinDJMinRating").Value
  SDB.IniFile.IntValue(Prefs,"DJMinDays") = Sheet1.Common.ChildControl("spinDJMinDays").Value
  SDB.IniFile.IntValue(Prefs,"DJMinHours") = Sheet1.Common.ChildControl("spinDJMinHours").Value
  SDB.IniFile.IntValue(Prefs,"DJMaxCount") = Sheet1.Common.ChildControl("spinDJMaxCount").Value
  SDB.IniFile.IntValue(Prefs,"DJQueue") = Sheet1.Common.ChildControl("spinDJQueue").Value
  SDB.IniFile.IntValue(Prefs,"DJRetryMax") = Sheet1.Common.ChildControl("spinDJRetryMax").Value
  
'   SDB.IniFile.StringValue(Prefs,"IconPref") = Sheet1.Common.ChildControl("dropIconPref").ItemText(Sheet1.Common.ChildControl("dropIconPref").ItemIndex)
'   SDB.IniFile.StringValue(Prefs,"Order1") = Sheet1.Common.ChildControl("dropSort1").ItemText(Sheet1.Common.ChildControl("dropSort1").ItemIndex)
'   SDB.IniFile.StringValue(Prefs,"Order2") = Sheet1.Common.ChildControl("dropSort2").ItemText(Sheet1.Common.ChildControl("dropSort2").ItemIndex)

  SDB.IniFile.IntValue(Prefs,"IconPref-IDX") = Sheet1.Common.Childcontrol("dropIconPref").ItemIndex
  SDB.IniFile.IntValue(Prefs,"Order1-IDX") = Sheet1.Common.Childcontrol("dropSort1").ItemIndex
  SDB.IniFile.IntValue(Prefs,"Order2-IDX") = Sheet1.Common.Childcontrol("dropSort2").ItemIndex

  SDB.IniFile.StringValue(Prefs,"IconPref") = Sheet1.Common.ChildControl("dropIconPref").Text
  SDB.IniFile.StringValue(Prefs,"Order1") = Sheet1.Common.ChildControl("dropSort1").Text
  SDB.IniFile.StringValue(Prefs,"Order2") = Sheet1.Common.ChildControl("dropSort2").Text

  SDB.IniFile.Flush
'   InitPrefs
'   LastFMDJToggle
  
End Sub

'*******************************************************************'
'* End of form                              Richard Lewis (c) 2007 *'
'*******************************************************************
brianon
Posts: 78
Joined: Wed Dec 07, 2005 4:48 am

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by brianon »

Appreciate the effort but not working for me. I've replaced the vbs with your updated script.
Heres the log.

Code: Select all

13-Sep-15 6:51:57 PM: <<<<<<<<<<<<<<<<-------   Start Here   --------->>>>>>>>>>>>>>>>>>>
13-Sep-15 6:51:57 PM: >> AutoDJ:> 2009.08.17.1000 :> attempt :> 0 : Metallica - Dyers Eve
13-Sep-15 6:51:57 PM: GenerateRecentArtists: begin
13-Sep-15 6:51:58 PM:   TooSoonList :> Doves
13-Sep-15 6:51:58 PM:   TooSoonList :> Slayer
13-Sep-15 6:51:58 PM:   TooSoonList adding current track artist :> Metallica
13-Sep-15 6:51:58 PM: GenerateRecentArtists: finished with 3
13-Sep-15 6:51:58 PM: GetSimilarTracks: begin
13-Sep-15 6:51:58 PM: >> fixurl() entered with: Metallica
13-Sep-15 6:51:58 PM: << fixurl will return with: Metallica
13-Sep-15 6:51:58 PM: >> fixurl() entered with: Dyers Eve
13-Sep-15 6:51:58 PM: << fixurl will return with: Dyers+Eve
13-Sep-15 6:51:58 PM: >> LoadXML: Begin with &artist=Metallica&track=Dyers+Eve & SimilarTracks
13-Sep-15 6:51:58 PM:  xmlDoc.Load: Init Query Last.FM: http://ws.audioscrobbler.com/2.0/?method=track.getSimilar&artist=Metallica&track=Dyers+Eve&api_key=###############################&limit=100&callback=?
13-Sep-15 6:51:58 PM:  xmlDoc.Load: Waiting for Last.FM to return SimilarTracks of &artist=Metallica&track=Dyers+Eve
13-Sep-15 6:51:58 PM:  xmlDoc: returned from loop in: 0.53125
13-Sep-15 6:51:58 PM: << LoadXML: Finished in --> 0
13-Sep-15 6:51:58 PM: SimilarTracksXML appears to be OK, proceeding
13-Sep-15 6:51:58 PM:  GetSimilarTracks: finished with # of tracks :> 0
13-Sep-15 6:51:58 PM:  GetSimilarTracks Failed to return any results, DJSongList Empty try similar artists
13-Sep-15 6:51:58 PM:  Prune SimilarTracks did not return any valid tracks, trying Similar artists
13-Sep-15 6:51:58 PM: GetSimilarArtists: begin with :> Metallica
13-Sep-15 6:51:58 PM: >> fixurl() entered with: Metallica
13-Sep-15 6:51:58 PM: << fixurl will return with: Metallica
13-Sep-15 6:51:58 PM: >> LoadXML: Begin with &artist=Metallica & SimilarArtists
13-Sep-15 6:51:58 PM:  xmlDoc.Load: Init Query Last.FM: http://ws.audioscrobbler.com/2.0/?method=artist.getSimilar&artist=Metallica&api_key=###############################&limit=100&callback=?
13-Sep-15 6:51:58 PM:  xmlDoc.Load: Waiting for Last.FM to return SimilarArtists of &artist=Metallica
13-Sep-15 6:51:58 PM:  xmlDoc: returned from loop in: 0.25
13-Sep-15 6:51:58 PM: << LoadXML: Finished in --> 0
13-Sep-15 6:51:58 PM:  SimilarArtistXML appears to be OK, proceeding
13-Sep-15 6:51:58 PM: GetSimilarArtists: finished with :> 0
13-Sep-15 6:51:58 PM:  Similar Artists appears empty, adding a random track and exiting
13-Sep-15 6:51:58 PM:  all else failed, adding random track
13-Sep-15 6:51:59 PM: << DJ event: finished
Would love to have this working again.
Image
brianon
Posts: 78
Joined: Wed Dec 07, 2005 4:48 am

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by brianon »

Having looked at it i guess the problem is the "&api_key=###############################"
Image
Teknojnky
Posts: 5537
Joined: Tue Sep 06, 2005 11:01 pm
Contact:

Re: Last.FM Node: dynamic node based on last.fm 2009.08.17 [

Post by Teknojnky »

from the above post, you will need to create your own API key from last.fm to use the modified code above.
Post Reply