Article
Build a Yahoo Music Mashup with Adobe AIR
When Yahoo released the Yahoo Music application programming interface (API), I was immediately all over it! What could be cooler than playing with a data source containing musicians, bands, album listings, and videos? In this article, we’ll build an Adobe AIR application that takes advantage of this rich source of data.
The trick was getting hold of a list of my favorite artists. I could have used a search field, but that seemed kind of old school. Then it dawned on me that my local iTunes library contained all of the artists that I like; better yet, Adobe AIR would allow me to access that iTunes library, so I could take my web programming skills and use them to build a fun desktop app. So, I decided to create a mashup of my iTunes library and the Yahoo Music API.
Along the way, I learned a lot about the AIR File API and AIR’s SQLite database support, which I used to maintain a list of every Yahoo video retrieved between invocations of the app. I also learned a great deal about how to launch native sub-windows in AIR—especially managing progress bars. As you’ll soon see, these progress bars are necessary because the process of scanning iTunes and then requesting videos of each artist from Yahoo is time-consuming.
Pay attention—there will be a quiz at the end! The first 100 people to complete the quiz will win a copy of my book, Getting Started With Flex 3, delivered to their front door for FREE, thanks to Adobe. You can also download the book in PDF format for free for a limited time.
Setting up Shop
Let’s dig right in and I’ll walk you through how I built this application. Previous Adobe AIR tutorials here on SitePoint have made use of HTML, CSS and JavaScript. However, you can also create AIR applications using Adobe Flex—and that’s what we’ll be doing here. Download the code archive for this application (.zip, 2.2 MB) if you’d like to have all the code listings readily accessible.
Our first step is to set up Adobe Flex Builder 3. You can install a trial edition at no cost, or if you prefer, you can run the examples in this article by downloading the Flex software development kit (SDK) and the Air SDK. However, I’d definitely recommend downloading the Flex Builder integrated development environment (IDE), as it makes building both Flex and AIR applications a lot easier.
For this article, I’ll present the video timelines application in two parts. In the first part we’ll cover the iTunes reader that accesses the list of artists from the iTunes music catalog XML file. The second part will cover how to build an application that looks up the artists from Yahoo.
Note: This code does not currently work on Linux systems. Although AIR runs on Linux, iTunes currently does not.
Accessing the iTunes XML Database
Apple’s iTunes media player stores its complete list of songs in an XML file under the Documents directory on a Mac (My Documents on Windows). Retrieving this list of artists is as simple as opening the XML file and locating the right tags. Because this process can take a fair bit of time to perform, I’ve broken it down into two steps. The first part of the process involves opening the file and reading in all the artist tags from every track. In the second step, we’ll build the list of artists along with the tracks associated with each artist; this is done in small chunks with the aid of a timer.
As the code below shows, all of this is carried out in the Artists Singleton object. A Singleton is an object that has only one instance in the application; you access that instance by using the static instance method. I chose to make our Artists object a Singleton, because we’ll only want to have one music library open at a time in this application. The Artists Singleton object is shown below:
File: Artists.as
package com.videomashup
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.utils.ByteArray;
import flash.utils.Timer;
public class Artists extends EventDispatcher
{
private static var _artistsInstance:Artists = new Artists();
public static function get instance() : Artists {
return _artistsInstance;
}
private var _artists:Object = {};
private var _dicts:Array = [];
private var _dictsProcessed:uint = 0;
private var _dictsTotal:uint = 0;
private var _timer:Timer = null;
private var _artistCount:uint = 0;
public function get artists() : Array {
var out:Array = [];
for( var k:String in _artists )
out.push( k );
return out.sort();
}
public function get count() : uint {
return _artistCount;
}
public function get bytesLoaded() : uint {
return _dictsProcessed;
}
public function get bytesTotal() : uint {
return _dictsTotal;
}
public function Artists()
{
super();
}
public function startReader() : void {
var xmlFile:File = new File( File.userDirectory.nativePath+'/Music/iTunes/iTunes Music Library.xml' );
var bytes:ByteArray = new ByteArray();
var fileStream:FileStream = new FileStream();
fileStream.open( xmlFile, FileMode.READ );
var doc:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();
for each( var dict:XML in doc..dict.(key[2]=='Artist') )
_dicts.push( dict );
_dictsTotal = _dicts.length;
_timer = new Timer( 100 );
_timer.addEventListener(TimerEvent.TIMER,onTimer);
_timer.start();
}
private function onTimer( event:Event ) : void {
if ( _dicts.length > 0 ) {
for( var i:int = 0; i < 50; i++ ) {
var dict:XML = _dicts.pop() as XML;
if ( dict == null || _dicts.length == 0 ) {
dispatchEvent( new ArtistEvent( ArtistEvent.ITUNES_ANALYSIS_COMPLETE ) );
return;
}
_dictsProcessed++;
var art:XML = dict.string[2];
if ( art != null ) {
var artName:String = String( art );
if ( _artists[ artName ] == null ) {
_artists[ artName ] = { name:artName, count: 1 };
_artistCount++;
} else
_artists[ artName ].count += 1;
}
}
dispatchEvent( new ArtistEvent( ArtistEvent.ARTIST_LIST_CHANGE ) );
}
}
}
}
The two primary methods used here are the startReader method and the onTimer method. The startReader method parses the iTunes XML file and extracts all of the artist tags from the XML. It then creates a timer that will handle the asynchronous processing of the tags. The callback for that timer is the onTimer method.
The onTimer method processes a set amount of tags, then dispatches the ARTIST_LIST_CHANGE event to notify our application that there may be some new artists that have been added to this list. This is a custom event that’s dispatched by the Artists Singleton to notify the user that the list of artists is growing and, eventually, has been processed.
Jack Herrington is an engineer, author, and presenter who lives and works in San Francisco, USA. He writes regularly on the topics of Flex, Ajax, Silverlight, PHP, and Ruby on Rails at