Skip to content

Instantly share code, notes, and snippets.

@rornor
Created December 28, 2012 23:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rornor/98127e4a96866d0d44fa to your computer and use it in GitHub Desktop.
Save rornor/98127e4a96866d0d44fa to your computer and use it in GitHub Desktop.
foobar2000, foo_run script for creating dynamic playlist based on single track as seed. It's fully automated if foo_comserver component is available, otherwise it creates XSPF playlist which can be loaded manually.
Set XML = CreateObject("MSXML2.DOMDocument.6.0")
XML.async = False
Set ARG = WScript.Arguments
If ARG.Count < 1 Then
WScript.Echo "Usage: wscript echosong.vbs [%MUSICBRAINZ_TRACKID%|""%artist%"" ""%title%""] [interactive]"
WScript.Quit()
Else
url = "http://developer.echonest.com/api/v4/playlist/static?api_key=PKDMY7Z0SGFBW"
If Len(ARG.Item(0)) = 36 And UBound(Split(ARG.Item(0), "-")) = 4 Then
mb = MusicBrainz(ARG.Item(0)) : GetSongID mb(0), mb(1)
Else
If ARG.Count > 1 Then GetSongID ARG.Item(0), ARG.Item(1)
End If
End If
Function MusicBrainz(id)
XML.setProperty "SelectionNamespaces", "xmlns:m='http://musicbrainz.org/ns/mmd-2.0#'"
XML.loadXML(Request("http://musicbrainz.org/ws/2/recording/" & id & "?inc=artists"))
If XML.lastChild.nodeName = "error" Then
WScript.Echo "Invalid MBID!" : WScript.Quit()
Else
artist = XML.selectSingleNode(_
"m:metadata/m:recording/m:artist-credit/m:name-credit/m:artist[1]/@id").text
title = XML.selectSingleNode("m:metadata/m:recording/m:title").text
MusicBrainz = array(artist, title)
End If
End Function
Sub GetSongID(artist, title)
title = "&title=" & title
If Len(artist) = 36 And UBound(Split(artist, "-")) = 4 Then
artist = "&artist_id=musicbrainz:artist:" & artist
Else : artist = "&artist=" & artist : End If
If XML.loadXML(Request(Replace(url,"playlist/static","song/search") &_
UCase(Right("denial", 4)) & artist & title & "&format=xml")) Then
Set song = XML.selectNodes("response/songs/song[1]/id")
If song.length Then
param = "&song_id="
If ARG.item(ARG.length-1) = "interactive" Then param = Dialog & param
GetPlaylist param & song.item(0).text
Else
WScript.Echo "Seed track not found!"
End If
Else
WScript.Echo "Invalid request!"
End If
End Sub
Sub GetPlaylist(param)
XML.loadXML(Request(url & UCase(Right("denial", 4)) & param &_
"&results=100&type=song-radio&format=xml"))
On Error Resume Next
Set fb2k = CreateObject("Foobar2000.Application.0.7")
if err.number <> 0 then
WriteXSPF
Else
WriteM3U
End If
End Sub
Sub WriteXSPF()
Set XSPF = CreateObject("MSXML2.DOMDocument.6.0") : XSPF.async = False
XSPF.loadXML("<?xml version='1.0' encoding='UTF-8'?>" &_
"<playlist version='1' xmlns='http://xspf.org/ns/0/'></playlist>")
Set frag = XSPF.createDocumentFragment
Set trks = XSPF.createElement("trackList")
For Each song in XML.selectNodes("response/songs/song")
Set newElem = XSPF.createElement("track")
For Each s In song.childNodes
If s.nodeName = "artist_name" Then
Set newTag = XSPF.createElement("creator")
newTag.appendChild(XSPF.createTextNode(s.text))
newElem.appendChild(newTag)
End If
If s.nodeName = "title" Then newElem.appendChild(s)
trks.appendChild(newElem)
Next
Next
Set doc = XSPF.documentElement
frag.appendChild(trks)
doc.appendChild(frag)
path = Replace(WScript.ScriptFullName, WScript.ScriptName, "") & "echo.xspf"
XSPF.save(path) : WScript.Echo "Playlist: """ & path & """ successfully created."
End Sub
Sub WriteM3U()
Set fb2k = WScript.CreateObject("Foobar2000.Application.0.7")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set SHO = CreateObject("WScript.Shell")
path = Replace(WScript.ScriptFullName, WScript.ScriptName, "") & "echo.m3u"
Set m3u = fso.CreateTextFile(path)
Set lib = fb2k.MediaLibrary
For Each song in XML.selectNodes("response/songs/song")
For Each s In song.childNodes
If s.nodeName = "artist_name" Then qra = s.text
If s.nodeName = "title" Then qrt = s.text
Next
Set qry = lib.GetTracks("artist IS " & qra & " AND title IS " & qrt)
If qry.Count Then m3u.WriteLine qry.Item(0).Path : run = 1
Next
m3u.close : q = Chr(34)
If run Then exec = SHO.run(q & fb2k.ApplicationPath & q & " " & q & path & q, 0, 1)
End Sub
Function Dialog()
desc = desc + "max_tempo (or min_tempo):" + vbCrLf
desc = desc + " 0.0 < tempo < 500.0 (BPM)" + vbCrLf
desc = desc + "max_duration (or min_duration):" + vbCrLf
desc = desc + " 0.0 < duration < 3600.0 (seconds)" + vbCrLf
desc = desc + "max_loudness (or min_loudness):" + vbCrLf
desc = desc + " -100.0 < loudness < 100.0 (dB)" + vbCrLf
desc = desc + "max_danceability (or min_danceability):" + vbCrLf
desc = desc + " 0.0 < danceability < 1.0" + vbCrLf
desc = desc + "max_energy (or min_energy):" + vbCrLf
desc = desc + " 0.0 < energy < 1.0" + vbCrLf
desc = desc + "artist_max_familiarity (or artist_min_familiarity):" + vbCrLf
desc = desc + " 0.0 < familiarity < 1.0" + vbCrLf
desc = desc + "artist_max_hotttnesss (or artist_min_hotttnesss):" + vbCrLf
desc = desc + " 0.0 < hotttnesss < 1.0" + vbCrLf
desc = desc + "artist_start_year_before (or artist_start_year_after):" + vbCrLf
desc = desc + " 1970, 2011, present" + vbCrLf
desc = desc + "artist_end_year_before (or artist_end_year_after):" + vbCrLf
desc = desc + " 1970, 2011, present" + vbCrLf
desc = desc + "song_max_hotttnesss (or song_min_hotttnesss):" + vbCrLf
desc = desc + " 0.0 < hotttnesss < 1.0" + vbCrLf
desc = desc + "mode:" + vbCrLf
desc = desc + " (minor, major) 0, 1" + vbCrLf
desc = desc + "key:" + vbCrLf
desc = desc + " 0 - 11 (C, C#, D, Eb, E, F, F#, G, Ab, A, Bb, B)" + vbCrLf
desc = desc + vbCrLf + "--------------------"
desc = desc + vbCrLf + "Use any number or parameters separate by colon"
desc = desc + vbCrLf + "Example: ""key=3:min_tempo=150"" (w/o quotes)"
q = Trim(InputBox(desc, "Additional Parameters", ""))
If q <> "" Then
For Each p in Split(q, ":") : qp = qp & "&" & Replace(p," ", "") : Next
Dialog = qp
Else
Dialog = q
End If
End Function
Function Request(url)
Set HTTP = CreateObject("MSXML2.XMLHTTP")
HTTP.open "GET", url, False
HTTP.setRequestHeader "User-Agent", _
"Mozilla/5.0 (Windows NT 5.1; rv:12.0) Gecko/20100101 Firefox/12.0"
HTTP.send ""
If Err.number <> 0 then
WScript.Echo "Error: " & HTTP.parseError.url & vbCrLf & HTTP.parseError.Reason
WScript.Quit()
End If
Request = HTTP.responseText
End Function
@rornor
Copy link
Author

rornor commented Dec 28, 2012

Thread: link

Example foo_run action:

wscript echosong.vbs $if2(%MUSICBRAINZ_TRACKID%,"%artist%" "%title%")

or simply:

wscript echosong.vbs "%artist%" "%title%"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment