AFComponents.com

Media List MP3 Player
Updated: Jul 26, 2007   Views: 5526  
Description: This tutorial will show you how to create an MP3 player with the Media List Flash Component, the Image Loader Flash Component, and the MP3 player Flash Component.
Part I - The Completed Project

Note: We've noticed that sometimes the progress bar in this tutorial acts a little flaky. We think this is because the MP3 player starts playing the MP3 file when the buffer time is met, and Flash may not know exactly how long the file is at that point. It's not a major bug, but you can choose whether to use the progress bar or not.

To get started, here is all of the code and an example of what we are going to build. More advanced users may only need to look at this example, while others might want to read below where I will go through the code and what each part of it does. I am using the Media List Component, the IMG Loader Component (I used the Stretch one here, but you could use any of them), and the Simple MP3 Player Component to build this application.



Stage.scaleMode = "noScale";

// progress bar mc
progressBar_mc._xscale = 0;

// default gradient fill
var gradientDefault:Object = new Object;

gradientDefault.fillType = "linear";
gradientDefault.colors = [0x000000, 0x333333];
gradientDefault.alphas = [75, 75];
gradientDefault.ratios = [0, 255];
gradientDefault.matrix = new flash.geom.Matrix();
gradientDefault.matrix.createGradientBox(100, 50, (Math.PI * 3 / 2), 0, 0);

myList.itemDefaultStyle.fillGradient = gradientDefault;

// over gradient fill
var gradientOver:Object = new Object;

gradientOver.fillType = "linear";
gradientOver.colors = [0x000000, 0x333333];
gradientOver.alphas = [85, 85];
gradientOver.ratios = [0, 255];
gradientOver.matrix = new flash.geom.Matrix();
gradientOver.matrix.createGradientBox(100, 50, (Math.PI * 3 / 2), 0, 0);

myList.itemOverStyle.fillGradient = gradientOver;


// selected gradient fill
var gradientSelected:Object = new Object;

gradientSelected.fillType = "linear";
gradientSelected.colors = [0x000000, 0x333333];
gradientSelected.alphas = [95, 95];
gradientSelected.ratios = [0, 255];
gradientSelected.matrix = new flash.geom.Matrix();
gradientSelected.matrix.createGradientBox(100, 50, (Math.PI * 3 / 2), 0, 0);

myList.itemSelectedStyle.fillGradient = gradientSelected;

// play the first item when loading is complete
function listLoadHandler(evnt:Object) {

    // select first item in the list
    myList.selectItemNum(0);
   
    // get and play the first item in the list
    var item:Object = myList.getSelectedItem();
    var itemData:Array = item.data.split(",");
   
    myLoader.load(itemData[0], item.title + " - " + item.description);
}
myList.addEventListener("CONTENT_LOAD_COMPLETE", listLoadHandler);

// play an item when it is clicked
function listClickHandler(evnt:Object) {
   
    myPlayer.stop();
    progressBar_mc._xscale = 0;
    time_txt.text = "00:00";
   
    play_btn._visible = false;
    pause_btn._visible = true;
    bufferingMsg_mc._visible = true;
   
    // get and play the selected item in the list
    var itemData:Array = evnt.target.data.split(",");
   
    myLoader.load(itemData[0], evnt.target.title + " - " + evnt.target.description);
}
myList.addEventListener("ITEM_ON_RELEASE", listClickHandler);

// play the item once the image has loaded
function transCompleteHandler(evnt:Object){
   
    // get selection
    var item:Object = myList.getSelectedItem();
    var itemData:Array = item.data.split(",");
   
    // check if this track has already been loaded
    var itemIsLoaded:Boolean = false;
    var itemIndex:Number;
   
    for(var x:Number = 0; x<=myPlayer.getTotalItems(); x++) {
        var mp3:Object = myPlayer.getItemNum(x);
       
        if(mp3.path == itemData[1]) {
            itemIsLoaded = true;
            itemIndex = x;
        }
    }
   
    if(itemIsLoaded) {
        myPlayer.dspItemNum(itemIndex);
    } else {
        myPlayer.addItem(item.title + " - " + item.description, itemData[1]);
        myPlayer.dspItemNum(myPlayer.getTotalItems());
    }
   
    myPlayer.play();
}
myLoader.addEventListener("TRANSITION_END", transCompleteHandler);

// update time and playbar
function playerTimeHandler(evnt:Object){
   
    bufferingMsg_mc._visible = false;
   
    // time
    var dspTime:String  = "";
   
    // minute
    if(Math.floor(evnt.currentTime/60) < 10) {
        dspTime = "0" + String(Math.floor(evnt.currentTime/60)) + ":"
    } else {
        dspTime = String(Math.floor(evnt.currentTime/60)) + ":"
    }
   
    // second
    var seconds:Number = evnt.currentTime;
   
    if(Math.floor(evnt.currentTime/60) > 0) {
        seconds = evnt.currentTime - (Math.floor(evnt.currentTime/60) * 60);
    }
   
    if(seconds < 10) {
        dspTime += "0" + String(seconds);
    } else {
        dspTime += String(seconds);
    }
   
    time_txt.text = dspTime;
   
    // progress bar
    progressBar_mc._xscale = Math.round((evnt.currentTime/evnt.totalTime) * 100);

    if(progressBar_mc._xscale == 99) {
        progressBar_mc._xscale = 100;
    }
}
myPlayer.addEventListener("time", playerTimeHandler);

// play/pause

// hide play button
play_btn._visible = false;

// pause
pause_btn.onRelease = function() {
   
    pause_btn._visible = false;
    play_btn._visible = true;   
   
    myPlayer.pause();
}

// play
play_btn.onRelease = function() {
   
    play_btn._visible = false;
    pause_btn._visible = true;
   
    myPlayer.play();
}

Part II - Setting Up the File

This is a pretty complicated file setup, so I am providing the framework that I used here. This file doesn't contain any of the components, but does have all of the code and everything else that I used. (If you have purchased all of the components required and want the full example, let us know.)

mp3_player_framework.fla (37KB)

Basically, in addition to the components:
  1. The Media List Flash Component with an instance name "myList"
  2. An Image Loader Flash Component with an instance name "myLoader"
  3. The Simple MP3 Player Flash Component with an instance name "myPlayer"
You will need five other items on the stage:
  1. A MovieClip "BufferingMsg" with an instance name "bufferingMsg_mc" to be shown while the MP3 file is buffering
  2. A Button "PlayBtn" with an instance name "play_btn" to play the MP3
  3. A Button "PauseBtn" with an instance name "pause_btn" to pause the MP3
  4. A MovieClip "ProgressBar" with an instance name "progressBar_mc" to show MP3 playing progress
  5. A Dynamic TextField with an instance name "time_txt" to show playback time (Set the default value to "00:00")

Part III - Media List XML

Now it is time to set up the links to your images and MP3 files using Media List XML.  Check out the sample XML file for help on how XML should be formatted, etc. Notice that I am passing 2 items in the data parameter (image path and mp3 path) comma delimited.

Once you have created your XML, add the XML path to the contentXML property in the Media List parameters. For the sample file:

contentXML:http://www.afcomponents.com/components/media_list/mp3_data.xml

Part IV - The Code

Finally, let's step through the code.

Stage.scaleMode = "noScale";


This is just setting the stage mode so that it won't scale.

// progress bar mc
progressBar_mc._xscale = 0;


Set the initial _xscale of the progressBar_mc to zero. It will be scaled up as the MP3 Player plays to indicate progress.

// default gradient fill
var gradientDefault:Object = new Object;

gradientDefault.fillType = "linear";
gradientDefault.colors = [0x000000, 0x333333];
gradientDefault.alphas = [75, 75];
gradientDefault.ratios = [0, 255];
gradientDefault.matrix = new flash.geom.Matrix();
gradientDefault.matrix.createGradientBox(100, 50, (Math.PI * 3 / 2), 0, 0);

myList.itemDefaultStyle.fillGradient = gradientDefault;

// over gradient fill
var gradientOver:Object = new Object;

gradientOver.fillType = "linear";
gradientOver.colors = [0x000000, 0x333333];
gradientOver.alphas = [85, 85];
gradientOver.ratios = [0, 255];
gradientOver.matrix = new flash.geom.Matrix();
gradientOver.matrix.createGradientBox(100, 50, (Math.PI * 3 / 2), 0, 0);

myList.itemOverStyle.fillGradient = gradientOver;


// selected gradient fill
var gradientSelected:Object = new Object;

gradientSelected.fillType = "linear";
gradientSelected.colors = [0x000000, 0x333333];
gradientSelected.alphas = [95, 95];
gradientSelected.ratios = [0, 255];
gradientSelected.matrix = new flash.geom.Matrix();
gradientSelected.matrix.createGradientBox(100, 50, (Math.PI * 3 / 2), 0, 0);

myList.itemSelectedStyle.fillGradient = gradientSelected;


These are just gradient fill styles for the Media List.

// play the first item when loading is complete
function listLoadHandler(evnt:Object) {

    // select first item in the list
    myList.selectItemNum(0);
   
    // get and play the first item in the list
    var item:Object = myList.getSelectedItem();
    var itemData:Array = item.data.split(",");
   
    myLoader.load(itemData[0], item.title + " - " + item.description);
}
myList.addEventListener("CONTENT_LOAD_COMPLETE", listLoadHandler);


Ok, here I listen for the Media List to finish loading (CONTENT_LOAD_COMPLETE event) and load the image for the first item in the list. (Note: Later, I will check for the image to finish loading and then play the MP3 file.) One thing to note here is that I take the data property of my selected item object and split it into an array. This is because I stored both the image path and the MP3 path in the data property.

// play an item when it is clicked
function listClickHandler(evnt:Object) {
   
    myPlayer.stop();
    progressBar_mc._xscale = 0;
    time_txt.text = "00:00";
   
    play_btn._visible = false;
    pause_btn._visible = true;
    bufferingMsg_mc._visible = true;
   
    // get and play the selected item in the list
    var itemData:Array = evnt.target.data.split(",");
   
    myLoader.load(itemData[0], evnt.target.title + " - " + evnt.target.description);
}
myList.addEventListener("ITEM_ON_RELEASE", listClickHandler);


Here, I begin loading an item when it is clicked in the Media List (ITEM_ON_RELEASE event.) At the top of the handler function, I reset a bunch of stuff, assuming an item might already be playing. I stop the player, set the progress bar back to zero, reset the time display, show the play button (in case the player was paused when a user clicked an item,) then show my buffering message. The second part of the handler function works just like the function above that loads the first item.

// play the item once the image has loaded
function transCompleteHandler(evnt:Object){
   
    // get selection
    var item:Object = myList.getSelectedItem();
    var itemData:Array = item.data.split(",");
   
    // check if this track has already been loaded
    var itemIsLoaded:Boolean = false;
    var itemIndex:Number;
   
    for(var x:Number = 0; x<=myPlayer.getTotalItems(); x++) {
        var mp3:Object = myPlayer.getItemNum(x);
       
        if(mp3.path == itemData[1]) {
            itemIsLoaded = true;
            itemIndex = x;
        }
    }
   
    if(itemIsLoaded) {
        myPlayer.dspItemNum(itemIndex);
    } else {
        myPlayer.addItem(item.title + " - " + item.description, itemData[1]);
        myPlayer.dspItemNum(myPlayer.getTotalItems());
    }
   
    myPlayer.play();
}
myLoader.addEventListener("TRANSITION_END", transCompleteHandler);


Here, I listen for the image to finish loading into the IMG Loader (TRANSITION_END event,) and then load and play the MP3 file. At the top, I check if the MP3 File is already loaded by comparing the path of the file the user wants to play to each path already loaded. If it is, I simply jump to that file and play it (myPlayer.dspItemNum().) If it isn't, I load the new file and then jump to the last file and play it (myPlayer.dspItemNum(myPlayer.getTotalItems()).)

// update time and playbar
function playerTimeHandler(evnt:Object){
   
    bufferingMsg_mc._visible = false;
   
    // time
    var dspTime:String  = "";
   
    // minute
    if(Math.floor(evnt.currentTime/60) < 10) {
        dspTime = "0" + String(Math.floor(evnt.currentTime/60)) + ":"
    } else {
        dspTime = String(Math.floor(evnt.currentTime/60)) + ":"
    }
   
    // second
    var seconds:Number = evnt.currentTime;
   
    if(Math.floor(evnt.currentTime/60) > 0) {
        seconds = evnt.currentTime - (Math.floor(evnt.currentTime/60) * 60);
    }
   
    if(seconds < 10) {
        dspTime += "0" + String(seconds);
    } else {
        dspTime += String(seconds);
    }
   
    time_txt.text = dspTime;
   
    // progress bar
    progressBar_mc._xscale = Math.round((evnt.currentTime/evnt.totalTime) * 100);

    if(progressBar_mc._xscale == 99) {
        progressBar_mc._xscale = 100;
    }
}
myPlayer.addEventListener("time", playerTimeHandler);


This part of the code handles many things. Here, I listen for the player's play time to be updated (time event) and do three different things. First, I hide the buffering message, because the player has started. Second, I update the time display (on a side note, I just kind of came up with this time formatting stuff using Flash's Math.floor. If anyone knows a better method, please let me know. Maybe there is a more standard "formatSeconds" function floating around out there.) Third, we update the scale of the progress bar as the MP3 file plays. (I also check if the progress bar is at 99% and just set it to 100% to avoid having it not fill in all the way. Sometimes the time event doesn't get fired for the last second.)

// play/pause

// hide play button
play_btn._visible = false;

// pause
pause_btn.onRelease = function() {
   
    pause_btn._visible = false;
    play_btn._visible = true;   
   
    myPlayer.pause();
}

// play
play_btn.onRelease = function() {
   
    play_btn._visible = false;
    pause_btn._visible = true;
   
    myPlayer.play();
}


Finally, I just handle the pause and play buttons.

That's about it!  If you have any comments, suggestions, or examples, etc you can post on the forum or send me an email matt at afcomponents dot com (wigz). Enjoy!

Credits: Thanks to Flash TV for the MP3 files.


© 2005-2007 advanced flash components