This is the second of two music playing Flash objects that we are making, both of which read information (data) from an external source. The first one took a "juke box" approach—a variety of songs are available in any order, but one must press the appropriate button to make it work. The object we will build in this exercise will be more of a stripped-down "iTunes/Winamp" style player—it plays the songs in sequence but there is only one play/pause button and you can skip ahead and backward.
As with the juke box, you will need more than just a Flash file; you will also need several mp3 files (obviously) a data file, and something new—an external actionscript file that will contain a class object (more on that later). If you don't have any songs handy I've put five song snippets along with a sample data file, object file and a Flash file with some ready-made buttons together in a zip file that you can download and use. If you downloaded the songs for the previous exercise, you can download a zip file that contains just the Flash & data files instead.
This exercise draws heavily upon Lee Brimelow's mp3 player tutorials found at gotoandlearn.com.
First, we need to type a line of code that declares that this is an XML file; write the following:
<?xml version="1.0" encoding="UTF-8"?>
<songs>
</songs>
<songs>
<song url="tunes/BachEdit.mp3" artist="J.S. Bach" track="Toccata in D" />
<song url="tunes/BeethovenEdit.mp3" artist="L.V. Beethoven" track="5th Symphony" />
<song url="tunes/CoplandEdit.mp3" artist="A. Copland" track="Rodeo/Hoedown" />
<song url="tunes/MouretEdit.mp3" artist="J.J. Mouret" track="Rondeau" />
<song url="tunes/OrffEdit.mp3" artist="C. Orff" track="Carmina Burana" />
</songs>
Bear in mind that if your songs are in a different location, or if you're using different songs you will have to update the data. You can also have as many songs as you like (which is a big improvement over the jukebox which was limited by the number of buttons).
class Song
{
public var earl:String;
public var artist:String;
public var track:String;
public function Song(e:String, a:String, t:String)
{
earl = e;
artist = a;
track = t;
}
}
Essentially, this creates three variables called "earl" (to hold the url—get it? We can't use "url" for a variable name because it's a reserved term—it's an Actionscript command), "artist," and "track." Then it reads the data from the XML file and assigns the three corresponding data nodes to the three variables. Simple, right?
So create a simple graphic to represent a "pause" button. Something like this: ![]()
// Set up the sound object
var mySong:Sound = new Sound();
mySong.onSoundComplete = playSong;
mySong.setVolume(50);
This first section creates an empty sound holder called mySong (we'll fill it later), sets the master volume to 50(%), and tells the player to execute the function playSong (which we will create further down) once mySong is finished playing. Actually, if you plan on adding the volume slider you don't need to set the volume (the code for the slider will do that); just leave off the bottom line.
// Set up the array and some variables
var songArray:Array = new Array();
var playingSong:Number = -1;
var pos:Number;
var xml:XML = new XML();
xml.ignoreWhite = true;
xml.onLoad = function() {
var nodes:Array = this.firstChild.childNodes;
for(var i=0;i<nodes.length;i++)
{
songArray.push(new Song(nodes[i].attributes.url, nodes[i].attributes.artist, nodes[i].attributes.track));
}
playSong();
// If you want the first song to autoplay,
// remove the next two lines before the closing }
pauseIt();
playPause.gotoAndStop("play");
}
xml.load("songs.xml");
Okay this section is probably the trickiest part to grasp. First, it creates an empty array called songArray. An array is like a variable, but instead of storing one piece of information, it contains a list of data. Next it sets up a couple of variables: playingSong holds the track number of the song that is playing (initially it will be song 0 since computer programs always begin counting at zero, not 1). The second variable, pos, will be used to record the position of the playhead within the song that is playing (the "counter"). After the array is created, it is filled with the data in the XML file we created earlier. Once the array is filled, it executes the playSong function (which we haven't written yet). Note that I added two lines at the bottom that stop the song from playing (so the user must hit the "play" button to start the music). If you want your player to start automatically, remove the two lines after the comment.
//Play the mp3 file
function playSong():Void {
mySong = new Sound();
mySong.onSoundComplete = playSong;
if(playingSong == songArray.length - 1)
{
playingSong = 0;
mySong.loadSound(songArray[playingSong].earl, true);
}
else
{
mySong.loadSound(songArray[++playingSong].earl, true);
}
trackInfo.text=songArray[playingSong].artist+" • "+songArray[playingSong].track;
playPause.gotoAndStop("pause");
}
Now we get to the function that actually plays a song. The mySong holder is filled with a song from the array that corresponds to the variable playingSong (the track number) starting with 0. But if the number of the song exceeds the total number of songs, it goes back and starts over at song 0 again. In addition, the trackInfo field is filled with the appropriate data, and the playPause movie clip is jumped to the "pause" label (causing the pause button to appear on stage).
// Go back one song
function goBack():Void {
mySong = new Sound();
mySong.onSoundComplete = playSong;
if(playingSong == 0)
{
playingSong = songArray.length - 1;
mySong.loadSound(songArray[playingSong].earl, true);
}
else
{
mySong.loadSound(songArray[--playingSong].earl, true);
}
trackInfo.text=songArray[playingSong].artist+" • "+songArray[playingSong].track;
playPause.gotoAndStop("pause");
}
Now we create a function that jumps backward to the previous song. I'm particularly proud of this function, I wrote it all by myself (the tutorial I based this on had no back button).
// Pauses the music
function pauseIt():Void {
pos = mySong.position;
mySong.stop();
}
// Unpauses the music
function unPauseIt():Void {
mySong.start(pos/1000);
}
This code creates the pauseIt function and the unPause function. The pauseIt function doesn't just stop the music, it makes a note of the playhead's position and stores that in the pos variable. Then the unPause function plays the music from that spot.
// Music controls
// Play/Pause toggle button
playPause.onRollOver = function() {
if(this._currentframe == 1) this.gotoAndStop("pauseOver");
else this.gotoAndStop("playOver");
}
playPause.onRollOut = playPause.onReleaseOutside = function() {
if(this._currentframe == 10) this.gotoAndStop("pause");
else this.gotoAndStop("play");
}
playPause.onRelease = function() {
if(this._currentframe == 10)
{
this.gotoAndStop("playOver");
this._parent.pauseIt();
}
else
{
this.gotoAndStop("pauseOver");
this._parent.unPauseIt();
}
}
This code sets up the playPause button. Recall that we made the "button" out of a movie clip, not a button symbol. This piece of code specifies different functions for the movie clip depending on the action taken. On a "rollover" the button changes to the over state. On a "rollout" (rolling off the button), the button reverts to its normal appearance. But on a "release" (the button is pressed), the button changes to the either the "play" or "pause" state (depending on what state it was in when pressed), and it either plays or pauses the music (again, depending on the state it was in initially) by executing the specified function.
// Next button
nextButton.onRollOver = function() {
this.gotoAndStop("nextOver");
}
nextButton.onRollOut = next.onReleaseOutside = function() {
this.gotoAndStop("next");
}
nextButton.onRelease = function() {
this._parent.playSong();
}
// Back button
goBackButton.onRollOver = function() {
this.gotoAndStop("backOver");
}
goBackButton.onRollOut = next.onReleaseOutside = function() {
this.gotoAndStop("back");
}
goBackButton.onRelease = function() {
this._parent.goBack();
}
These last two blocks of code set up the next and back buttons. As with the play/pause button, the functions performed depend on the action taken.
onClipEvent(load) {
this._x=_root.hBase._x + _root.hBase._width/2 - this._width/2;
left=this._x - _root.hBase._width/2;
top=this._y;
right=this._x + _root.hBase._width/2;
bottom=this._y;
volCalc=_root.hSlider._x - _root.hBase._width/2
}
onClipEvent(enterFrame) {
this.onPress = function ()
{
startDrag(this, false, left , top , right, bottom)
}
this.onRelease = this.onReleaseOutside = function () {
this.stopDrag();
}
sliderx=_root.hSlider._x;
songVolume=(sliderx-volCalc);
_root.mySong.setVolume(songVolume);
_root.currentVolume="Volume " + _root.mySong.getVolume();
}
If you did the previous jukebox exercise with the volume slider you will note that this is the exact same code we used in that one; if it ain't broke, don't fix it.
4 pts |
Portfolio quality design; great mp3 player. |
3 pts |
Good looking; above average work. |
2 pts |
It works, but it's nothing fancy. |
1 pts |
Something's not working right. |
0 pts |
Poor showing; mostly incomplete or full of errors. |