<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Code Train &#187; itunes</title>
	<atom:link href="http://thecodetrain.co.uk/tag/itunes/feed/" rel="self" type="application/rss+xml" />
	<link>http://thecodetrain.co.uk</link>
	<description>Where Neil Crosby talks about coding on the train...</description>
	<lastBuildDate>Sun, 03 Apr 2011 18:15:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Using last.fm tags to make awesome playlists in your local iTunes library</title>
		<link>http://thecodetrain.co.uk/2010/08/using-last-fm-tags-to-make-awesome-playlists-in-your-local-itunes-library/</link>
		<comments>http://thecodetrain.co.uk/2010/08/using-last-fm-tags-to-make-awesome-playlists-in-your-local-itunes-library/#comments</comments>
		<pubDate>Wed, 18 Aug 2010 18:00:15 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[last.fm]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[tags]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=484</guid>
		<description><![CDATA[<p>As I&#8217;ve mentioned previously, I have a large music collection that I manage using iTunes.  One of the problems with any large collection is the curation and management that goes with it.  I carry my iPhone around with me and I listen to music on it, but even the biggest iPhone available would hold only  fifth of my collection.  So, I need techniques for pulling interesting music from my iTunes library into my iPhone.</p>

<p>Up until now I&#8217;ve used a collection of Smart Playlists which take into account my ratings, when I last listened to songs and a whole bunch of other information.  At the last count, I had over 70 Smart Playlists feeding into each other to generate the playlists which finally get Synced over to my iPhone.</p>

<p>But there was something missing.  Whilst I could generate playlists based on the mid-90s simplicity of the &#8220;Genre&#8221; tag, that tag is by design only able to identify one piece of information.  So I wouldn&#8217;t be able to find, for example, all tracks in my collection that are &#8220;rock&#8221;, &#8220;funny&#8221; and performed by a &#8220;female&#8221;.  And even if I could, I wouldn&#8217;t want to go and tag 40,000 tracks by hand. That way madness lies.</p>

<p>It turns out there&#8217;s a fairly simple solution to this &#8211; last.fm allows users to tag any and all tracks it knows about, and it keeps track of how many times each track has been tagged with each tag.  So, it&#8217;s entirely possible to grab the top 15 tags for each track in my collection, add that data to my tracks somehow, and then query that.</p>

<p>The somehow turns out to be pretty simple too &#8211; the ID3 &#8220;comment&#8221; field is there for the taking, and by design is expected to be larger than any other field.  Excellent.  So that&#8217;s the &#8220;where to store&#8221; sorted, now how about &#8220;how to store so that the data is queryable&#8221;?</p>

<p>For this I took <a href="http://www.xml.com/pub/a/2007/09/04/parsing-microformats.html?page=2">a trick out of Brian Suda&#8217;s book</a>.  A couple of years back I took a look at how he&#8217;d written his microformats parser using XSLT to be able to check for classes an element may or may not have &#8211; the trick being to wrap strings of classes with a space at the beginning and end so that every class <em>always</em> had spaces surrounding it.  I used the same trick for storing my tag data, also wrapping it in a &#8216;lfm&#8217; square bracketed enclosure to separate it from any other data in the comment.</p>

<p>So, the data I saved in the comment looked a little something like this:</p>

<pre><code>[lfm: tag1 tag2 tag23 tag3 ]
</code></pre>

<p>You&#8217;re probably starting to see why wrapping in spaces is important now.  Because iTunes&#8217; Smart Playlist system can only perform simple string matching (Apple doesn&#8217;t seem to like regexes &#8211; AppleScript can&#8217;t do them natively either), you need some way of targetting the beginning and end of tags. Without those spaces, a query of &#8220;<code>Comments contains 'tag2'</code>&#8221; would return you both <code>tag2</code> and <code>tag23</code>, which no-one wants.  By requesting &#8220;<code>Comments contains ' tag2 '</code>&#8221; instead (note the extra spaces) you end up just being given <code>tag2</code>.</p>

<p>All this thinking is packaged up into a <a href="http://github.com/NeilCrosby/itunes-helpers/commit/b94cf1f2c28bdc2b83129b458e0e6bc42573afdb">couple of scripts</a> (though obviously take <a href="http://github.com/NeilCrosby/itunes-helpers/tree/master/playlist/lastfm/">the latest code</a> if you want to actually use it yourself) I wrote a couple of days ago that takes a given playlist from your iTunes library, asks last.fm for tags for each of the songs in that playlist, and then adds that data to the library using AppleScript.</p>

<h2>Problems?</h2>

<p>There are, unfortunately, a couple of issues with the script at the moment.  First off, because last.fm allows anything and everything to be given as a tag, they can contain characters that need to be normalised out.  Right now I&#8217;m doing that very simply (spaces to dashes mostly), but I should revisit the code and harden that normalisation &#8211; I&#8217;ve seen tagging bail out a couple of times because of unexpected data.</p>

<p>Next up, the fact that last.fm allows tags to be incredibly long coupled with the fact that under ID3 v2.x the comments field can only be 256 characters long means that it&#8217;s possible to run into issues with tagsets being too long to fit into the comments field.  Add that to the fact that some songs in my collection legitimately contain comments already and that I want to add tags non-destructively, and we&#8217;re ending up with not much space for tags.  So, an improvement that I&#8217;m planning on making to the script is to make sure that tags try to take up no more than the space that&#8217;s legitimately available to them.</p>

<p>The final issue that I&#8217;ve been having lives with last.fm&#8217;s track.getTopTags API method.  Unfortunately at present the track.getTopTags API method does not perform any auto-correction of track names, which means that if you try to get the tags for something that does get auto-corrected by the system then you end up with the tags for the uncorrected track name. A subtle distinction, but it probably means that we end up with unmaintained tags that haven&#8217;t been touched for the year or so since auto-correction was turned on. A possible solution here if last.fm choose not to &#8220;fix&#8221; this behaviour (it could be argued that this is correct behaviour) would be to make a request out to Musicbrainz to get an ID for the track and then pass that into track.getTopTags instead.  But that seems like a whole bunch of extra work for a not massive gain.</p>

<h2>The final Smart Playlist</h2>

<p>So, what about that Smart Playlist? After all, that&#8217;s the thing that all this work was done for.</p>

<p>In iTunes, select <code>File</code>, <code>New Smart Playlist</code>, and then enter the following:</p>

<pre><code>Match all of the following rules:
    Comments contains ' female '
    Comments contains ' rock ' ...
    any of the following rules:
        Comments contains ' comedy '
        Comments contains ' funny '
</code></pre>

<p>This cunning playlist uses a Smart Playlist feature I wasn&#8217;t aware of until yesterday &#8211; rule groups.  Up until now, I&#8217;d been pulling in other Smart Playlists as sources to perform the same job.</p>

<p>To create a new rule group in a Smart Playlist, simply click an ellipsis button in the Smart Playlist interface, rather than clicking on the plus button.</p>

<p>Essentially what these rule groups give you is the ability to nest rulesets, and generate very complex playlists that don&#8217;t have half their rules hidden in external playlists.  In the playlist above we&#8217;re simply asking for all tracks tagged with &#8220;female&#8221;, &#8220;rock&#8221; and either &#8220;funny&#8221; or &#8220;comedy&#8221;. So essentially &#8220;female comedy rock&#8221;.  At present this playlist returns me no items from my collection, but not everything&#8217;s been tagged yet.  I&#8217;m hopeful.</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;ve mentioned previously, I have a large music collection that I manage using iTunes.  One of the problems with any large collection is the curation and management that goes with it.  I carry my iPhone around with me and I listen to music on it, but even the biggest iPhone available would hold only  fifth of my collection.  So, I need techniques for pulling interesting music from my iTunes library into my iPhone.</p>

<p>Up until now I&#8217;ve used a collection of Smart Playlists which take into account my ratings, when I last listened to songs and a whole bunch of other information.  At the last count, I had over 70 Smart Playlists feeding into each other to generate the playlists which finally get Synced over to my iPhone.</p>

<p>But there was something missing.  Whilst I could generate playlists based on the mid-90s simplicity of the &#8220;Genre&#8221; tag, that tag is by design only able to identify one piece of information.  So I wouldn&#8217;t be able to find, for example, all tracks in my collection that are &#8220;rock&#8221;, &#8220;funny&#8221; and performed by a &#8220;female&#8221;.  And even if I could, I wouldn&#8217;t want to go and tag 40,000 tracks by hand. That way madness lies.</p>

<p>It turns out there&#8217;s a fairly simple solution to this &#8211; last.fm allows users to tag any and all tracks it knows about, and it keeps track of how many times each track has been tagged with each tag.  So, it&#8217;s entirely possible to grab the top 15 tags for each track in my collection, add that data to my tracks somehow, and then query that.</p>

<p>The somehow turns out to be pretty simple too &#8211; the ID3 &#8220;comment&#8221; field is there for the taking, and by design is expected to be larger than any other field.  Excellent.  So that&#8217;s the &#8220;where to store&#8221; sorted, now how about &#8220;how to store so that the data is queryable&#8221;?</p>

<p>For this I took <a href="http://www.xml.com/pub/a/2007/09/04/parsing-microformats.html?page=2">a trick out of Brian Suda&#8217;s book</a>.  A couple of years back I took a look at how he&#8217;d written his microformats parser using XSLT to be able to check for classes an element may or may not have &#8211; the trick being to wrap strings of classes with a space at the beginning and end so that every class <em>always</em> had spaces surrounding it.  I used the same trick for storing my tag data, also wrapping it in a &#8216;lfm&#8217; square bracketed enclosure to separate it from any other data in the comment.</p>

<p>So, the data I saved in the comment looked a little something like this:</p>

<pre><code>[lfm: tag1 tag2 tag23 tag3 ]
</code></pre>

<p>You&#8217;re probably starting to see why wrapping in spaces is important now.  Because iTunes&#8217; Smart Playlist system can only perform simple string matching (Apple doesn&#8217;t seem to like regexes &#8211; AppleScript can&#8217;t do them natively either), you need some way of targetting the beginning and end of tags. Without those spaces, a query of &#8220;<code>Comments contains 'tag2'</code>&#8221; would return you both <code>tag2</code> and <code>tag23</code>, which no-one wants.  By requesting &#8220;<code>Comments contains ' tag2 '</code>&#8221; instead (note the extra spaces) you end up just being given <code>tag2</code>.</p>

<p>All this thinking is packaged up into a <a href="http://github.com/NeilCrosby/itunes-helpers/commit/b94cf1f2c28bdc2b83129b458e0e6bc42573afdb">couple of scripts</a> (though obviously take <a href="http://github.com/NeilCrosby/itunes-helpers/tree/master/playlist/lastfm/">the latest code</a> if you want to actually use it yourself) I wrote a couple of days ago that takes a given playlist from your iTunes library, asks last.fm for tags for each of the songs in that playlist, and then adds that data to the library using AppleScript.</p>

<h2>Problems?</h2>

<p>There are, unfortunately, a couple of issues with the script at the moment.  First off, because last.fm allows anything and everything to be given as a tag, they can contain characters that need to be normalised out.  Right now I&#8217;m doing that very simply (spaces to dashes mostly), but I should revisit the code and harden that normalisation &#8211; I&#8217;ve seen tagging bail out a couple of times because of unexpected data.</p>

<p>Next up, the fact that last.fm allows tags to be incredibly long coupled with the fact that under ID3 v2.x the comments field can only be 256 characters long means that it&#8217;s possible to run into issues with tagsets being too long to fit into the comments field.  Add that to the fact that some songs in my collection legitimately contain comments already and that I want to add tags non-destructively, and we&#8217;re ending up with not much space for tags.  So, an improvement that I&#8217;m planning on making to the script is to make sure that tags try to take up no more than the space that&#8217;s legitimately available to them.</p>

<p>The final issue that I&#8217;ve been having lives with last.fm&#8217;s track.getTopTags API method.  Unfortunately at present the track.getTopTags API method does not perform any auto-correction of track names, which means that if you try to get the tags for something that does get auto-corrected by the system then you end up with the tags for the uncorrected track name. A subtle distinction, but it probably means that we end up with unmaintained tags that haven&#8217;t been touched for the year or so since auto-correction was turned on. A possible solution here if last.fm choose not to &#8220;fix&#8221; this behaviour (it could be argued that this is correct behaviour) would be to make a request out to Musicbrainz to get an ID for the track and then pass that into track.getTopTags instead.  But that seems like a whole bunch of extra work for a not massive gain.</p>

<h2>The final Smart Playlist</h2>

<p>So, what about that Smart Playlist? After all, that&#8217;s the thing that all this work was done for.</p>

<p>In iTunes, select <code>File</code>, <code>New Smart Playlist</code>, and then enter the following:</p>

<pre><code>Match all of the following rules:
    Comments contains ' female '
    Comments contains ' rock ' ...
    any of the following rules:
        Comments contains ' comedy '
        Comments contains ' funny '
</code></pre>

<p>This cunning playlist uses a Smart Playlist feature I wasn&#8217;t aware of until yesterday &#8211; rule groups.  Up until now, I&#8217;d been pulling in other Smart Playlists as sources to perform the same job.</p>

<p>To create a new rule group in a Smart Playlist, simply click an ellipsis button in the Smart Playlist interface, rather than clicking on the plus button.</p>

<p>Essentially what these rule groups give you is the ability to nest rulesets, and generate very complex playlists that don&#8217;t have half their rules hidden in external playlists.  In the playlist above we&#8217;re simply asking for all tracks tagged with &#8220;female&#8221;, &#8220;rock&#8221; and either &#8220;funny&#8221; or &#8220;comedy&#8221;. So essentially &#8220;female comedy rock&#8221;.  At present this playlist returns me no items from my collection, but not everything&#8217;s been tagged yet.  I&#8217;m hopeful.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2010/08/using-last-fm-tags-to-make-awesome-playlists-in-your-local-itunes-library/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Displaying your current remote iTunes Playlist on your local Mac&#8217;s Dashboard</title>
		<link>http://thecodetrain.co.uk/2009/11/displaying-your-current-remote-itunes-playlist-on-your-local-macs-dashboard/</link>
		<comments>http://thecodetrain.co.uk/2009/11/displaying-your-current-remote-itunes-playlist-on-your-local-macs-dashboard/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 12:16:33 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[dashboard]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[mamp]]></category>
		<category><![CDATA[osascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scratching an itch]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=315</guid>
		<description><![CDATA[<p>In my last blog entry, I wrote about &#8220;<a href="http://thecodetrain.co.uk/2009/10/controlling-itunes-across-multiple-computers-with-the-keyboard/">Controlling iTunes across multiple computers with the keyboard</a>&#8221; (snappy title, huh?).  In it, I promised that the next step was to work out how to get the current playlist displaying on the dashboard.  So, here goes&#8230;</p>

<p><a class="sidenote" href="http://www.flickr.com/photos/thevoicewithin/4102944794/" title="Remote viewing the currently playing iTunes playlist by Neil Crosby, on Flickr"><img src="http://farm3.static.flickr.com/2475/4102944794_483cf765f4.jpg" width="500" height="313" alt="Remote viewing the currently playing iTunes playlist" /></a></p>

<p>The first thing to be aware of is that if Safari can display something on a webpage, then Dashboard can display it as well.  If you visit a page in Safari and right-click somewhere on the background of the page then you should see a menu item titled <code>Open in Dashboard...</code>. If you select this then you&#8217;ll be able to drag to select an area of the page to turn into a dashboard widget.  Click the <code>Add</code> button at the top of the window once you&#8217;re done, and you&#8217;ll magically have created a widget.  Now, any time you open up your Dashboard that widget will be reloaded and you&#8217;ll see fresh data.</p>

<p>So, that&#8217;s how we&#8217;ll display the playlist as a Dashboard Widget &#8211; we&#8217;ll create a webpage that contains the data and then use that as the widget.</p>

<p>If you read the last entry, you&#8217;ll know that I like to use AppleScript as a quick glue language on my Mac.  It&#8217;s pretty easy to use (once you know what you&#8217;re doing), and you can hook into many of the apps you use on a day to day basis and do interesting things with them.  So, it should be no surprise to hear that I&#8217;ll be using AppleScript to get the playlist data out of iTunes.  Given that I&#8217;ll be displaying this data on a webpage though I&#8217;ll be using PHP (because it&#8217;s what I know) to write a quick and dirty page that displays the data that the AppleScript provides.</p>

<p>The AppleScript is a little more involved than the one liners we used last time.  We need to grab the current playlist and then grab information about its UID, Title, Artist and Album, and before finally finding out what the currently playing track is.  Here&#8217;s how we do that.</p>

<pre><code>set tracks_list to {}

tell application "iTunes"
    tell current playlist
        tell tracks
            set tracks_list to get {persistent ID, name, artist, album}
        end tell
    end tell

    set tracks_list to tracks_list  {persistent ID of current track}
end tell

get tracks_list
</code></pre>

<p>In this script we first we create an empty list to put all our data in, then we add lists of track IDs, names, artists and albums to it, then we add a single item of the currently playing track&#8217;s ID.  It&#8217;s not the most elegant of data structures to use once we get to play with it in PHP, but it&#8217;ll do.  Running this from the commandline using <code>osascript -s s playlist.scpt</code> (the <code>-s s</code> means &#8220;print the output in a recompilable form&#8221;) gives us something like the following (respaced for clarity):</p>

<pre><code>{
    {
        "0D7D716D221B623B", 
        "688E193B9F7F7EE3", 
        "05BFA94137C9691F"
    }, 
    {
        "Fashion Is Danger", 
        "Fabulous", 
        "Never Gonna Give You Up"
    }, 
    {
        "Flight of the Conchords", 
        "High School Musical Cast", 
        "Rick Astley"
    }, 
    {
        "I Told You I Was Freaky", 
        "High School Musical 2", 
        "Fantastic 80s"
    }, 
    "688E193B9F7F7EE3"
}
</code></pre>

<p>Now that we have a data structure, we can actually do something with it in PHP.  Unfortunately, as far as I&#8217;m aware there&#8217;s nothing built into PHP that&#8217;ll read this structure. Fortunately though, this structure is pretty damn close to JSON.  If we were to replace the twiddly brackets with square ones then PHP&#8217;s <code>json_decode</code> would return a data structure and we could do something with the data.  Hooray. It&#8217;s a hack, but it works, and it&#8217;s what I did.  A simple <code>str_replace</code> later and I had data.  You can see the code, such as it is, in my <a href="http://github.com/NeilCrosby/itunes-helpers">github repository</a>.</p>

<p>The eagle eyed amongst you will notice that I&#8217;m not directly calling <code>osascript</code> from my PHP script though, and am instead going through an intermediary shell script that nukes <code>DYLD_LIBRARY_PATH</code> before running the AppleScript.  The reason for this is that on the machine I&#8217;m running the script on I&#8217;m using MAMP for my web stack, and that does funny things with <code>DYLD_LIBRARY_PATH</code> under Snow Leopard apparently.  So, I have to nuke it.</p>

<p>And that&#8217;s all there is to it.  Visit the webpage you&#8217;ve created to display the data, let it show you what&#8217;s playing and then turn it into a dashboard component using Safari.  I get to control iTunes on a remote machine and I don&#8217;t have to keep a VNC connection on it.  This makes me happy.</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>In my last blog entry, I wrote about &#8220;<a href="http://thecodetrain.co.uk/2009/10/controlling-itunes-across-multiple-computers-with-the-keyboard/">Controlling iTunes across multiple computers with the keyboard</a>&#8221; (snappy title, huh?).  In it, I promised that the next step was to work out how to get the current playlist displaying on the dashboard.  So, here goes&#8230;</p>

<p><a class="sidenote" href="http://www.flickr.com/photos/thevoicewithin/4102944794/" title="Remote viewing the currently playing iTunes playlist by Neil Crosby, on Flickr"><img src="http://farm3.static.flickr.com/2475/4102944794_483cf765f4.jpg" width="500" height="313" alt="Remote viewing the currently playing iTunes playlist" /></a></p>

<p>The first thing to be aware of is that if Safari can display something on a webpage, then Dashboard can display it as well.  If you visit a page in Safari and right-click somewhere on the background of the page then you should see a menu item titled <code>Open in Dashboard...</code>. If you select this then you&#8217;ll be able to drag to select an area of the page to turn into a dashboard widget.  Click the <code>Add</code> button at the top of the window once you&#8217;re done, and you&#8217;ll magically have created a widget.  Now, any time you open up your Dashboard that widget will be reloaded and you&#8217;ll see fresh data.</p>

<p>So, that&#8217;s how we&#8217;ll display the playlist as a Dashboard Widget &#8211; we&#8217;ll create a webpage that contains the data and then use that as the widget.</p>

<p>If you read the last entry, you&#8217;ll know that I like to use AppleScript as a quick glue language on my Mac.  It&#8217;s pretty easy to use (once you know what you&#8217;re doing), and you can hook into many of the apps you use on a day to day basis and do interesting things with them.  So, it should be no surprise to hear that I&#8217;ll be using AppleScript to get the playlist data out of iTunes.  Given that I&#8217;ll be displaying this data on a webpage though I&#8217;ll be using PHP (because it&#8217;s what I know) to write a quick and dirty page that displays the data that the AppleScript provides.</p>

<p>The AppleScript is a little more involved than the one liners we used last time.  We need to grab the current playlist and then grab information about its UID, Title, Artist and Album, and before finally finding out what the currently playing track is.  Here&#8217;s how we do that.</p>

<pre><code>set tracks_list to {}

tell application "iTunes"
    tell current playlist
        tell tracks
            set tracks_list to get {persistent ID, name, artist, album}
        end tell
    end tell

    set tracks_list to tracks_list  {persistent ID of current track}
end tell

get tracks_list
</code></pre>

<p>In this script we first we create an empty list to put all our data in, then we add lists of track IDs, names, artists and albums to it, then we add a single item of the currently playing track&#8217;s ID.  It&#8217;s not the most elegant of data structures to use once we get to play with it in PHP, but it&#8217;ll do.  Running this from the commandline using <code>osascript -s s playlist.scpt</code> (the <code>-s s</code> means &#8220;print the output in a recompilable form&#8221;) gives us something like the following (respaced for clarity):</p>

<pre><code>{
    {
        "0D7D716D221B623B", 
        "688E193B9F7F7EE3", 
        "05BFA94137C9691F"
    }, 
    {
        "Fashion Is Danger", 
        "Fabulous", 
        "Never Gonna Give You Up"
    }, 
    {
        "Flight of the Conchords", 
        "High School Musical Cast", 
        "Rick Astley"
    }, 
    {
        "I Told You I Was Freaky", 
        "High School Musical 2", 
        "Fantastic 80s"
    }, 
    "688E193B9F7F7EE3"
}
</code></pre>

<p>Now that we have a data structure, we can actually do something with it in PHP.  Unfortunately, as far as I&#8217;m aware there&#8217;s nothing built into PHP that&#8217;ll read this structure. Fortunately though, this structure is pretty damn close to JSON.  If we were to replace the twiddly brackets with square ones then PHP&#8217;s <code>json_decode</code> would return a data structure and we could do something with the data.  Hooray. It&#8217;s a hack, but it works, and it&#8217;s what I did.  A simple <code>str_replace</code> later and I had data.  You can see the code, such as it is, in my <a href="http://github.com/NeilCrosby/itunes-helpers">github repository</a>.</p>

<p>The eagle eyed amongst you will notice that I&#8217;m not directly calling <code>osascript</code> from my PHP script though, and am instead going through an intermediary shell script that nukes <code>DYLD_LIBRARY_PATH</code> before running the AppleScript.  The reason for this is that on the machine I&#8217;m running the script on I&#8217;m using MAMP for my web stack, and that does funny things with <code>DYLD_LIBRARY_PATH</code> under Snow Leopard apparently.  So, I have to nuke it.</p>

<p>And that&#8217;s all there is to it.  Visit the webpage you&#8217;ve created to display the data, let it show you what&#8217;s playing and then turn it into a dashboard component using Safari.  I get to control iTunes on a remote machine and I don&#8217;t have to keep a VNC connection on it.  This makes me happy.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2009/11/displaying-your-current-remote-itunes-playlist-on-your-local-macs-dashboard/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Controlling iTunes across multiple computers with the keyboard</title>
		<link>http://thecodetrain.co.uk/2009/10/controlling-itunes-across-multiple-computers-with-the-keyboard/</link>
		<comments>http://thecodetrain.co.uk/2009/10/controlling-itunes-across-multiple-computers-with-the-keyboard/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 12:32:56 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[keyboard control]]></category>
		<category><![CDATA[scratching an itch]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=312</guid>
		<description><![CDATA[<p>Over the last few days on Twitter I&#8217;ve been talking about my peculiar iTunes setup, and a few people have been asking me if I&#8217;ll blog about it.  So, here goes&#8230;</p>

<p>My situation is that my iTunes music library is stored on my MacMini that lives in my living room (connected to and powering my TV experience). However, most of the time I spend using my MacBook Pro, which spends most of its time in the office upstairs a fair way away from the MacMini. Because I spend most of my time at the laptop, it&#8217;s nice to have music available for me to listen to on it.  Of course, if I just wanted to <em>listen</em> to music then this would be a very short blog post &#8211; I could use iTunes to share the library from the MacMini and listen to the music upstairs, or I could use Spotify or Last.fm. The problem with these as solutions are that I make heavy use of Smart and Genius Playlists in iTunes to generate playlists of music to listen to. Using iTunes&#8217; sharing feature doesn&#8217;t allow me to rate tracks in the originating library (even with iTunes 9&#8242;s &#8220;Home Sharing&#8221; feature), and it also doesn&#8217;t generate extra playcount in the originating library for the things I listen to. This means my Smart Playlists don&#8217;t update in the expected way, and I become a sad panda. Likewise, Genius Playlists don&#8217;t work in a usable way when using a shared library, so this doesn&#8217;t really work for me.</p>

<p>What I wanted was a way to play my music using the MacMini downstairs, but have the music erupt from the speakers connected to my MacBook Pro.  As it turns out, there&#8217;s an app for that &#8211; <a href="http://www.rogueamoeba.com/airfoil/mac/">Airfoil</a>. This lovely application hijacks audio from one device and sends it out across the network to multiple other devices of your choice, all in sync. So, immediately I was able to use OSX&#8217;s Screen Sharing app to connect to my MacMini, start some music playing in iTunes and then have Airfoil pipe it out to my MacBook Pro.  It was a solution that was sheer elegance in its simplicity. Yes, you have to wait a second or so after pressing play before you hear anything come out of your speakers, but that&#8217;s down to Airfoil making sure all your devices are in sync before it starts to do anything.  All in all, it&#8217;s brilliant. It costs $25, but that&#8217;s a small price to pay for this functionality for me.</p>

<p>The only problem is that in playing music on a different computer than the one you&#8217;re on, you&#8217;re playing music on a different computer than the one you&#8217;re on.  So various things, like media keys on your keyboard don&#8217;t work in the way you expect. So, whenever I was wanting to do simple things like pause my music I was having to go into Apple&#8217;s Screen Sharing app, log into the MacMini and then press the pause button in iTunes.  Not ideal.  So, I wrote a quick AppleScript in Apple&#8217;s Script Editor:</p>

<pre><code>tell application "iTunes" of machine "eppc://macmini-2.local" to playpause
</code></pre>

<p>Yup, that&#8217;s a really simple AppleScript.  Something I wasn&#8217;t aware of until a couple of days ago is that it&#8217;s possible to run AppleScript that runs AppleScript on a different machine.  All you have to do is go into <code>System Preferences</code>, open the <code>Sharing</code> panel, and enable <code>Remote Apple Events</code>. The first time you try to run an event on the remote machine you&#8217;ll be asked to enter your credentials on the local machine, which you can save to your keychain for auto-use in the future.  Now, if I run that AppleScript then iTunes on the remote machine will toggle its play state, and consequently on my local machine.  Awesome.</p>

<p>It&#8217;s just as easy to write other scripts as well. For example, to advance to the next track, just change <code>playpause</code> to <code>play (next track)</code>.</p>

<p>But we&#8217;re still not controlling iTunes on the remote machine with just a keypress.  If you&#8217;ve got something like Quicksilver installed on your machine then you should be able to simply hook the script up to a key combination of your choice. I don&#8217;t currently have Quicksilver installed on this machine (and wasn&#8217;t about to install it just for this), so I had to find another alternative. What I&#8217;m currently using is <a href="http://www.red-sweater.com/fastscripts/">FastScripts Lite</a>, a free app that adds an icon to your menubar that contains menu items for any AppleScripts you put in a certain directory. The nice thing about FastScripts is that it also allows you to enter a keypress combo for any of these scripts by going into its <code>Preferences</code> pane and double clicking on the Shortcut field next to the relevant script. I&#8217;ve got <code>playpause</code> bound to <code>ctrl-up</code>, <code>next track</code> to <code>ctrl-right</code> and <code>previous track</code> to (you guessed it) <code>ctrl-left</code>. Now I can easily change what I&#8217;m listening to with a quick keypress, and I&#8217;m happy.</p>

<p>Well, I&#8217;m almost happy.  I still need to have Screen Sharing open so that I can see what&#8217;s actually in the playlist that I&#8217;m listening to.  There&#8217;s a solution to that as well though.  All I needed do was create a script that calls some AppleScript on the MacMini, grabs the current playlist info and then outputs it into a web page. I could then use this page as the basis of a Dashboard widget and I&#8217;d only ever have to press F12 to see my current playlist.  And that&#8217;s what I did. To find out how I did it though, you&#8217;ll have to read the <a href="http://thecodetrain.co.uk/2009/11/displaying-your-current-remote-itunes-playlist-on-your-local-macs-dashboard/">next post</a>!</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Over the last few days on Twitter I&#8217;ve been talking about my peculiar iTunes setup, and a few people have been asking me if I&#8217;ll blog about it.  So, here goes&#8230;</p>

<p>My situation is that my iTunes music library is stored on my MacMini that lives in my living room (connected to and powering my TV experience). However, most of the time I spend using my MacBook Pro, which spends most of its time in the office upstairs a fair way away from the MacMini. Because I spend most of my time at the laptop, it&#8217;s nice to have music available for me to listen to on it.  Of course, if I just wanted to <em>listen</em> to music then this would be a very short blog post &#8211; I could use iTunes to share the library from the MacMini and listen to the music upstairs, or I could use Spotify or Last.fm. The problem with these as solutions are that I make heavy use of Smart and Genius Playlists in iTunes to generate playlists of music to listen to. Using iTunes&#8217; sharing feature doesn&#8217;t allow me to rate tracks in the originating library (even with iTunes 9&#8242;s &#8220;Home Sharing&#8221; feature), and it also doesn&#8217;t generate extra playcount in the originating library for the things I listen to. This means my Smart Playlists don&#8217;t update in the expected way, and I become a sad panda. Likewise, Genius Playlists don&#8217;t work in a usable way when using a shared library, so this doesn&#8217;t really work for me.</p>

<p>What I wanted was a way to play my music using the MacMini downstairs, but have the music erupt from the speakers connected to my MacBook Pro.  As it turns out, there&#8217;s an app for that &#8211; <a href="http://www.rogueamoeba.com/airfoil/mac/">Airfoil</a>. This lovely application hijacks audio from one device and sends it out across the network to multiple other devices of your choice, all in sync. So, immediately I was able to use OSX&#8217;s Screen Sharing app to connect to my MacMini, start some music playing in iTunes and then have Airfoil pipe it out to my MacBook Pro.  It was a solution that was sheer elegance in its simplicity. Yes, you have to wait a second or so after pressing play before you hear anything come out of your speakers, but that&#8217;s down to Airfoil making sure all your devices are in sync before it starts to do anything.  All in all, it&#8217;s brilliant. It costs $25, but that&#8217;s a small price to pay for this functionality for me.</p>

<p>The only problem is that in playing music on a different computer than the one you&#8217;re on, you&#8217;re playing music on a different computer than the one you&#8217;re on.  So various things, like media keys on your keyboard don&#8217;t work in the way you expect. So, whenever I was wanting to do simple things like pause my music I was having to go into Apple&#8217;s Screen Sharing app, log into the MacMini and then press the pause button in iTunes.  Not ideal.  So, I wrote a quick AppleScript in Apple&#8217;s Script Editor:</p>

<pre><code>tell application "iTunes" of machine "eppc://macmini-2.local" to playpause
</code></pre>

<p>Yup, that&#8217;s a really simple AppleScript.  Something I wasn&#8217;t aware of until a couple of days ago is that it&#8217;s possible to run AppleScript that runs AppleScript on a different machine.  All you have to do is go into <code>System Preferences</code>, open the <code>Sharing</code> panel, and enable <code>Remote Apple Events</code>. The first time you try to run an event on the remote machine you&#8217;ll be asked to enter your credentials on the local machine, which you can save to your keychain for auto-use in the future.  Now, if I run that AppleScript then iTunes on the remote machine will toggle its play state, and consequently on my local machine.  Awesome.</p>

<p>It&#8217;s just as easy to write other scripts as well. For example, to advance to the next track, just change <code>playpause</code> to <code>play (next track)</code>.</p>

<p>But we&#8217;re still not controlling iTunes on the remote machine with just a keypress.  If you&#8217;ve got something like Quicksilver installed on your machine then you should be able to simply hook the script up to a key combination of your choice. I don&#8217;t currently have Quicksilver installed on this machine (and wasn&#8217;t about to install it just for this), so I had to find another alternative. What I&#8217;m currently using is <a href="http://www.red-sweater.com/fastscripts/">FastScripts Lite</a>, a free app that adds an icon to your menubar that contains menu items for any AppleScripts you put in a certain directory. The nice thing about FastScripts is that it also allows you to enter a keypress combo for any of these scripts by going into its <code>Preferences</code> pane and double clicking on the Shortcut field next to the relevant script. I&#8217;ve got <code>playpause</code> bound to <code>ctrl-up</code>, <code>next track</code> to <code>ctrl-right</code> and <code>previous track</code> to (you guessed it) <code>ctrl-left</code>. Now I can easily change what I&#8217;m listening to with a quick keypress, and I&#8217;m happy.</p>

<p>Well, I&#8217;m almost happy.  I still need to have Screen Sharing open so that I can see what&#8217;s actually in the playlist that I&#8217;m listening to.  There&#8217;s a solution to that as well though.  All I needed do was create a script that calls some AppleScript on the MacMini, grabs the current playlist info and then outputs it into a web page. I could then use this page as the basis of a Dashboard widget and I&#8217;d only ever have to press F12 to see my current playlist.  And that&#8217;s what I did. To find out how I did it though, you&#8217;ll have to read the <a href="http://thecodetrain.co.uk/2009/11/displaying-your-current-remote-itunes-playlist-on-your-local-macs-dashboard/">next post</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2009/10/controlling-itunes-across-multiple-computers-with-the-keyboard/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

