Flash MX MP3 player, Pt.1

source: http://www.thegoldenmean.com

4 — Functions

This in an exceptionally long page, unrelieved by the diversion of anything resembling a graphic. Be forewarned and be prepared with something caffeinated!

Grouping functions by intent

There are three main groups of functions: those that format milliseconds into more readable units, those that display meaningful information to the user and those that provide, well, “functionality.” For the sake of my own sanity, I place this ActionScript code in the layer called “functions” to make it easier for me to find.

Formatting Time Display

The first function, “formatTime()”, comes from Philip Kerman’s book “ActionScripting in Flash MX”. It takes a time expressed in milliseconds and re–formats it into minutes, seconds and tenths of a second. (If you aren’t interested in tenths then just leave that part out.) This function looks complex but really is just a series of divisions. It is called by the displayStreaming() and displayPosition() functions that follow, so for now just take a look at what it does. The code reads:

/*******************************
 function formatTime()
 feed it time in milliseconds; it returns time formatted 
minutes:seconds:remainder
*********************************/  
function formatTime(theSource) { 
var elapsedTime = theSource;

  //Minutes
 var elapsedM = Math.floor(elapsedTime/60000); 
var remaining = elapsedTime - (elapsedM * 60000);
//add a leading zero if it's a single digit 	number
if (elapsedM < 10) {
 		elapsedM = "0"+elapsedM;
	 	} 
	
 //Seconds 
var elapsedS = Math.floor(remaining/1000);
 remaining -= (elapsedS*1000);
	////add leading zero
	if (elapsedS<10) {
		elapsedS = "0"+elapsedS;
	}
 //Hundredths
 var elapsedFractions = Math.floor(remaining/10); 	
	if (elapsedFractions < 10) {
		elapsedFractions = "0"+elapsedFractions;
	}
//display result nicely 
outputData = elapsedM+":"+elapsedS+":"+elapsedFractions; 
return outputData; 
} 

Displaying Time Data

Functions two and three write useful information to the player interface. displayStreaming() will send information to one of the movie’s two text fields as the MP3 file streams to the client and, once it has fully loaded report the song length (in terms of time). displayDuration() will send information to the movie’s other text field, reporting how many minutes the song has been playing so far. The first will tell you how long the song is; the second will tell you how much of that you have heard so far.

These functions introduce some important properties of the Sound class which we will consider shortly but first have a look at the ActionScript:

/********************************
 functions displayStreaming() and displayPosition()
  called by setIntervals in the doPlay() function, these two functions are 
responsible for updating and displaying time data: one for the song's
duration, the other for the song's position
 *********************************/

  function displayStreaming(theSource){
  if(theSource.duration>0){
       if(theSource.getBytesLoaded()== theSource.getBytesTotal()){
            clearInterval(streamingID); 
            mainTL.displayDuration_txt.text = " song duration: "
            +formatTime(theSource.duration);
       }else{
            mainTL.displayDuration_txt.text = "streaming: "
            +formatTime(theSource.duration);
       }
  }
 }

  function displayPosition(theSource){
  if(theSource.position>0){
       if(theSource.position==theSource.duration){
            clearInterval(playingID);
            mainTL.displayPosition_txt.text = "completed: "
            +formatTime(theSource.position);
       }else{
            mainTL.displayPosition_txt.text = "current position: "
            +formatTime(theSource.position);
       }
  }
 } 

Looking at these functions, you may see some things you are unfamiliar with. First — the intervals “streamingID” and “playingID” will be declared in the last function on this page so don’t be too concerned about what they are for now. The important thing is that these functions clear the intervals if conditions are met.

Don’t be alarmed if you don’t observe the streaming display when testing from your local machine. The data loads so fast from your hard drive it is unlikely you will ever see that output. Rest assured that when you upload the project to a web server you will indeed see it!

There are two methods and two properties of the Sound class we are utilizing here:

You may be familiar with getBytesLoaded() and getBytesTotal() from building preloaders for other Flash resources such as movies or external jpeg files. Both methods return a number expressed in kilobytes. In this case we’re simply using the data to check for whether the file has loaded completely. If “total” equals “loaded” it has.

The properties “position” and “duration” are unique to the Sound class. Both represent a number but this time the number is a quantity of milliseconds. “duration” represents the total length of the song in milliseconds. “position” represents how far into the sound the player is, again expressed in milliseconds. By using setInterval to repeatedly interrogate the particular Sound object we can keep updating the two dynamic quantities (how much has loaded and where the play head is). The funny thing about “duration” when the sound is streaming is that Flash actually doesn’t know the duration until it has fully loaded. That’s why the displayStreaming() function reports "streaming:" until the track has fully transferred from the server to the client, at which time it stops updating and switches to "duration:".

Pull the Pieces Together

One function remains to be covered on this page, but it’s a whopper. In fact, it is the function that really ties everything together and makes it all work. I named this function “doPlay()”. I’ll chop it up and discuss the major portions as we go. How is this function called? This is the callback function that is attached to the onChanged event the listBox component generates when you select an item.

The first part to this function is initialization. If a track had been playing it stops and then deletes that tune and clears anything that might be in the text fields.

/**********************************
the core function: doPlay()
doPlay() clears old Sound object, creates a new one and starts it playing
also clears it when it finishes playing
*********************************/

function doPlay(theSong){
	
      //always start with a fresh Sound object...
     clearInterval(streamingID);
     clearInterval(playingID);
          if(typeof myTunes == "object"){
               myTunes.stop();
               delete myTunes;
          }
	
     mainTL.displayDuration_txt.text = "-";
     mainTL.displayPosition_txt.text = "-";

Next the script determines what track you want it to play (or, more precisely, what file you want it to load). It does that by accessing the .data property of the listBox. What? Every item displayed in a listBox has associated with it an array with two entries: label (whose value is what you see) and data (whose value in this case is the MP3 file associated with that item). Once the function has that information, it creates a new instance of the Sound class and loads the file into that new Sound object. Pay particular attention to the second argument in the loadSound method: “true”. This is the critical directive that tells Flash you want the sound to stream. Also note that we set the volume to a value derived from the horizontal position of the volume slider. This is a little confusing because we haven’t yet built the volume slider! But we lay the ground work here for things to come.

          //grab data parameter from ListBox
     var theSong = songList_lb.getSelectedItem().data;
     myTunes = new Sound();
     myTunes.loadSound(theSong, true);
     //base volume on slider position
     myTunes.setVolume(Math.floor(volume_mc.slider_mc._x/2));

Once the new Sound object has been created and a file loaded into it we have access to the properties bytesLoaded, bytesTotal, duration and position. We create two intervals to monitor the changing values of these properties. “streamingID” calls the displayStreaming() function every 200 milliseconds, while “playingID” calls the displayPosition() function every 200 milliseconds.

          //the setIntervals that display time data
          streamingID = setInterval(displayStreaming, 200, myTunes);
          playingID = setInterval(displayPosition, 200, myTunes);

A useful method of the Sound class is onSoundComplete(). This event handler is triggered, as you might guess, when the sound reaches its end (in other words, when position == duration). We will employ this method to do cleanup stuff. It’s essentially the same as the beginning of the function, but where the previous initialization work was written for a case in which the user selects a new tune before the current one has finished, this part of the function does the cleanup automatically if the user listens to a tune all the way to the end.

     //what to do when tune ends
//clean up stuff from previous song
myTunes.onSoundComplete=function(){
	
     //clear the text fields
     mainTL.displayDuration_txt.text = "";
     mainTL.displayPosition_txt.text = "";
	
     //delete existing Sound object
     myTunes.stop();
     delete myTunes;
	
     //stop the setIntervals
     clearInterval(streamingID);
     clearInterval(playingID);
     }
}

That concludes all the critical functions except for two. Creating the data provider that drives the listBox menu is considered by itself on the next page, Page Five.

go to page: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
divider ornament

--top--