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.
how to download source code?