• Home
  • Blog
  • Portfolio
  • Links
  • Contact

Building a Web-based Media Player - Part 1

August 31, 2008

For the past month I've been tinkering with Flex and my little Linux server. One of the projects that grew out of this was a web media player with which I could listen to all my tunes wherever there happened to be some scraps of internet. This has been one of the coolest projects I've worked on in some time. It successfully blends nearly all of my programming skills: PHP/MySQL, Javascript, XML, Flex/Actionscript 3.0, and some C++. I'm going to write a series of tutorials walking through what I've done in hopes of bringing this coolness to the masses. I'm going to be fairly verbose covering subjects that any seasoned programmer can pretty much skip over. In the first installment I'm going to cover creating the database and getting song information from the MP3s.[break]

The first thing to do, obviously, is set up the database tables. I've kept my setup fairly minimalistic having tables for artists, albums, and tracks. I plan to expand later to track playback habits and so forth, but these are all you need to make your player fully functional. I've got my tables setup as follows:
artists

  • id (int 4, primary key)

  • name (varchar 100)

albums

  • id (int 4, primary key)

  • title (varchar 100)

  • artist (int 3)

tracks

  • id (int 11, primary key)

  • title (varchar 100)

  • artist (int 4)

  • album (int 4)

  • track_num (int 3)

  • play_count (int 5)

  • date_played (int 11)

Most of these fields should be self-explanitory. The tracks table can expand or contract to include what ever metadata you want (I personally left out genre as I hardly ever use that). date_played will store the Unix timestamp of the last time the song was played. I personally like storing my timestamps without formatting as to forego the unnecessary strtotime () conversion. We'll use this later when we create the recently played list.

About now I would begin to discuss how we're going to get this information into the database, but first we need to be able to get the information from the files. I've got two methods for this and it all really depends on your programming skills and what you have available on your server. The first, and most available option is through Actionscript. Let's jump to code.

  1. var tagLoader:Sound = new Sound();

  2. tagLoader.load ("my_song.mp3");

  3. tagLoader.addEventListener (Event.ID3, tagsLoadedHandler)

  4. tagLoader.addEventListener (Event.COMPLETE, tagsLoadedHandler)


  5. function tagsLoadedHandler (e:Event):void

  6. {

  7.     var title:String = tagLoader.id3.title;

  8.     var artist:String = tagLoader.id3.artist;

  9.     var album:String = tagLoader.id3.album;

  10.     var track:String = tagLoader.id3.track;

  11.     // Send to database

  12.     tagLoader.removeEventListener (Event.COMPLETE, tagsLoadedHandler);

  13. }

Lines 1-2
Nothing terribly exciting. We set up our Sound object which will be loading the MP3 and getting ID3 information. Immediately after we load the MP3 file my_song.mp3 into our Sound object.
Lines 3-4
We set up two event listeners so we can catch the data. The first fires once ID3 information has been retrieved. Depending on your MP3 file, this event won't always fire so we set up the COMPLETE event so that the code is run regardless. We'll be talking more about that in the next tutorial.
Lines 8-12
We store the song information for temporary storage until we send it all off to the database (covered in the next tutorial).
Line 13
We remove the event listener on the COMPLETE event. In the probable case that the ID3 event was dispatched we want the COMPLETE event removed otherwise all this code will run again adding your song to the database twice. We don't want to pull and iTunes with duplicate song issues.

Alright, that's the first, and slowest way to do things. I say slowest because it actually requires that the song be downloaded to your computer before it gets the information. This isn't bad if you're on a LAN connection, but it's not near as fast as using the server itself to get the information (which we'll be doing now).

We'll be writing a small C++ program that reads ID3 information out of the MP3 file and returns XML as the output. Of course, writing the code to read ID3 tags by oneself requires some time, patience, and wading through a lot of documentation. Luckily, there are several libraries out there that will serve our purposes quite nicely. The one I have chosen is TagLib. If you're running debian getting tag lib is as simple as running:

sudo apt-get install taglib-dev


Now for some code:

  1. #include <iostream>

  2. #include <taglib/tag.h>

  3. #include <taglib/fileref.h>,


  4. using namespace std;


  5. void readID3 (char *fileName)

  6. {


  7.     TagLib::FileRef f(fileName);


  8.     cout << "tt<album>" << f.tag()->album() << "</album>n";

  9.     cout << "tt<artist>" << f.tag()->artist() << "</artist>n";

  10.     cout << "tt<title>" << f.tag()->title() << "</title>n";

  11.     cout << "tt<genre>" << f.tag()->genre() << "</genre>n";

  12.     cout << "tt<year>" << f.tag()->year() << "</year>n";

  13.     cout << "tt<track>" << f.tag()->track() << "</track>n";


  14. }


  15. int main (int argc, char *argv[])

  16. {


  17.     if (argc == 1) {

  18.         printf ("Usage --ntid3xml INPUTn");

  19.         return 1;

  20.     }


  21.     cout << "<?xml version="1.0" ?>n";

  22.     cout << "<songs>n";


  23.     for (int i = 1; i < argc; i++) {

  24.         cout << "t<song file="" << argv[i] << "">n";

  25.         readID3 (argv[i]);

  26.         cout << "t</song>n";

  27.     }


  28.     cout << "</songs>n";

  29.     return 0;


  30. }

I'm going to skip all the includes and jump right into the meat.
Line 10-17
This creates our TagLib object and parses the ID3 information for the file supplied to the function. This information is the output to the console.
Lines 25-28
Checks to make sure a file was passed. If not it outputs a friendly usage guide and moves on. In actuality, since this will be later parsed by a PHP script, it would probably be a better idea to output an error code encapsulated in XML tags.
Lines 30-31
Set up the XML file structure.
Lines 33-37
Loop through every file passed and outputs the ID3 information for each.
Lines 39-40
Close up and quit.
This script has a lot of obvious advantages. First of all is speed. Since it's being run on the server, where the files are kept, there is no waiting for the song to download to get the file info. Secondly, it can parse many files at one time making batch adds possible.
Well, that concludes part one of this tutorial. Next time we'll cover adding the songs to the database utilizing what was covered in this tutorial. We'll cover both scanning an existing library and a creating a front end for adding new songs. 'Til next time, happy coding.

Tags: media player programming flash actionscript c++ tutorial
0 Comments
 

Post Comment

 

Latest Entries

  • Display Time Code in After Effects with Expressions
  • The De-evolution of Nintendo Box Asses
  • I've been killed!
  • Building a Web-based Media Player - Part 1
  • We bring you... dxprog media!
  • From the Orlando Anime Festival
  • Speed Cubing
  • Awesome Video of Errata
  • Up next on dxprog.com
  • Mograph - now with more 3D

Archives

  • November 2008
  • October 2008
  • September 2008
  • August 2008
  • July 2008
  • June 2008
  • May 2008
  • April 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007
  • February 2007
  • January 2007
  • December 2006
  • November 2006
  • October 2006
  • September 2006
  • August 2006
  • July 2006
  • June 2006
  • May 2006
  • April 2006
  • March 2006
  • January 2006
  • December 2005
  • November 2005
  • October 2005
  • September 2005
  • August 2005
  • July 2005
  • June 2005
  • June 2003
  • May 2003
  • April 2003
 
Copyright © 2005-2008 Matt Hackmann
All Rights Reserved