Skip to content


Flash MP3 Player – Progress 1

So I have re-written my flash player to Actionscript 3 from Actionscript 2. The functionality is that there are two movies that will control the player. One movie that actually plays the music and another movie that controls it. This is so the music will not stop playing as the user travels from one html page to another. As this is still a work in progress, I will post my code here for now as a placeholder for things to come.

Here is a class that builds the Song objects:

package
{
	import flash.display.Sprite;

	public class Song extends Sprite
	{
		// public properties for the class
		public var earl:String;
		public var artist:String;
		public var track:String;
		public var coverimage:String;

		public function Song(e:String, a:String, t:String, c:String)
		{
			earl = e;
			artist = a;
			track = t;
			coverimage = c;
		}
	}
}

Another class to control the Power button state of the player’s remote control movie:

package
{
    import flash.display.Sprite;
   	import flash.events.MouseEvent;
    import flash.text.TextField;
	import fl.controls.CheckBox;
	import flash.net.SharedObject;
    import flash.net.SharedObjectFlushStatus;
	import flash.events.NetStatusEvent;
	import flash.net.LocalConnection;

	/*
	This class is to allow the user the ability to control power of player each time they visit
	the site.
	*/

    public class PowerButton extends Sprite
    {
        private var togglePower:CheckBox; // allows user to control the music to be ON or OFF
        private var _so:SharedObject;
		private var ctrlMusic:LocalConnection;

        public function PowerButton()
		{
			_so = SharedObject.getLocal("nec-music","/");

			ctrlMusic = new LocalConnection();

            checkPB();

			addChild(togglePower);
        }

		private function checkPB():void
		{
            togglePower = new CheckBox();

            togglePower.label = "Power";
            togglePower.y = 280;

			if (_so.size == 0)
			{
				// user has never been to site. set the default value
				togglePower.selected = true;
				_so.data.power = "ON";

				// flush the shared object
				flushSO();

				//  play the music
				// ctrlMusic.send("lc", "playSong");

			}
			else
			{
				if (_so.data.power == "ON")
				{
					togglePower.selected = true;
				}
				else if (_so.data.power == "OFF")
				{
					togglePower.selected = false;
				}
			}

			togglePower.addEventListener(MouseEvent.CLICK,PowerControl);
        }

        private function PowerControl(e:MouseEvent):void
		{
            if(togglePower.selected == true)
			{
				// set the shared object
				_so.data.power = "ON";

				// play the music
				ctrlMusic.send("lc", "unpauseSong");

				// -----------------------------------------------------------
				// need to enable all controls of the player
				// -----------------------------------------------------------

			}
			else
			{
				// set the shared object
				_so.data.power = "OFF";

				// stop the music
				ctrlMusic.send("lc", "pauseSong");

				// -----------------------------------------------------------
				// need to disable all controls of the player
				// -----------------------------------------------------------

			}

			// flush the shared object
			flushSO();
        }

		private function flushSO():void
		{
			var flushStatus:String = null;  

			try
			{
               	flushStatus = _so.flush(10000);
            }
			catch (error:Error)
			{
               	trace("Error...Could not write SharedObject to disk");
            }

			if (flushStatus != null)
            {
				switch (flushStatus)
               	{
                   	case SharedObjectFlushStatus.PENDING:
                       	trace("Requesting permission to save object...");
                       	_so.addEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
                       	break;
               		case SharedObjectFlushStatus.FLUSHED:
                       	trace("Value flushed to disk. " + _so.data.power);
                       	break;
               	}
            }
		}

		private function onFlushStatus(e:NetStatusEvent):void
		{
            switch (e.info.code)
            {
                case "SharedObject.Flush.Success":
                    trace("User granted permission -- value saved.");
                    break;
                case "SharedObject.Flush.Failed":
                    trace("User denied permission -- value not saved.");
                    break;
            }    

            _so.removeEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
        }
    }
}

A beginning basic class that will build the User Interface:

package
{
	import flash.display.Sprite;

	public class MP3PlayerUI extends Sprite
	{

		public function MP3PlayerUI():void
		{
			// The player design .. this is in the library
			var playerUI = new PlayerDesign();
			addChild(playerUI);

		}
	}
}

File to populate the player with some data:

package
{
    import flash.display.Sprite;
    import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.net.SharedObject;
    import flash.net.SharedObjectFlushStatus;
	import flash.events.Event;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.net.URLRequest;

	/*
	This class is to allow the user the ability to control power of player each time they visit
	the site.
	*/

    public class BandData extends Sprite
    {
		public var tfBandName:TextField;
		public var tfSongName:TextField;

		public var BandName:String;
		public var SongName:String;
		public var CoverImageURL:String;
		private var myImg:Loader = new Loader();

        public function BandData(BandName:String, SongName:String, CoverImageURL:String)
		{
			buildUI();

			tfBandName.text = BandName;
			tfSongName.text = SongName;

			// Load in the image
			// let's load the image
            try {
                myImg.load(new URLRequest(CoverImageURL));
            } catch (error:Error) {
                trace ("Unable to load requested document.");
            }  

            myImg.contentLoaderInfo.addEventListener(Event.COMPLETE,imgResult);
        }

		private function buildUI():void
		{
			// Small Black Text Formatting
			var tf:TextFormat = new TextFormat();
			tf.font = "Arial";
			tf.color = 0x000000;
            tf.size = 9;
            tf.underline = false;

        	// Band Name
        	tfBandName = new TextField();
			tfBandName.defaultTextFormat = tf;
        	addChild(tfBandName);
        	tfBandName.width = 80;
            tfBandName.height = 20;
			tfBandName.x = 90;
        	tfBandName.y = 45;
            tfBandName.multiline = true;
            tfBandName.wordWrap = true;
            tfBandName.border = false;
            tfBandName.background = true;

			// Song Name
			tfSongName = new TextField();
			tfSongName.defaultTextFormat = tf;
        	addChild(tfSongName);
        	tfSongName.width = 80;
            tfSongName.height = 50;
			tfSongName.x = 90;
        	tfSongName.y = 64;
            tfSongName.multiline = true;
            tfSongName.wordWrap = true;
            tfSongName.border = false;
            tfSongName.background = true;
        }

		private function imgResult(e:Event):void
		{
			addChild(myImg);

			myImg.x = 30;
			myImg.y = 45;
		}
    }
}

The code for the player movie itself:

/*
This package is for the MP3 Player that is essentially behind the scenes.
The player is used to:

	-hold all the song data
	-continually play the song as the user moves from one page to another
	-control the song play (if the user doesn't want to play any music when entering the page
*/

package
{
	import flash.display.Sprite;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.LocalConnection;
	import flash.net.SharedObject;
    import flash.net.SharedObjectFlushStatus;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;

	public class MP3Player extends Sprite
	{
		private var xml:XML;
		private var ct:Number = 0; // just a counter
		private var sa:Array = new Array(); // Song Array
		public var s:Sound = new Sound();
		private var channel:SoundChannel;
		private var cps:Number = -1;
		private var _so:SharedObject;
		public var pausePosition:uint;
		public var isPlaying:Boolean;
		private var loadLC:LocalConnection;
		private var toRemoteControl:LocalConnection;

		public function MP3Player()
		{
			Output();

			_so = SharedObject.getLocal("nec-music","/");

			/*
			First off, we need to listen to make sure the Remote Control is loaded.
			We do this because it is the remote that will load and unload from page to page.
			*/
			loadLC = new LocalConnection();
            loadLC.client = this;

            try
			{
                loadLC.connect("lc");
				output.appendText("Connected!\n");
            }
			catch (error:ArgumentError)
			{
                output.appendText("Can't loadConn...the loadConnection name is already being used by another SWF\n");
            }

			/* If we need to send data and call functions to our remote control movie */
			toRemoteControl = new LocalConnection();

		}

		public function remoteSWFLoaded(msg:String):void {
			if ( sa.length == 0 )
			{
				output.appendText("Loading XML File \n" + msg + "\n");
				var loader:URLLoader = new URLLoader();
				loader.load(new URLRequest("files-xml/mp3player.xml"));
				loader.addEventListener(Event.COMPLETE, loadSongs);
			}
			else
			{
				output.appendText("XML File need not be loaded\n");
			}
        }

		private function loadSongs(e:Event):void
		{
			// pull in the xml file and load the song data
			xml = new XML(e.target.data);

			var urlList:XMLList = xml.song.@url;
            var artistList:XMLList =  xml.song.@artist;
			var trackList:XMLList =  xml.song.@track;
			var coverimageList:XMLList = xml.song.@coverimage;

			for each (var urlXML:XML in urlList)
			{
				sa.push(new Song(urlList[ct], artistList[ct], trackList[ct], coverimageList[ct]));

				output.appendText (sa[ct]);

				ct++;
			}

			if ( sa.length == 0 )
			{
				output.appendText("loadSongs Function - no XML data provided\n");
			}
			else
			{
				// tell the remote control to display all the buttons and song data.
				output.appendText("xml loaded, telling MP3RemoteControl file to display button objects\n");
			}

			// Check the Shared Object Status
			output.appendText("Shared Object Size: " + _so.size + "\n");
			output.appendText("Shared Object Power Value: " + _so.data.power + "\n");

			if (_so.size == 0 || _so.data.power == "ON")
			{
				playSong();
			}
			else
			{
				output.appendText("Song will not play, user option\n");
			}

		}

		public function playSong(songDirection:String = "nextSong"):void
		{
			removeEventListener(Event.ENTER_FRAME, SoundProgressHandler);

			if ( channel ) channel.stop();

			output.appendText("playSong function called\n");

			// create a new sound
			var s:Sound = new Sound();

			if ( songDirection == "nextSong" ) {
				// check the value of the currently playing song
				if (cps == sa.length - 1) // is it at the end?
				{
					cps = 0; // re-init the currently playing song
					s.load(new URLRequest(sa[cps].earl));
				}
				else
				{
					s.load(new URLRequest(sa[++cps].earl)); // ++cps will increment the value first and then use it.
				}
			}
			else if ( songDirection == "previousSong" )
			{
				// check the value of the currently playing song
				if ( cps == 0 )
				{
					cps = sa.length - 1;
					s.load(new URLRequest(sa[cps].earl));
				}
				else
				{
					s.load(new URLRequest(sa[--cps].earl)); // --cps will decrement the value firs and then use it.
				}
			}

			// play the music
			channel = s.play();

			// show loading status
			s.addEventListener(ProgressEvent.PROGRESS, SoundProgressHandler);
			s.addEventListener(IOErrorEvent.IO_ERROR, SoundErrorHandler);
			//addEventListener(Event.ENTER_FRAME, SoundProgressHandler);
			addEventListener(Event.ENTER_FRAME, SoundPlayingHandler);
			// stage.addEventListener(MouseEvent.MOUSE_DOWN, SoundPlayingHandler);
			channel.addEventListener(Event.SOUND_COMPLETE, SoundCompleteHandler);

			// update the remote control movie of the music data - the displayBandData function
			toRemoteControl.send("remotecontrollistener","displayBandData", sa[cps].artist, sa[cps].track, sa[cps].coverimage);

			// set boolean for playing
			isPlaying = true;

            channel.addEventListener(Event.SOUND_COMPLETE, continuousPlay);

			// save sound data
			soundData();
		}

		private function continuousPlay(e:Event):void
		{
			// remove listener
			channel.removeEventListener(Event.SOUND_COMPLETE, continuousPlay);
			// play the song
			playSong();
		}

		public function stopSong():void
		{
			// remove listener
			channel.removeEventListener(Event.SOUND_COMPLETE, continuousPlay);

			output.appendText("stopSong function called\n");
			output.appendText(s + " - " + channel);

			// stop the downloading
			// s.close();

			// stop the music
			channel.stop();
		}

		public function PlayPause():void
		{
			// This function to be called from a click of the play pause button from the remote control movie
			output.appendText("Is the music playing? " + isPlaying + "\n");

			if ( isPlaying )
			{
				pauseSong();
			}
			else
			{
				unpauseSong();
			}
		}

		public function pauseSong():void
		{
			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			// NEED TO VERIFY POWER IS ON
			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

			output.appendText("PAUSESONG function called " + channel.position + "\n");

			pausePosition = channel.position;

			channel.stop();

			isPlaying = false;
		}

		public function unpauseSong():void
		{
			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			// NEED TO VERIFY POWER IS ON
			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			output.appendText("UNPAUSESONG function called\n");

			output.appendText("music position: " + pausePosition);

			if ( pausePosition != 0 )
			{
				var s:Sound = new Sound();
				s.load(new URLRequest(sa[cps].earl));

				output.appendText("-> now play current position\n");
				channel = s.play(pausePosition);

				isPlaying = true;
			}
			else
			{
				output.appendText("-> now play next song\n");
				playSong(); // if the remote control movie first loads with the power off
			}

			channel.addEventListener(Event.SOUND_COMPLETE, continuousPlay);

		}

		private function soundData():void
		{
			// This function will be used to save the current music data
		}

		public function debug(msg:String):void
		{
			output.appendText("\n" + msg + "\n");
		}

		private var loadTime:Number;
		private var loadPercent:uint;

		private function SoundProgressHandler(e:ProgressEvent):void
		{

            loadTime = e.bytesLoaded / e.bytesTotal;
            loadPercent = Math.round(100 * loadTime);

			output.text = "Sound file's size is " + e.bytesTotal + " bytes.\n"
                                   + "Bytes being loaded: " + e.bytesLoaded + "\n"
                                   + "Percentage of sound file that is loaded " + loadPercent + "%.\n";
        }

		private function SoundPlayingHandler(e:Event)
		{
			// output.text = channel + " Position: " + channel.position + " out of " + s.length + " " + loadTime;
			var estimatedLength:int = Math.ceil(s.length / (s.bytesLoaded / s.bytesTotal));
    		var playbackPercent:uint = Math.round(100 * (channel.position / estimatedLength));
		    output.appendText("Sound playback " + playbackPercent + "%\n");
		}

		private function SoundCompleteHandler(e:Event):void
		{
			output.appendText("Sound Loaded, killing event handler");
			removeEventListener(Event.ENTER_FRAME, SoundProgressHandler);
		}

		private function SoundErrorHandler(errorEvent:IOErrorEvent):void {
            output.text = "The sound could not be loaded: " + errorEvent.text;
        }

		// UI elements
    	private var output:TextField;

		public function Output():void
		{

			// Small Black Text Formatting
			var smallBlackFormat:TextFormat = new TextFormat();
			smallBlackFormat.font = "Arial";
			smallBlackFormat.color = 0x000000;
            smallBlackFormat.size = 10;
            smallBlackFormat.underline = false;

        	// output TextField
        	output = new TextField();
			output.defaultTextFormat = smallBlackFormat;
        	addChild(output);
        	output.width = 210;
            output.height = 400;
			output.x = 0;
        	output.y = 0;
            output.multiline = true;
            output.wordWrap = true;
            output.border = true;
            output.background = true;
			output.text = "DEBUGGING:\n";
        }

	}
}

As the player is progressing, I will update this code base.

Posted in Actionscript 3, Audio.


One Response

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. kiss says

    how to download source code?



Some HTML is OK

or, reply to this post via trackback.