Apr
15

Making an MP3 player in AS3

by Paul


Music Credits:
Title: The Best Day Ever
Artist: SpongBob
Album: The SpongeBob SquarePants Movie: Music From the Movie and More

Creating an MP3 Player in ActionScript 3.0 is fairly straight forward. The complexity varies greatly depending on what kind of features you want your player to have. I don’t plan on getting into ID3 tags here, but otherwise (as you can see) I will be going over the full functionality of a normal MP3 Player.

The first step is setting up the display and graphics. I went into the FLVPlayback skin SkinOverAll.fla file and fetched all the button graphics I needed (I’m not a very good artist). It was only a little trouble to recreate the buttons in a way that satisfied me (The only important thing to note about my buttons is that I gave them frame labels on the keyframes to make it easier to remember while writing the code).

Setting up the framework:

Now for the code! You can approach code like this from a number of different directions. I chose to start with making my button instances look like buttons, even though they don’t do anything yet. It’s really just a matter of setting up a LOT of event listeners (4 for each button):


stop_mc.addEventListener(MouseEvent.MOUSE_OVER, StopOver);
stop_mc.addEventListener(MouseEvent.MOUSE_OUT, StopOut);
stop_mc.addEventListener(MouseEvent.MOUSE_DOWN, StopDown);
stop_mc.addEventListener(MouseEvent.MOUSE_UP, StopUp);

private function StopOver(event:MouseEvent):void {
        var obj:Object = event.currentTarget;
        obj.gotoAndStop(’stop_over’);
}
private function StopOut(event:MouseEvent):void {
        var obj:Object = event.currentTarget;
        obj.gotoAndStop(’stop’);
}
private function StopDown(event:MouseEvent):void {
        var obj:Object = event.currentTarget;
        obj.gotoAndStop(’stop_down’);
}
private function StopUp(event:MouseEvent):void {
        var obj:Object = event.currentTarget;
        playPause_mc.playing = false;
        playPause_mc.gotoAndStop(‘play’);
        obj.gotoAndStop(’stop_over’);
}

At this point most of the buttons are the same. The only difference might lay in the MOUSE_UP event or how the play button has to switch between play and pause, so I have the boolean property playing in my PlayPauseBtn class.

Bringing in a PlayList:

Now that we have basic working buttons that don’t do anything, it feels like the framework is in place to start making our MP3 player play music. To do this we will need a few elements:

public var url:URLRequest;
public var xmlLoad:URLLoader;
public var musicXML:XML;
public var song:Sound;
public var channel:SoundChannel;
public var sndTrans:SoundTransform;
public var position:Number;

Our song:Sound will load the song and play it. The play() method in the Sound class returns a sound channel which we need to store in our channel:SoundChannel in order to pause/play/stop, or change the volume of our music.

The SoundTransform class is what is used to change the volume through the channel. It can also change the pan (balance of left and right speakers), but I’m not going to get into that.

What we are going to do is load an external XML file with our playlist in it… something like this:

<music>
        <song id="/url/TheBestDayEver.mp3" disp="The Best Day Ever"/>
        <song id="/url/come_away.mp3" disp="Come Away"/>
        <song id="/url/nightmares.mp3" disp="Nightmares and Dreams"/>
        <song id="/url/override.mp3" disp="Override"/>
        <song id="/url/rescue.mp3" disp="Rescue"/>
        <song id="/url/stick_em_up.mp3" disp="Stick’em Up"/>
        <song id="/url/trogdor.mp3" disp="TROGDOOOR"/>
        <song id="/url/you_are.mp3" disp="You Are"/>
</music>

Then we want to add each song on that playlist to a list component on the stage (I’ve called it playList). After we have the URLs of our songs, then we can start to load and play them.

In our xmlComplete(event:Event) event handler (handling the COMPLETE event from loading our XML file with a URLLoader) we need to parse the playlist into our List:

private function xmlComplete(event:Event):void {
        var item:Object;
        musicXML = new XML(event.currentTarget.data);
               
        for each(var prop:XML in musicXML.song){
                item = new Object();
                item.label = prop.@disp;
                item.data = prop.@id;
                playList.addItem(item);
        }

        song = new Sound();
        song.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        song.load(new URLRequest(playList.getItemAt(0).data));
        this.addEventListener(Event.ENTER_FRAME, updateSeek);
        playList.selectedIndex = 0;
}

The for each..in loop is one that not everyone knows about. It’s very useful for getting all the elements of an XML object when you aren’t sure how many elements there will be. Basically it’s assigning each song tag from the XMLList musicXML.song to prop and then runs the code within the curly brackets {}.

I don’t like it when music or sounds start playing on the internet without my consent. So, whenever I make something like and MP3 Player, I set it up to NOT automatically play.

Still, I want it to be ready to play as soon as the user tells it to. So, I needed to add those lines after my for each..in loop. What is happening might be obvious enough. I’m creating a new Sound object and storing it in song. I always check for load errors so that the end user doesn’t get annoying pop-ups telling them that I’m a bad programmer. Then I’m loading the first song on the playList and making that song highlighted in my List component.

The event listener with a handle of updateSeek is needed for my seekbar. I will get to that later.

Playing the music and traversing out PlayList:

Great! So, now we have everything set up to look like a complete player. We even have our first song loaded. But, there is no way to get it to play yet. Our PLAY button doesn’t work yet.

This is where we have to start giving those buttons some functionality. Most (if not all) of the functionality for each button is going to be in the MOUSE_UP event handlers:

private function PlayUp(event:MouseEvent):void {
        var obj:Object = event.currentTarget;
        if(obj.playing) {
                obj.gotoAndStop(‘play_over’);
                position = channel.position;
                channel.stop();
                obj.playing = false;
        } else {
                obj.gotoAndStop(‘pause_over’);
                channel = song.play(position);
                channel.soundTransform = (mute_mc.isMute)? new SoundTransform(0) : sndTrans;
                channel.addEventListener(Event.SOUND_COMPLETE, soundComplete);
                obj.playing = true;
        }
}

private function StopUp(event:MouseEvent):void {
        var obj:Object = event.currentTarget;
        channel.stop();
        position = 0;
        playPause_mc.playing = false;
        playPause_mc.gotoAndStop(‘play’);
        obj.gotoAndStop(’stop_over’);
}

playList.addEventListener(ListEvent.ITEM_CLICK, SnglClick);

private function SnglClick(event:ListEvent):void {
        var item:Object = event.item;
                       
        try
        {song.close();}
        catch(error)
        {trace(error);}
        try
        {channel.stop();}
        catch(error)
        {trace(error);}
               
        song = new Sound();
        song.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        song.load(new URLRequest(item.data));
        channel = song.play();
        channel.soundTransform = (mute_mc.isMute)? new SoundTransform(0) : sndTrans;
        channel.addEventListener(Event.SOUND_COMPLETE, soundComplete);
        position = 0;
        playPause_mc.playing = true;
        playPause_mc.gotoAndStop(‘pause’);
}

private function soundComplete(event:Event):void {
        if(playList.length > playList.selectedIndex + 1){
                playList.selectedIndex++;
                playList.scrollToSelected();
        } else {
                playList.selectedIndex = 0;
                playList.scrollToSelected();
        }
        playList.dispatchEvent(new ListEvent(ListEvent.ITEM_CLICK, false, true, 0, playList.selectedIndex, playList.selectedIndex, playList.selectedItem));
}

private function ForwardUp(event:MouseEvent):void {
        var obj:Object = event.currentTarget;
        obj.gotoAndStop(‘forward_over’);
       
        if(playList.length > playList.selectedIndex + 1){
                playList.selectedIndex++;
                playList.scrollToSelected();
        } else {
                playList.selectedIndex = 0;
                playList.scrollToSelected();
        }
        playList.dispatchEvent(new ListEvent(ListEvent.ITEM_CLICK, false, true, 0, playList.selectedIndex, playList.selectedIndex, playList.selectedItem));
}

My Play/Pause button, if playing, will save the current position and then stop the music through the channel. Otherwise, it will play from position and set the volume and add a listener for the end of the song.

The Stop button obviously just stops the song and sets the position back to zero (0). I guess it also resets the Play button.

The ListEvent.ITEM_CLICK is when we click on a list item (a new song in the playlist). The handler closes any open stream that might be there (thus the try..catch) and if not then to simply stop the channel. It then loads the song URL stored in that items data provider and starts it playing.

The forward and back buttons are almost exactly the same. They just change the selection in the List component and then dispatch a fake ITEM_CLICK event.

The soundComplete() method, as you can see, is also very similar to the forward button. This event handler is called when a song played right to the end.

Working with volume:

Since I’ve already mentioned setting the volume, I might as well get into that next. The volume is a property of the SoundTransform class. We already made a SoundTransform variable, we just haven’t stored an ST object in it yet.

My main volume control is sndTrans:SoundTransform; After setting the volume property within it I can assign it to the channel.soundTransform and it will take effect. My volume bar has it’s own class to handle the effect of dragging the handle around:

package controls {
import flash.display.MovieClip;
import flash.events.*;
import flash.geom.Rectangle;
       
public class VolControl extends MovieClip {
        private var bounds:Rectangle;
        public var percent:Number;
       
        public function VolControl() {
                percent = 1;
                bounds = new Rectangle(0, 10, 50, 0);
                       
                volBar_mc.hit_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragHandle);
                volHandle_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragHandle);
                volHandle_mc.addEventListener(MouseEvent.MOUSE_UP, endDrag);
                volHandle_mc.addEventListener(MouseEvent.MOUSE_OUT, endDrag);
        }
       
        private function dragHandle(event:MouseEvent):void {
                volHandle_mc.startDrag(true, bounds);
                this.addEventListener(Event.ENTER_FRAME, changeVol);
        }
        private function endDrag(event:MouseEvent):void {
                volHandle_mc.stopDrag();
                volBar_mc.fullness_mc.fill_mc.x = volHandle_mc.x - volBar_mc.fullness_mc.fill_mc.width;
                percent = volHandle_mc.x/50;
                dispatchEvent(new Event("volume_change"));
                this.removeEventListener(Event.ENTER_FRAME, changeVol);
        }
        private function changeVol(event:Event):void {
                volBar_mc.fullness_mc.fill_mc.x = volHandle_mc.x - volBar_mc.fullness_mc.fill_mc.width;
                percent = volHandle_mc.x/50;
                dispatchEvent(new Event("volume_change"));
        }
}
}

This is simply letting you drag around the little pointer within its bounds and dispatching an event to let the main class know that the volume has been changed. I needed to repeat some of the code from changeVol() in endDrag() because if you just click quickly then the ENTER_FRAME event never gets handled before it’s removed.

Back in the main class we are handling that “volume_change” event:

vol_mc.addEventListener("volume_change", updateVolume);

private function updateVolume(event:Event):void {
        sndTrans.volume = vol_mc.percent;
        channel.soundTransform = (mute_mc.isMute)? new SoundTransform(0) : sndTrans;
}

Another thing that a lot of new programmers don’t know about is the conditional ? : operator. It’s shorthand for an if..else statement. Basically these two bits of code are the same:

if(num>5) {
        num = 5;
}else {
        num = 0;
}
//OR THIS NEXT PART DOES THE SAME THING
num = (num>5)? 5 : 0;

Isn’t that great?

Getting back to our MP3 player. We should add our Mute button while we are working with volume. You’ve already seen that I take the mute condition into account when I set that volume. Here is where I set the mute condition:

private function MuteUp(event:MouseEvent):void {
        var obj:Object = event.currentTarget;
        if(obj.isMute) {
                obj.gotoAndStop(‘mute_over’);
                obj.isMute = false;
                channel.soundTransform = sndTrans;
        } else {
                obj.gotoAndStop(‘unmute_over’);
                obj.isMute = true;
                channel.soundTransform = new SoundTransform(0);
        }
}

I never want to set sndTrans.volume to zero (0) just because I pressed the mute button. I would rather leave that as it is so that I can unmute back to the original volume again.

*phew* About this time I’m thinking to myself, “It sure takes a lot of code to get a simple MP3 Player to work correctly.” But, there is light on the horizon so we must press on.

Making the seek bar to search a song:

Now for the most complicated part of our player. The seek bar. The seek bar isn’t THAT bad, but it’s definitely worse then what we have done so far.

First of all we will give the seek bar the same drag or click functionality that we gave to volume control bar:

public class SeekControl extends MovieClip {
        private var bounds:Rectangle;
        public var percent:Number;
        public var seeking:Boolean;
       
        public function SeekControl() {
                seeking = false;
                percent = 0;
                bounds = new Rectangle(0, 12, 100, 0); //I made the seek bar 100 wide for convenience
               
                seekHit_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragHandle);
                seekHandle_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragHandle);
                seekHandle_mc.addEventListener(MouseEvent.MOUSE_UP, endDrag);
        }
               
        private function dragHandle(event:MouseEvent):void {
                seeking = true;
                seekHandle_mc.startDrag(true, bounds);
        }
        private function endDrag(event:MouseEvent):void {
                seeking = false;
                seekHandle_mc.stopDrag();
                fillBar_mc.x = seekHandle_mc.x - fillBar_mc.width;
                percent = seekHandle_mc.x/100;
                dispatchEvent(new Event("seek_change"));
        }
       
        public function moveSeekPos(perc:Number):void {
                fillBar_mc.x = (fillBar_mc.width * perc) - fillBar_mc.width;
                if(!seeking)
                seekHandle_mc.x = 100 * perc;
        }
}

The biggest difference here is that I don’t want a live update while dragging the pointer around. Otherwise, a few values have changed, some var names have changed, but it should look familiar (well it would if you had written this code yourself).

The moveSeekPos() method is going to be updated constantly from our main class. This is here so that we can see the play progress when listening to a song.

Getting back to the main class again, we have to write a thing or two about our seek bar there:

/*Remember that
this.addEventListener(Event.ENTER_FRAME, updateSeek);
is added when we start to load a new song.*/

seek_mc.addEventListener("seek_change", changeSeekBar);

private function changeSeekBar(event:Event):void {
        position = song.length * seek_mc.percent;
        if(playPause_mc.playing){
                channel.stop();
                channel = song.play(position);
                channel.soundTransform = (mute_mc.isMute)? new SoundTransform(0) : sndTrans;
                channel.addEventListener(Event.SOUND_COMPLETE, soundComplete);
        }
}

private function updateSeek(event:Event):void {
        if(playPause_mc.playing) {
                var perc:Number = channel.position / song.length;
                seek_mc.moveSeekPos(perc);
                display_mc.timeDisp.text = formatTime(channel.position) + "/" + formatTime(song.length);
        }
}

public function formatTime(time:Number):String {
        var min:String = Math.floor(time/60000).toString();
        var sec:String = (Math.floor((time/1000)%60) < 10)? "0" + Math.floor((time/1000)%60).toString() : Math.floor((time/1000)%60).toString();

        return(min+":"+sec);
}

I went ahead and added the code here to display the current play time and the total play time in a dynamic text field on the stage. That seemed to be closely related to the seek bar, so I figured showing it here is suitable.

A final note:

Now would be a good time to mention that I didn’t bother fixing a “minor” bug. While a song is still streaming (loading), Flash doesn’t know how long it is. Thus, song.length will be growing over time till it’s done loading. This is only an issue for our seek bar, because it uses the ratio between the current position and the total length to decide how to display itself.

To work around this issue (which is really only an issue for slower internet connections), you will need to pass Flash the songs length along with the file path in the XML doc. It seemed like a lot of trouble to me and since this isn’t for a client, I figured I would just tell you about it instead of do it for you.

Wow. This was so long that I wouldn’t be surprised to find later that I forgot something. If I find anything I will make sure to update this post and make a note of what I changed.

Anyways, that is it! I think…

Let me know what you think about it and also let me know if you even use my Player on your site somewhere. I would love to see my work being used.

You can get the source files for this tutorial and the example at the beginning to the page here: MP3 Player Source Code.zip

Tags: , , ,

Related Posts

48 Responses to “Making an MP3 player in AS3” RSS

  1. Jones Says:

    Dont like the graphics in the player, but the source code is great, thanks!

  2. Nick Says:

    Woo hoo!!! :-)

  3. knfubu Says:

    Hi,

    If you had to fix that minor bug about sound length, how would you go about fixing it? I’m loading especially long mp3s (40+ minutes) and I need a good way to get the length of the mp3 dynamically.

    -Shant

  4. Paul Says:

    Well, I’ve thought of a few ways. Probably the best way to do it would be to have a “length” attribute in your song tag. This would have to be the approximate length of the sound file (round to the nearest second) in seconds or milliseconds… whatever will allow you to know the length before it’s even started loading.

    Add the length to the item given to the DataProvider for the list…
    for each(var prop:XML in musicXML.song){
    item = new Object();
    item.label = prop.@disp;
    item.data = prop.@id;
    item.data2 = prop.@length;
    playList.addItem(item);
    }

    If that works then you should be able to use that length for all calculations and even show the load progress right in the seek bar like on youTube videos.

    ClickPopMedia
  5. Corey Schario Says:

    How come I can’t figure out how to change the color? That neon blue makes my eyes cry. Any help would be appreciated.

  6. Paul Says:

    I copied the interface controls from the FVLPlayback component skin SkinOverAll.fla

    The buttons, seekbar, and volume control are all just an alpha gray. There is only a few things that have color. The background is a square of light blue (change that and you are 90% done) and the button’s over and down states have the purplish outline.

    All of that should be changeable without any code. You can change the style colors of the list using listInstance.setStyle(”styleName“, value);

    ClickPopMedia
  7. wilson Says:

    How would you go about changing the displayed text color?
    The song name.

  8. Paul Says:

    var myFormat:TextFormat = new TextFormat();
    myFormat.font = “Georgia”;
    myFormat.color = 0×00FF00;

    var b:List = new List();
    b.dataProvider = [{label:"Hello World"}];
    b.setStyle(”textFormat”, myFormat);
    addChild(b);

    Something like this will add a new List to the stage with one item labeled “Hello World”. What you (wilson) wanted to know (I think) is that .setStyle(); function where I am changing the font and font color.

    ClickPopMedia
  9. wilson Says:

    Thanks for your help. That is an awesome player thanks for sharing it.

  10. charlie Says:

    Thanks for the source code, info and really great help. This makes as3 ALMOST understandable, even for an old BASIC stick in the mud like me.
    Thank you

  11. wilson Says:

    Hello again, I’ve been testing the player on several browsers, and with internet explorer i get TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at Mp3Main/::updateSeek()

    any idea how to fix this?

  12. Paul Says:

    Actually one of my friends informed me of this issue…

    I’ve just gone about fixing it in the tutorial and source zip.

    What was happening was Flash Player was trying to access channel.position while channel was still null. channel is only defined when a song is playing.
    So, to fix this I just moved the one line of code still remaining outside the if loop within updateSeek() inside the if loop in updateSeek(). It’s a very quick solution and it does the job just fine.

    The reason I had that line outside of the if loop was because I was hoping to show the position that you where dragging to live as you drag. It didn’t work anyways… I do have a way to do that in mind, but I’m not going to bother right now.

    ClickPopMedia
  13. Menorca Online Says:

    Hi! I’m trying to use your mp3player and i’m having problems… :P Can you write an example with http://www.example.com/modules/mp3/ ? Thankyou!

  14. Menorca Online Says:

    Donty worry it’s working fine! GOOD JOB!

  15. nk Says:

    When I roll over the components how can I change it to a hand pointer? Is this possible?

  16. Paul Says:

    nk,
    I would think that it might be possible to use the hand cursor, but I’m not sure how. I’ve just tried a few things, but none of them are working.
    The problem I’m running into is that I don’t have easy access to the children of the List component.
    Setting buttonMode to true for the component itself doesn’t work. You have to do it for each of the items, which I’m not sure how to do right now.

    Maybe if you edit the component itself you could probably get it to work that way.

    ClickPopMedia
  17. s'PlatterKep Says:

    Hello, and thanks *very* much for your hard work in creating this valuable tutorial. I have 2 questions I hope someone can help with:

    1. Where specifically in the FLA does it link to the AS file? I’m an idiot, can’t find it.

    2. How could I add a dropdown menu populated with the XML instead of the list?

    Thanks again!

    -sPlat

  18. Mladen Says:

    Can you confirm that you solved memory problem with flash streaming? In similar application I have streamed music for 24h and after that, computer become useless. Problem is that Flash player will store all downloaded material until you close opened application.
    Is it solved or I’m not up to date :) ?

    mladen

  19. melie Says:

    i keep getting this error message:
    Error: Error #2029: This URLStream object does not have a stream opened.

    what does that mean and how do i fix it?

  20. Harry Says:

    > Well, I’ve thought of a few ways. Probably the best
    way to do it would be to have a “length” attribute in your song tag.

    Much better way: find the percentage that’s loaded, then divide the current song length by it - if 50% has loaded, and it’s giving a length of 100000 milliseconds, then 100000/0.5 = 200000 (the proper length).

    It works, trust me.

  21. Paul Says:

    For the first time ever, I tried to view this tutorial with a slow (dial-up speed) connection. That minor loading issue seemed MUCH bigger then.

    I like your suggestion Harry. I guess sometimes I just don’t realize the obvious. There is probably a few things I could do to make this MP3 Player work better on a slower connection machine.

    ClickPopMedia
  22. Maria Says:

    Any chance you can show us how to add album art in the playlist?

  23. Paul Says:

    Wow! Album art? Now that’s a whole different ball of wax. I suppose you could have a simple gallery that switches to the appropriate image in the SnglClick(event:ListEvent) function.

    I which case you would need to have the album art image’s URL in the XML somewhere. I will write a tutorial on making a gallery later today…

    ClickPopMedia
  24. Maria Says:

    You are so totally awesome and a scripting genius at that! Thank you for this tutorial : )

  25. s'PlatterKep Says:

    Bump.

    Hi, can anyone please offer suggestions as to the following?

    1. Where specifically in the FLA does it link to the AS file? I’m an idiot, can’t find it.

    2. How could I add a dropdown menu populated with the XML instead of the list?

    Thanks again!

    -sPlat

  26. Ottis Says:

    I did it the easy way (downloaded the zip-file).

    This is what I get when I test the fla:

    Error #2044: Unhandled ioError:. text=Error #2032: Stream Error. URL: file:///url/music.xml
    at Mp3Main$iinit()

    …and this when I press the play button:

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at Mp3Main/::PlayUp()

    Why and how do I fix the problem?

  27. Paul Says:

    s’PlatterKep, if you click on the stage and then check out the propertes, you will see “Document Class” next to an input box. That is where you set the Documents AS file.
    As for your other question, s’PlatterKep, the easiest way to use a dropdown menu instead of a list would be to use the combobox component. You would have to make a few changes to the code to make that work, but not a lot.

    Ottis, I didn’t provide any music with the ZIP and so I also didn’t use real URLs in my URLRequests. You are going to have to put those in yourself if you want to test this MP3 Player out.

    ClickPopMedia
  28. Ottis Says:

    I forgot I had do change the xml-file too. It´s done now and the music is playing. However I get this message. Is something wrong or can I ignore the error..?

    Error: Error #2029: This URLStream object does not have a stream opened.
    TypeError: Error #1009: Cannot access a property or method of a null object reference.

  29. Ottis Says:

    One last question…

    What do I need to do with the script if I want to take away the list component at the very top and instead just show the current playing song in the display window? (No time needed - the progress bar is enough.)

  30. Paul Says:

    With all the question that have been asked that require a detailed responds, we at ClickPopMedia are going to be putting up a forum soon where I (and others) can answer these questions more appropriately.

    ClickPopMedia
  31. s'PlatterKep Says:

    Paul, Thanks so much for your response. In terms of changing the code re the combobox, could I please ask you to point me in the right direction? I’m trying to set it up, but keep breaking it.

    Thanks again, this is a great FLA.

    Cheers,

    s’Plat

  32. kyle Says:

    not sure if something mentioned this before but for the conditional statement

    num = (num>5)? num = 5 : num = 0;

    you dont need the extra num =

    it can just be
    num = (num>5)? 5 : 0;

    cheers

  33. Paul Says:

    Thanks kyle, I didn’t notice that I did that. I know better then that… OK, I fixed it.

    ClickPopMedia
  34. brett Says:

    to get the hand cursor:

    myButtonName.buttonMode = true;

  35. John Says:

    I love your player, but I am struggling to meld other ideas with it.

    I would like to load the lyrics with the song. I believe that I have to use CDATA in the XML, does the current xml syntax in the playlist allow this?

    Thanks again
    John

  36. Paul Says:

    John, you don’t have to use CDATA, but you can if you want to and it really is needed if you want to have HTML in the lyrics (bold, italics, etc.)

    I would suggest changing the tags so that there is an open and closing tags instead of just the self closing ones. Then you can have the lyrics within the tags and not as attributes.
    You will have to add code to the MP3 Player this way, but you should have to change much.

    ClickPopMedia
  37. Jordy Says:

    I am having a memory leak issue here! Great code for a noob to get stuck into and I am slowly adding my bits (equalizer and load bar) but I seem to have a memory leak! I am monotoring it - but dont have a clue where to start - anyone else having this issue?

  38. Jordy Says:

    its not removing the addeventlistener right? - can these be removed or not? I.e if they are removed then nothing would be listened for so nothing would work…..or maybe remove certain things once they have been activated……hmmmmm

    My machine reset due to leaving this on for ages! now thats not a good memory leak

  39. Paul Says:

    How many time can one listen to “The Best Day Ever!” by Sponge Bob? Well I know VQ has listened to it at least 100 times according to his iTunes play count…

    Anyways, I put this MP3 Player together in about 90 minutes and didn’t thoroughly error check it (obviously I never even bothered to get the loader bar working correctly).

    If event listeners are giving memory leaking problems (and they are usually the cause) then you should use a weak reference like this:
    myMovieClip.addEventListener(Event.COMPLETE, completeHandler, false, 0, true);

    The last parameter is the useWeakReference that you have to set to true.

    Someday in the not to far future I will come back to this MP3Player and maybe make it into a component. When that day comes I will do some real thorough debugging and error checking.

    ClickPopMedia
  40. Dean Says:

    OK. Dumb question. How do I make it autoplay the first song in the list? Usually I don’t like thngs to autoplay but I am using it for a Bar.

    http://www.intersoltours.com/tequisol/tequisol.html

  41. Paul Says:

    Dean,
    It is very easy. Simply add a line at the end of the function xmlComplete(event:Event) that will make it seem like the play button has been clicked.

    playPause_mc.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));

    With that, the first song should auto play. There are other ways to do it, but this one takes the least amount of typing on my part.

    ClickPopMedia
  42. Dean Says:

    It makes the button look clicked and displays the pause state until you
    mouse over the button.
    Doesn’t play a note.

    private function xmlComplete(event:Event):void {
    var item:Object;
    musicXML = new XML(event.currentTarget.data);
    playPause_mc.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));

  43. Paul Says:

    First of all Dean, you have to create your Sound object FIRST then load the song BEFORE you set up the autoclick.
    Like this:

    song = new Sound();
    song.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
    song.load(new URLRequest(playList.getItemAt(0).data));
    playPause_mc.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));

    I did notice that it leaves the Pause button in the mouse over state and so to avoid this, let’s just preset all our variables to the play-state first and then call song.play()
    Like this:

    song = new Sound();
    song.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
    song.load(new URLRequest(playList.getItemAt(0).data));
    //the following replaces our event dispatch.
    playPause_mc.gotoAndStop(’play’);
    channel = song.play(position);
    channel.soundTransform = (mute_mc.isMute)? new SoundTransform(0) : sndTrans;
    channel.addEventListener(Event.SOUND_COMPLETE, soundComplete);
    playPause_mc.playing = true;

    OR you can dispatch a MOUSE_OUT event directly following the MOUSE_UP event. It’s up to you.

    ClickPopMedia
  44. Dean Says:

    Works grat Paul. You are the man. One thing though, the progress bar no longer functions. I figure I did something wrong. I have an off topice question… you sent a file to me via email with the MP3 plyer that added the class to the mp3 player instead of the Document. I have another similar file and I do not know how to combine the same process to turn it into something I know how to use. It is a cool fog effect and I can not separate it from the original FLA file.

    I need help.

  45. knfubu Says:

    Hi

    I used your seekbar code to get my own player up and running. I’m currently running into a strange bug that I thought you might be able to shed some light on. I have loaded a mix that is 44 minutes long. I have checked the percent amounts and seekPosition numbers I am sending to it and I get a discrepancy in my sound playback.

    Early in the mix, the discrepancy is about a 5 or 10 second difference but as the mix goes on it gets exponentially worse. When the time stamp is showing 44 minutes and the mix is supposed to be over, it is actually ending about 2 minutes early in the song.

    Is this a bug that has to do with Flash or am I coding something wrong?

  46. Bala Says:

    Hi,
    First i Thank for this mp3 player.
    i am having the problem in loading mp3(40 bitrate). while i drag the seekbar in to end. it doesn’t play
    i change 40 bitrate into 64 bitrate and more its work fine.
    any body knows why it not play in 40 bitrate?

  47. Thomas Says:

    Hi paul,
    Thanks for the mp3player but I have trouble uploading the music because it just doesnt work and I uploaded the xml file but it had errors when loading..
    how can I fix this?

  48. Maria Says:

    Hi Paul,

    Do you know where within the code can I add the .setStyle to change the text color?

    var myFormat:TextFormat = new TextFormat();
    myFormat.font = “Georgia”;
    myFormat.color = 0×00FF00;

    var b:List = new List();
    b.dataProvider = [{label:"Hello World"}];
    b.setStyle(”textFormat”, myFormat);
    addChild(b);

    thanks!


Warning: stristr() [function.stristr]: Empty delimiter in /home/vmnstudi/public_html/wp-content/plugins/wassup/wassup.php on line 2093