I'm a complete novice at writing code and not sure what I'm doing. Am hoping that one or more folks here with more experience might be willing to point me in the right direction, maybe review the script as I'm writing it and provide feedback.
Thanks to the efforts of other users we have scripts that will find an AcoustID for a given track. We also have a script that will search Musicbrainz to find the earliest release date for a given track (which I would use if the below lookups don't return results). I'd like to build a script that will do the following:
1. Search AcoustID metadata to find a Musicbrainz recording ID (e.g., http://api.acoustid.org/v2/lookup?clien ... ee12d5718c)
2. For a given recording ID, store the Work ID (if available) in a custom field - this is both for the classical lookup mentioned below, as well as to allow me to find covers of tracks in my library
3. If the track is a classical work, find the composition date and store it in the year (if available, assuming work ID returned a result)
4. If the track is not a classical work, find the recording date and store it in the year (if available)
This query at Musicbrainz will return the recording date, work ID and composition date if they're accessible:
http://musicbrainz.org/ws/2/recording/3 ... place-rels
I'm looking at borrowing some code from either the MusicIP tagger (which was based on the now-deprecated PUID) or the MusicBrainz NGS tagger, or maybe both, but again, not really sure what I'm doing.
*******
First issue I'm looking to tackle is how to load the currently selected song list and, for each track in the list, query AcoustID to find the recording ID. I store the AcoustID in Custom5 but if the script is to be more broadly applicable I'd have to incorporate either fpcalc or allow a user to specify which field the AcoustID is stored in to perform the lookup.
I could use some pointers on how to do the above so I can get started - also not sure how to integrate debugging into the code to identify any problems that might come up.
*******
Next issue would be querying to find the Work ID (I'm not sure how to get this data from the query I posted above). Then storing that ID in a custom field (I use custom 4 but again, might need to make this user-defined).
I use the Grouping field to specify whether a track is classical, although others may use the newer functionality in MediaMonkey 4 to separate classical tracks from other tracks. That would be my next problem to solve, figuring out whether a track is classical and, if so, looking up and storing the composition date.
Final issue would be looking up and storing the recorded date if the track is not classical.
Thanks in advance for any help!
Novice scripting - updating info from Musicbrainz
Moderators: Gurus, Addon Administrators
Re: Novice scripting - updating info from Musicbrainz
Shockingly, I actually was able to make this work, more or less. Biggest problem is that the script will effectively freeze MediaMonkey if run against a large number of tracks, but otherwise seems to work OK. Would appreciate if anyone happens to look to see what could be improved here. For simplicity, I just built it for myself, but could be extended to allow for user inputs if someone has the knowledge to do that.
Code: Select all
Sub SearchAcoustID
' Define variables
Dim list, itm, i
Dim APIKey : APIKey = "[insert your API key here]"
Dim Grouping
Dim AcoustID
Dim Worktemp
Dim WorkID
Dim RecordingID
Dim acoustidurl
Dim mbrainzurl
Dim xml : Set xml = CreateObject("Microsoft.XMLDOM")
xml.async = False
xml.preserveWhiteSpace = True
Dim mbrainz : Set mbrainz = CreateObject("Microsoft.XMLDOM")
mbrainz.async = False
mbrainz.preserveWhiteSpace = True
Dim mbrainznode
Dim recordingidtemp
Dim mbrainztemp
Dim workidtemp
RecordingID = ""
WorkID = ""
' Get list of selected tracks from MediaMonkey
Set list = SDB.CurrentSongList
If list.Count=0 Then
Exit Sub
End If
' Process all selected tracks
For i=0 To list.count-1
Do
Set itm = list.Item(i)
Grouping = itm.Grouping
AcoustID = itm.Custom5
acoustidurl = "http://api.acoustid.org/v2/lookup?format=xml&client=" & APIKey & "&meta=recordingids+recordings&trackid=" & AcoustID
Call xml.Load(acoustidurl)
Dim cnt : cnt = 0
While (xml.readyState < 4 And cnt < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cnt = cnt+1
WEnd
If xml.readyState < 4 Then
Exit Sub
End If
Set recordingidtemp = xml.getElementsByTagName("id").Item(0)
If recordingidtemp Is Nothing Then Exit Do
RecordingID = xml.getElementsByTagName("id").Item(0).Text
mbrainzurl = "http://musicbrainz.org/ws/2/recording/" & RecordingID & "?inc=place-rels+artist-rels+work-rels+work-level-rels"
Call mbrainz.Load(mbrainzurl)
Dim cnta : cnta = 0
While (mbrainz.readyState < 4 And cnta < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cnta = cnta+1
WEnd
If mbrainz.readyState < 4 Then
Exit Sub
End If
If Grouping = "Classical" Then
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then Exit Do
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
Set mbrainztemp = mbrainz.SelectSingleNode("//recording/relation-list/relation/work/relation-list/relation/end")
If mbrainztemp Is Nothing Then
itm.UpdateDB
itm.WriteTags
Exit Do
End If
mbrainznode = mbrainz.SelectSingleNode("//recording/relation-list/relation/work/relation-list/relation/end").Text
itm.Year = mbrainznode
Else
Set mbrainztemp = mbrainz.SelectSingleNode("//recording/relation-list/relation/end")
If mbrainztemp Is Nothing Then
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then Exit Do
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
itm.UpdateDB
itm.WriteTags
Exit Do
End If
mbrainznode = mbrainz.SelectSingleNode("//recording/relation-list/relation/end").Text
itm.Year = Left(mbrainznode,4)
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then
itm.UpdateDB
itm.WriteTags
Exit Do
End If
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
End If
Loop While False
Next
list.UpdateAll
End Sub
Re: Novice scripting - updating info from Musicbrainz
Oh, just to set good expectations, the script won't commonly return results, unfortunately. I think this is because the fields I'm looking up are not often filled out and associated with an AcoustID fingerprint, so your mileage may vary. If I'm incorrect and this is due to a coding error would love to have some help to make this more productive.
Re: Novice scripting - updating info from Musicbrainz
Last post (I think) - made some improvements. Now the script will also search by Work ID for classical works, if that information is stored in Custom4. Also limited the loop to go once per second to avoid hitting Musicbrainz too often. I created a separate version of the script just to tag the Work ID from the AcoustID, which mostly involved stripping out a bunch of code. If anyone's interested in that I can post it separately.
Code: Select all
Sub SearchAcoustID
' Define variables
Dim list, itm, i
Dim APIKey : APIKey = "[REPLACE WITH ACOUSTID API KEY]"
Dim Grouping
Dim AcoustID
Dim Worktemp
Dim WorkID
Dim RecordingID
Dim acoustidurl
Dim mbrainzurl
Dim xml : Set xml = CreateObject("Microsoft.XMLDOM")
xml.async = False
xml.preserveWhiteSpace = True
Dim mbrainz : Set mbrainz = CreateObject("Microsoft.XMLDOM")
mbrainz.async = False
mbrainz.preserveWhiteSpace = True
Dim mbrainznode
Dim recordingidtemp
Dim mbrainztemp
Dim workidtemp
Dim workurl
Dim workxml : Set workxml = CreateObject("Microsoft.XMLDOM")
workxml.async = False
workxml.preserveWhiteSpace = True
Dim mbrainzlist
RecordingID = ""
WorkID = ""
' Get list of selected tracks from MediaMonkey
Set list = SDB.CurrentSongList
If list.Count=0 Then
Exit Sub
End If
' Process all selected tracks
For i=0 To list.count-1
Do
Set itm = list.Item(i)
Grouping = itm.Grouping
AcoustID = itm.Custom5
acoustidurl = "http://api.acoustid.org/v2/lookup?format=xml&client=" & APIKey & "&meta=recordingids+recordings&trackid=" & AcoustID
Call xml.Load(acoustidurl)
Dim cnt : cnt = 0
While (xml.readyState < 4 And cnt < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cnt = cnt+1
WEnd
If xml.readyState < 4 Then
Exit Sub
End If
Set recordingidtemp = xml.getElementsByTagName("id").Item(0)
If recordingidtemp Is Nothing Then
If itm.Custom4 <> "" AND Grouping = "Classical" Then
WorkID = itm.Custom4
workurl = "http://musicbrainz.org/ws/2/work/" & WorkID & "?inc=artist-rels"
Call workxml.Load(workurl)
Dim cntb : cntb = 0
While (workxml.readyState < 4 And cntb < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cntb = cntb+1
WEnd
If workxml.readyState < 4 Then
Exit Sub
End If
Set mbrainztemp = workxml.SelectSingleNode("//work/relation-list/relation/end")
If mbrainztemp Is Nothing Then Exit Do
mbrainznode = workxml.SelectSingleNode("//work/relation-list/relation/end").Text
itm.Year = Left(mbrainznode,4)
itm.UpdateDB
itm.WriteTags
End If
Exit Do
End If
RecordingID = xml.getElementsByTagName("id").Item(0).Text
mbrainzurl = "http://musicbrainz.org/ws/2/recording/" & RecordingID & "?inc=place-rels+artist-rels+work-rels+work-level-rels"
Call mbrainz.Load(mbrainzurl)
Dim cnta : cnta = 0
While (mbrainz.readyState < 4 And cnta < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cnta = cnta+1
WEnd
If mbrainz.readyState < 4 Then
Exit Sub
End If
If Grouping = "Classical" Then
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then Exit Do
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
Set mbrainztemp = mbrainz.SelectSingleNode("//recording/relation-list/relation/work/relation-list/relation/end")
If mbrainztemp Is Nothing Then
itm.UpdateDB
itm.WriteTags
Exit Do
End If
mbrainznode = mbrainz.SelectSingleNode("//recording/relation-list/relation/work/relation-list/relation/end").Text
itm.Year = Left(mbrainznode,4)
Else
Set mbrainztemp = mbrainz.SelectSingleNode("//recording/relation-list/relation/end")
If mbrainztemp Is Nothing Then
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then Exit Do
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
itm.UpdateDB
itm.WriteTags
Exit Do
End If
mbrainznode = mbrainz.SelectSingleNode("//recording/relation-list/relation/end").Text
itm.Year = Left(mbrainznode,4)
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then
itm.UpdateDB
itm.WriteTags
Exit Do
End If
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
End If
Loop While False
Call SDB.Tools.Sleep(1000)
Next
list.UpdateAll
End Sub
Re: Novice scripting - updating info from Musicbrainz
Found that there were some instances where the script would return the incorrect date or Work ID. Have adjusted accordingly.
Code: Select all
Sub SearchAcoustID
' Define variables
Dim list, itm, i, j, jnum, jcnt, jmax, jpos
Dim APIKey : APIKey = "[ENTER ACOUSTID API KEY HERE]"
Dim Grouping
Dim AcoustID
Dim Worktemp
Dim WorkID
Dim RecordingID
Dim acoustidurl
Dim mbrainzurl
Dim xml : Set xml = CreateObject("Microsoft.XMLDOM")
xml.async = False
xml.preserveWhiteSpace = True
Dim mbrainz : Set mbrainz = CreateObject("Microsoft.XMLDOM")
mbrainz.async = False
mbrainz.preserveWhiteSpace = True
Dim mbrainznode
Dim recordingidtemp
Dim recordingidtemp1
Dim mbrainztemp
Dim workidtemp
Dim workurl
Dim workxml : Set workxml = CreateObject("Microsoft.XMLDOM")
workxml.async = False
workxml.preserveWhiteSpace = True
Dim mbrainzlist
RecordingID = ""
WorkID = ""
' Get list of selected tracks from MediaMonkey
Set list = SDB.CurrentSongList
If list.Count=0 Then
Exit Sub
End If
' Process all selected tracks
For i=0 To list.count-1
Do
Set itm = list.Item(i)
Grouping = itm.Grouping
AcoustID = itm.Custom5
acoustidurl = "http://api.acoustid.org/v2/lookup?format=xml&client=" & APIKey & "&meta=recordingids+sources&trackid=" & AcoustID
Call xml.Load(acoustidurl)
Dim cnt : cnt = 0
While (xml.readyState < 4 And cnt < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cnt = cnt+1
WEnd
If xml.readyState < 4 Then
Exit Sub
End If
jnum = 0
jcnt = -1
jmax = 0
jpos = 0
For Each j In xml.selectNodes("//sources")
jnum = CInt(j.Text)
jcnt = jcnt + 1
If jnum > jmax Then jpos = jcnt
If jnum > jmax Then jmax = jnum
Next
Set recordingidtemp = xml.getElementsByTagName("id").Item(jpos)
If recordingidtemp Is Nothing Then
If itm.Custom4 <> "" AND Grouping = "Classical" Then
WorkID = itm.Custom4
workurl = "http://musicbrainz.org/ws/2/work/" & WorkID & "?inc=artist-rels"
Call workxml.Load(workurl)
Dim cntb : cntb = 0
While (workxml.readyState < 4 And cntb < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cntb = cntb+1
WEnd
If workxml.readyState < 4 Then
Exit Sub
End If
xpath = "//relation[@type='composer']/end"
Set mbrainztemp = workxml.SelectSingleNode(xpath)
If mbrainztemp Is Nothing Then Exit Do
mbrainznode = mbrainztemp.Text
itm.Year = Left(mbrainznode,4)
itm.UpdateDB
itm.WriteTags
End If
Exit Do
End If
RecordingID = recordingidtemp.Text
mbrainzurl = "http://musicbrainz.org/ws/2/recording/" & RecordingID & "?inc=place-rels+artist-rels+work-rels+work-level-rels"
Call mbrainz.Load(mbrainzurl)
Dim cnta : cnta = 0
While (mbrainz.readyState < 4 And cnta < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cnta = cnta+1
WEnd
If mbrainz.readyState < 4 Then
Exit Sub
End If
If Grouping = "Classical" Then
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then Exit Do
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
xpath = "//relation[@type='composer']/end"
Set mbrainztemp = mbrainz.SelectSingleNode(xpath)
If mbrainztemp Is Nothing Then
itm.UpdateDB
itm.WriteTags
Exit Do
End If
mbrainznode = mbrainztemp.Text
itm.Year = Left(mbrainznode,4)
Else
xpath = "//relation-list[@target-type='place']/relation/end"
Set mbrainztemp = mbrainz.SelectSingleNode(xpath)
If mbrainztemp Is Nothing Then
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then Exit Do
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
itm.UpdateDB
itm.WriteTags
Exit Do
End If
mbrainznode = mbrainztemp.Text
itm.Year = Left(mbrainznode,4)
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then
itm.UpdateDB
itm.WriteTags
Exit Do
End If
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
End If
Loop While False
Call SDB.Tools.Sleep(1000)
Next
list.UpdateAll
End Sub
Re: Novice scripting - updating info from Musicbrainz
Err, OK, found instances where the AcoustID search returns no recording IDs but then the script still treats classical works like other works and doesn't search by work ID if present. Fixed in this version, so more results will be returned for classical works (assuming Grouping=Classical and the work ID is present and stored in Custom4).
Code: Select all
Sub SearchAcoustID
' Define variables
Dim list, itm, i, j, jnum, jcnt, jmax, jpos
Dim APIKey : APIKey = "[INSERT ACOUSTID API KEY HERE]"
Dim Grouping
Dim AcoustID
Dim Worktemp
Dim WorkID
Dim RecordingID
Dim acoustidurl
Dim mbrainzurl
Dim xml : Set xml = CreateObject("Microsoft.XMLDOM")
xml.async = False
xml.preserveWhiteSpace = True
Dim mbrainz : Set mbrainz = CreateObject("Microsoft.XMLDOM")
mbrainz.async = False
mbrainz.preserveWhiteSpace = True
Dim mbrainznode
Dim recordingidtemp
Dim recordingidtemp1
Dim mbrainztemp
Dim workidtemp
Dim workurl
Dim workxml : Set workxml = CreateObject("Microsoft.XMLDOM")
workxml.async = False
workxml.preserveWhiteSpace = True
Dim mbrainzlist
RecordingID = ""
WorkID = ""
' Get list of selected tracks from MediaMonkey
Set list = SDB.CurrentSongList
If list.Count=0 Then
Exit Sub
End If
' Process all selected tracks
For i=0 To list.count-1
Do
Set itm = list.Item(i)
Grouping = itm.Grouping
AcoustID = itm.Custom5
acoustidurl = "http://api.acoustid.org/v2/lookup?format=xml&client=" & APIKey & "&meta=recordingids+sources&trackid=" & AcoustID
Call xml.Load(acoustidurl)
Dim cnt : cnt = 0
While (xml.readyState < 4 And cnt < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cnt = cnt+1
WEnd
If xml.readyState < 4 Then
Exit Sub
End If
jnum = 0
jcnt = -1
jmax = 0
jpos = 0
For Each j In xml.selectNodes("//sources")
jnum = CInt(j.Text)
jcnt = jcnt + 1
If jnum > jmax Then jpos = jcnt
If jnum > jmax Then jmax = jnum
Next
Set recordingidtemp = xml.getElementsByTagName("id").Item(jpos)
If recordingidtemp Is Nothing OR jmax = 0 Then
If itm.Custom4 <> "" AND Grouping = "Classical" Then
WorkID = itm.Custom4
workurl = "http://musicbrainz.org/ws/2/work/" & WorkID & "?inc=artist-rels"
Call workxml.Load(workurl)
Dim cntb : cntb = 0
While (workxml.readyState < 4 And cntb < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cntb = cntb+1
WEnd
If workxml.readyState < 4 Then
Exit Sub
End If
xpath = "//relation[@type='composer']/end"
Set mbrainztemp = workxml.SelectSingleNode(xpath)
If mbrainztemp Is Nothing Then Exit Do
mbrainznode = mbrainztemp.Text
itm.Year = Left(mbrainznode,4)
itm.UpdateDB
itm.WriteTags
End If
Exit Do
End If
RecordingID = recordingidtemp.Text
mbrainzurl = "http://musicbrainz.org/ws/2/recording/" & RecordingID & "?inc=place-rels+artist-rels+work-rels+work-level-rels"
Call mbrainz.Load(mbrainzurl)
Dim cnta : cnta = 0
While (mbrainz.readyState < 4 And cnta < 300)
Call SDB.Tools.Sleep(100)
SDB.ProcessMessages
cnta = cnta+1
WEnd
If mbrainz.readyState < 4 Then
Exit Sub
End If
If Grouping = "Classical" Then
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then Exit Do
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
xpath = "//relation[@type='composer']/end"
Set mbrainztemp = mbrainz.SelectSingleNode(xpath)
If mbrainztemp Is Nothing Then
itm.UpdateDB
itm.WriteTags
Exit Do
End If
mbrainznode = mbrainztemp.Text
itm.Year = Left(mbrainznode,4)
Else
xpath = "//relation-list[@target-type='place']/relation/end"
Set mbrainztemp = mbrainz.SelectSingleNode(xpath)
If mbrainztemp Is Nothing Then
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then Exit Do
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
itm.UpdateDB
itm.WriteTags
Exit Do
End If
mbrainznode = mbrainztemp.Text
itm.Year = Left(mbrainznode,4)
Set Worktemp = mbrainz.getElementsByTagName("work").Item(0)
If Worktemp Is Nothing Then
itm.UpdateDB
itm.WriteTags
Exit Do
End If
WorkID = Worktemp.getAttribute("id")
itm.Custom4 = WorkID
End If
Loop While False
Call SDB.Tools.Sleep(1000)
Next
list.UpdateAll
End Sub