Article
Build a Yahoo Music Mashup with Adobe AIR
Mashing up the Yahoo Music API
The first thing you need to access the user-friendly Yahoo Music API, is an API key; you can apply for one directly from the Yahoo Developer Network home page. When you have an API key, you can use it to perform one of any number of Yahoo Music API calls. For example, you can do an API search that, when given an artist name, returns a list of matching artists along with their videos. You can then store these videos in an SQLite database, so that you don’t have to make the same query from Yahoo again.
Our Artists list object now pulls data from Yahoo and iTunes, and manages a cached database of videos. The complete code listing for this object is quite long, so I’ll only talk about the key functionality. If you’re interested in exploring any of the other methods contained in this class, be sure to download the code archive for this tutorial.
The differences start in the constructor, where I build an SQLite database in a file called artists.db.
File: Artists.as
public function Artists()
{
super();
_sqlConnection = new SQLConnection();
var dbFile:File = File.applicationStorageDirectory.resolvePath( "artists.db" );
_sqlConnection.open( dbFile );
var artCreateStmt:SQLStatement = new SQLStatement();
artCreateStmt.sqlConnection = _sqlConnection;
artCreateStmt.text = 'CREATE TABLE IF NOT EXISTS artist ( artistName VARCHAR( 128 ), artistID VARCHAR( 32 ) )';
artCreateStmt.execute();
var vidCreateStmt:SQLStatement = new SQLStatement();
vidCreateStmt.sqlConnection = _sqlConnection;
vidCreateStmt.text = 'CREATE TABLE IF NOT EXISTS video ( artistID VARCHAR( 32 ), year INT, videoID VARCHAR( 32 ), name VARCHAR( 128 ) )';
vidCreateStmt.execute();
}
As you can see from the code above, our artists.db database has two tables: Artist and Video. As the names suggest, the Artist table stores the name of the artists and their IDs, which are supplied by Yahoo, while the Video table stores information about the videos for each artist. This includes the artist ID, the year of the video, the video ID (required for video thumbnails), and the name of the video.
With this in hand, we need to upgrade our onTimer method to retrieve the artist ID from the database–if it’s known. The onTimer method also triggers the Yahoo scanning portion of the list creation, if the iTunes scanning has completed. This is done by invoking the updateArtistData method:
File: Artists.as
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 };
var fetchIdStmt:SQLStatement = new SQLStatement();
fetchIdStmt.sqlConnection = _sqlConnection;
fetchIdStmt.text = 'SELECT * FROM artist WHERE artistName=:name';
fetchIdStmt.parameters[':name'] = artName;
fetchIdStmt.execute();
var fetchResult:SQLResult = fetchIdStmt.getResult();
for each ( var row:Object in fetchResult.data ) {
_artists[ artName ].artistID = row.artistID;
}
_artistCount++;
} else
_artists[ artName ].count += 1;
}
}
dispatchEvent( new ArtistEvent( ArtistEvent.ARTIST_LIST_CHANGE ) );
}
else
{
if ( updateArtistData() == false ) {
_timer.stop();
dispatchEvent( new ArtistEvent( ArtistEvent.YAHOO_UPDATE_COMPLETE ) );
}
}
}
The updateArtistData method first checks to see whether a request to Yahoo is in process. If there is a pending request, it lets this invocation go. If there is no request in process, then it looks to find the first artist for which no ArtistID is assigned. It then makes a request of Yahoo to search for that artist. Here’s what that method looks like:
File: Artists.as
private function updateArtistData() : Boolean {
if ( _searchingYahoo == false ) {
dispatchEvent( new ArtistEvent( ArtistEvent.STARTING_YAHOO_SEARCH ) );
_searchingYahoo = true;
}
if ( _artistSearch == null ) {
_yahooSearchTotal = 0;
_yahooSearchCompleted = 0;
// Find any artist that doens't have an AristID associated with it
var artist:Object = null;
for each ( var art:Object in artists ) {
if ( art.artistID == null ) {
if ( artist != null )
artist = art;
_yahooSearchCompleted++;
}
_yahooSearchTotal++;
}
if ( artist == null )
return false;
// Send a search request to Yahoo for that artist
_searchingArtist = artist.name;
_artistSearch = new HTTPService();
_artistSearch.addEventListener( ResultEvent.RESULT, onArtistResult );
_artistSearch.addEventListener( FaultEvent.FAULT, onArtistFault );
_artistSearch.url = "http://us.music.yahooapis.com/artist/v1/list/search/artist/"+escape(artist.name)+"?appid="+Constants.APPID+"&response=videos";
_artistSearch.resultFormat = 'e4x';
_artistSearch.send();
}
return true;
}
Search results are sent to either onArtistResult or onArtistFault. In the case of a failure, we set the ArtistID to blank. If a result is recorded, we find the first artist listed and store that ArtistID along with the list of videos in the database.
The remaining methods in this class provide information about the artist list. As you can see, their names are self-explanatory. For example, videosMinYear and videosMaxYear return the minimum and maximum year values in the database, respectively; The getVideosByYear method returns an array of the videos for any given year. I won’t list them all here; feel free to poke around the code archive—the code is well commented.