{"id":48,"date":"2005-03-29T23:33:56","date_gmt":"2005-03-30T04:33:56","guid":{"rendered":"http:\/\/crschmidt.net\/blog\/?p=48"},"modified":"2005-03-29T23:33:56","modified_gmt":"2005-03-30T04:33:56","slug":"more-musicbrainz","status":"publish","type":"post","link":"https:\/\/crschmidt.net\/blog\/archives\/48\/more-musicbrainz\/","title":{"rendered":"More Musicbrainz&#8230;"},"content":{"rendered":"<p>What I posted about yesterday was obviously too ridiculously difficult to actually be a real solution to the problem. So, I set about making something that works at least a little bit better.<\/p>\n<p>It&#8217;s possible to generate &#8220;TRM&#8221;s for songs you have. These TRMs are basically accoustic identifiers for the track: they let you identify the song based on the way it sounds. This is how Musicbrainz does its identification. Yesterday, I installed a bunch of musicbrainz stuff in an effort to get this working, and did end up finding something that will generate TRM files. My current song, Chumbawumba&#8217;s Tubthumping, has a TRM of 776643d0-9b47-4eb9-8d29-608fa9ccedcd.<\/p>\n<p>So, I can generate TRMs: but that doesn&#8217;t get me very far. Now, I need to figure out the actual track associated. Since I&#8217;m doing this mostly non-interactively, I&#8217;m just going to use the most popular track with that TRM. (This doesn&#8217;t always work: for me so far this evening, it&#8217;s given me a ~80% accuracy rate). So, I fetch the RDF version of the TRM file: this can be retrieved from http:\/\/musicbrainz.org\/trmid\/776643d0-9b47-4eb9-8d29-608fa9ccedcd for the song I mentioned earlier.<\/p>\n<p>The first song in the &#8220;tracklist&#8221; RDF bag is the one that is the best match, so I&#8217;ll grab that Track. I can then add that URI, and fetch the creator ID from that file. All these files can be tossed into the general RDF model I keep lying around, along with the turtle that I mentioned in the earlier entry: [a foaf:Person; foaf:nick &#8220;crschmidt&#8221;;  menow:hasStatus [a menow:Status; dc:date &#8220;timestamp&#8221;; menow:listeningTo &lt;trackuri>]].<\/p>\n<p>Then, I can issue a query against the model: since I know the time, I only return the most recent result:<\/p>\n<p>select ?t, ?n, ?d where (?p foaf:nick &#8220;crschmidt&#8221;) (?p menow:hasStatus ?s) (?s dc:date ?d) (?s menow:listeningTo ?o) (?o dc:title ?t) (?o dc:creator ?a) (?a dc:title ?n) AND ?d =~ \/timestamp\/<\/p>\n<p>The end result? A couple hundred extra triples loaded into the global model, and I can see:<\/p>\n<p>23:23:56 &lt;crschmidt> ^listeningTo 776643d0-9b47-4eb9-8d29-608fa9ccedcd<br \/>\n23:24:02 &lt;julie>  2005-03-30T04:24:01Z Tubthumping Chumbawamba<\/p>\n<p>Some of the tracks I&#8217;ve been listening to tonight can be shown via:^q select ?t, ?n, ?d where (?p foaf:nick &#8220;crschmidt&#8221;) (?p menow:hasStatus ?s) (?s dc:date ?d) (?s menow:listeningTo ?o) (?o dc:title ?t) (?o dc:creator ?a) (?a dc:title ?n) AND ?d =~ \/2005-03-30\/. Feel free to stop by #julie on irc.freenode.net and try it!<br \/>\n<!--more--><br \/>\nCode for the above function in Julie:<\/p>\n<pre>mm = RDF.NS(\"http:\/\/musicbrainz.org\/mm\/mm-2.0#\")                                                                            \nrdf = RDF.NS(\"http:\/\/www.w3.org\/1999\/02\/22-rdf-syntax-ns#\")                                                                 \ndc = RDF.NS(\"http:\/\/purl.org\/dc\/elements\/1.1\/\")                                                                             \nmodel = RDF.Model(get_storage(self.db_password))\ntrm = m.group(1)                                                                                                            \nm = RDF.Model()                                                                                                             \np = RDF.Parser()                                                                                                            \np.parse_into_model(m, \"http:\/\/musicbrainz.org\/trmid\/%s\"%trm)                                                                \np.parse_into_model(model, \"http:\/\/musicbrainz.org\/trmid\/%s\"%trm)                                                            \ntl = m.find_statements(RDF.Statement(None, mm.trackList, None))                                                             \ntracklistBag = tl.current().object                                                                                          \nt1 = m.find_statements(RDF.Statement(tracklistBag, rdf['_1'], None))                                                        \ntrackId = t1.current().object.uri                                                                                           \np.parse_into_model(m, trackId)                                                                                              \np.parse_into_model(model, trackId)                                                                                      \nc = m.find_statements(RDF.Statement(trackId, dc.creator, None))                                                             \ncreator = c.current().object.uri                                                                                                                                                                                                                                \np.parse_into_model(model, creator)                                                                                                                                                                                                                              \ntp = RDF.TurtleParser()                                                                                                     \ntimestamp = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())                                                              \nturtle =  \"\"\"[a foaf:Person; foaf:nick \"%s\"; \n menow:hasStatus [a menow:Status; dc:date \"%s\"; \n menow:listeningTo < %s>]].\"\"\" \n    % (split_origin(origin)[0], timestamp, trackId)                                                                                       \nturtlestr = turtle                                                                                                          \nfor key, value in common_namespaces().items() :                                                                             \n    turtlestr = \"@prefix %s: < %s> .\\n%s\" % (key, value, turtlestr)                                                          \ntp.parse_string_into_model(model,\n  turtlestr,RDF.Uri(\"http:\/\/crschmidt.net\/julie\/data\/\"))                                   \nself.query_thread(\"\"\"select ?t, ?n, ?d where (?p foaf:nick \"%s\") \n  (?p menow:hasStatus ?s) \n  (?s dc:date ?d) \n  (?s menow:listeningTo ?o) \n  (?o dc:title ?t) \n  (?o dc:creator ?a) \n  (?a dc:title ?n) AND ?d =~ \/%s\/\"\"\" \n  % (split_origin(origin)[0], timestamp) ,origin,args,model)                                                                                                                                \n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>What I posted about yesterday was obviously too ridiculously difficult to actually be a real solution to the problem. So, I set about making something that works at least a little bit better. It&#8217;s possible to generate &#8220;TRM&#8221;s for songs you have. These TRMs are basically accoustic identifiers for the track: they let you identify [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25,8],"tags":[],"class_list":["post-48","post","type-post","status-publish","format-standard","hentry","category-menow","category-rdfcat"],"_links":{"self":[{"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/posts\/48","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/comments?post=48"}],"version-history":[{"count":0,"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/posts\/48\/revisions"}],"wp:attachment":[{"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/media?parent=48"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/categories?post=48"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/crschmidt.net\/blog\/wp-json\/wp\/v2\/tags?post=48"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}