In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: MP3 Player + Visualization - Demo

/**
 * Copyright Aksor.Al ( http://wonderfl.net/user/Aksor.Al )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/mLn0
 */

// forked from seikimaiii's MP3 Player + Visualization - Demo
// forked from seikimaiii's MP3 Player - Demo
/**
* This project is set up to demo my mp3 player.  Feel free to test it out.
*/
package
{
    import flash.text.TextField;
    import flash.display.MovieClip;
    import flash.display.Shape;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.media.SoundTransform;
    import flash.net.URLRequest;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.utils.Timer;
    import flash.external.ExternalInterface;
    import flash.system.Security;
    
    [SWF(frameRate="30",width=400,height=60,backgroundColor=0)]
    
    /**
    *
    * @author SeikimaIII
    * v1.0
    *
    * Music Class
    * Container for all the individual player elements.
    *
    */
    public class Music extends MovieClip
    {
        public var _boxTop:Shape;
        
        public var _buttonPrevious:PreviousButton;
        public var _buttonPlay:PlayButton;
        public var _buttonNext:NextButton;
        public var _buttonVolume:VolumeButton;
        
        public var _infoBar:InfoBar;
        
        private var _timer:Timer;
        
        // Sounds
        private var _mainSound:Sound;
        private var _bufferSound:Sound;
        private var _channel:SoundChannel;
        private var _transform:SoundTransform;
        private var _cue:Number;
        private var _durationS:Number;
        private var _durationMS:Number;
        private var _isPlaying:Boolean;
        
        // Website objects
        private var _mainURL:String;
        private var _bufferURL:String;
        
        
        public function Music():void
        {
            Security.allowDomain("music.lunchbin.com");
            Security.loadPolicyFile("http://music.lunchbin.com/crossdomain.xml");
            
            // Initialize graphics objects
            _boxTop = new Shape();
            
            // Initialize buttons
            _buttonPrevious = new PreviousButton();
            _buttonPlay = new PlayButton();
            _buttonNext = new NextButton();
            _buttonVolume = new VolumeButton(OnVolumeChanged);
            
            // Initialize info
            _infoBar = new InfoBar(OnPlayPositionChanged);
            addChild(_infoBar);
            
            // Buttons
            _buttonPrevious.SetPosition(0, 30);
            _buttonPlay.SetPosition(100, 30);
            _buttonNext.SetPosition(200, 30);
            _buttonVolume.SetPosition(300, 30);
            addChild(_buttonPrevious);
            addChild(_buttonPlay);
            addChild(_buttonNext);
            addChild(_buttonVolume);
            
            // Top box
            _boxTop.graphics.lineStyle(1, 0xFFFFFF, 1);
            _boxTop.graphics.drawRect(0, 0, 399, 30);
            addChild(_boxTop);
            
            // Button Events
            _buttonPrevious.addEventListener(MouseEvent.CLICK, OnPrevious);
            _buttonPlay.addEventListener(MouseEvent.CLICK, OnPlay);
            _buttonNext.addEventListener(MouseEvent.CLICK, OnNext);
   
            // Sound setup
            _transform = new SoundTransform(1, 0);
   
            // Main timer         
            _timer = new Timer(33.33); //30fps
            _timer.addEventListener(TimerEvent.TIMER, Tick);
            _timer.start();
        }
        
        // Main loop
        public function Tick(e:TimerEvent):void
        {
            // Update the song information
            if (_channel != null && _mainSound != null)
            {
                _infoBar.Update(_channel.position, _durationMS, _mainSound.bytesLoaded/_mainSound.bytesTotal);
            }
            else
            {
                _infoBar.Pause();
            }
        }
        
        // Play the given song
        public function Play(playlistItem:Object):void
        {
            var fileName:String = String(playlistItem[0]);
            var fileURL:String = String(playlistItem[1]);
            var playTime:String = String(playlistItem[2]);
            // Stop current sound
            if (_channel != null)
            {
                _channel.stop();
                _channel = null;
            }
            // Delete main sound
            _mainSound = null;
            // Reset the info bar
            _infoBar.Reset();
            // Assign the url
            _mainURL = fileURL;
            // Reset the position
            _cue = 0;
            // Is this the buffer sound
            if (_mainURL == _bufferURL)
            {
                // Set _mainSound to null
                _mainSound = null;
                // Assign buffer sound to main sound
                _mainSound = _bufferSound;
            }
            else // This is a new sound
            {
                // Set _mainSound to null
                _mainSound = null;
                // Create a new Sound
                _mainSound = new Sound();
                // Load the sound
                _mainSound.load(new URLRequest(_mainURL));
            }
            // Is the sound already loaded
            if (!_mainSound.isBuffering)
            {
                OnLoadComplete(null);
            }
            else // It isn't finished yet, assign an event
            {
                _mainSound.addEventListener(Event.COMPLETE, OnLoadComplete);
            }
            // Calculate the duration passed in
            _durationS = CalculateDuration(playTime);
            _durationMS = _durationS*1000;
            // Play the main sound
            _channel = _mainSound.play();
            // Reassign the sound transform
            _channel.soundTransform = _transform;
            // When the song is done, load the next track
            _channel.addEventListener(Event.SOUND_COMPLETE, OnSoundComplete);
            // Set the title
            _infoBar.SetSongTitle(fileName);
            // Set the is playing flag
            _isPlaying = true;
        }
        
        // Stop the player and reset
        public function Stop():void
        {
            // Stop the current sound
            if (_channel != null)
            {
                _channel.stop();
                _channel = null;
            }
            // Delete sounds
            _mainSound = null;
            _bufferSound = null;
            // Reset file names
            _mainURL = ""
            _bufferURL = "";
            // Reset the Loaded bar and Marker
            _infoBar.Reset();
            // Reset the play cue
            _cue = 0;
            // Reset duration
            _durationS = 0;
            _durationMS = 0;
            // Set the is playing flag
            _isPlaying = false;
        }
        
        //---------------------------------------
        // Events
        //---------------------------------------
        
        // Try to load the next available track
        public function OnLoadComplete(e:Event):void
        {
            // Is main sound done loading
            if (!_mainSound.isBuffering)
            {
                PeekNextTrack();
                // I have to move these calls because flash urlloader is asynchronous :(
                //_bufferURL = PeekNextTrack();
                //_bufferSound = new Sound();
                //_bufferSound.load(new URLRequest(_bufferURL));
            }
            else
            {
                _bufferURL = "";
                _bufferSound = null;
            }
        }
        
        // Called when the song currently playing is finished
        public function OnSoundComplete(e:Event):void
        {
            GetNextTrack();
        }

        // Called from the Play button
        public function OnPlay(e:MouseEvent):void
        {
            // Play/Pause sounds
            if (_mainSound == null)
            {
                GetCurrentTrack();
            }
            else
            {
                if (_isPlaying)
                {
                    // Get the position
                    _cue = _channel.position;
                    // Stop the channel
                    _channel.stop();
                    _channel = null;
                    // Set the is playing flag
                    _isPlaying = false;
                }
                else
                {
                    // Play the sound
                    _channel = _mainSound.play(_cue);
                    _channel.soundTransform = _transform;
                    _channel.addEventListener(Event.SOUND_COMPLETE, OnSoundComplete);
                    // Set the is playing flag
                    _isPlaying = true;
                }
            }
        }
        
        // Called from the Next button
        public function OnNext(e:MouseEvent):void
        {
            GetNextTrack();
        }
        
        // Called from the Previous button
        public function OnPrevious(e:MouseEvent):void
        {
            GetPreviousTrack();
        }
        
        // Called when the volume slider is moved
        public function OnVolumeChanged(volume:Number):void
        {
            // Change the volume
            _transform.volume = volume;
            // Apply it to the channel
            if (_channel != null)
            {
                _channel.soundTransform = _transform;
            }
        }
        
        // Called when the user clicks on the play bar, advancing or rewinding the current song
        public function OnPlayPositionChanged(skipPercentage:Number):void
        {
            if (_mainSound != null && _isPlaying)
            {
                // Basic idea: use MousePosition to get a pecentage of the movie width, multiply that times the song duration
                // For example: user clicks on pixel 100 (width), percentage of the movie width is 25%, jump to 25% in the song (25% * song duration)
                _cue = CalculateSeconds(skipPercentage)*1000;
                // Stop the current sound
                if (_channel != null)
                {
                    _channel.stop();
                    _channel = null;
                }
                // Restart the current sound
                _channel = _mainSound.play(_cue);
                _channel.soundTransform = _transform;
                _channel.addEventListener(Event.SOUND_COMPLETE, OnSoundComplete);
            }
        }

        
        //---------------------------------------
        // Helper functions
        //---------------------------------------
        
        public function CalculateDuration(playTime:String):Number
        {
            var times:Array = playTime.split(":");
            return (parseInt(times[0]) * 60) + (parseInt(times[1]));
        }
        
        public function CalculateSeconds(percent:Number):Number
        {
            return Math.floor(percent * _durationS);
        }
        
        //---------------------------------------
        // External Javascript Functions
        //---------------------------------------
   
        public function GetCurrentTrack():void
        {
            var loader:URLLoader = new URLLoader();
            loader.dataFormat = URLLoaderDataFormat.VARIABLES;
            loader.addEventListener(Event.COMPLETE, OnURLLoaderComplete_Play);
            loader.load(new URLRequest("http://music.lunchbin.com/demo/demo.php?action=get_current&prev_title=" + escape(_infoBar.GetSongTitle())));
        }
        
        public function GetPreviousTrack():void
        {
            var loader:URLLoader = new URLLoader();
            loader.dataFormat = URLLoaderDataFormat.VARIABLES;
            loader.addEventListener(Event.COMPLETE, OnURLLoaderComplete_Play);
            loader.load(new URLRequest("http://music.lunchbin.com/demo/demo.php?action=get_prev&prev_title=" + escape(_infoBar.GetSongTitle())));
        }
        
        public function GetNextTrack():void
        {
            var loader:URLLoader = new URLLoader();
            loader.dataFormat = URLLoaderDataFormat.VARIABLES;
            loader.addEventListener(Event.COMPLETE, OnURLLoaderComplete_Play);
            loader.load(new URLRequest("http://music.lunchbin.com/demo/demo.php?action=get_next&prev_title=" + escape(_infoBar.GetSongTitle())));
        }

        public function PeekNextTrack():void
        {
            var loader:URLLoader = new URLLoader();
            loader.dataFormat = URLLoaderDataFormat.VARIABLES;
            loader.addEventListener(Event.COMPLETE, OnURLLoaderComplete_Peek);
            loader.load(new URLRequest("http://music.lunchbin.com/demo/demo.php?action=get_next&prev_title=" + escape(_infoBar.GetSongTitle())));
        }
        
        public function OnURLLoaderComplete_Play(e:Event):void
        {
            var loader:URLLoader = URLLoader(e.target);
            Play(new Array(loader.data.name, loader.data.url, loader.data.playtime));
        }

        public function OnURLLoaderComplete_Peek(e:Event):void
        {
            var loader:URLLoader = URLLoader(e.target);
            _bufferURL = loader.data.url;
            _bufferSound = new Sound();
            _bufferSound.load(new URLRequest(_bufferURL));
        }
    }
}

import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.GradientType;
import flash.media.SoundMixer;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.geom.Matrix;
import flash.utils.ByteArray;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.external.ExternalInterface;

/**
*
* @author SeikimaIII
* v1.0
*
* Play Button Class
* Makes a play button.
*
*/
class PlayButton extends MovieClip
{
    public var _mc:MovieClip;
    public var _paused:Boolean = false;
    
    private var _primary_color:uint;
    private var _secondary_color:uint;
    
    public function PlayButton():void
    {
        _mc = new MovieClip();
        
        // Member variables
        _primary_color = 0xFFFFFF;
        _secondary_color = 0x675122;
        
        // Button modifiers
        _mc.buttonMode = true;
        _mc.useHandCursor = true;
        
        // Events
        _mc.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
        _mc.addEventListener(MouseEvent.CLICK, OnMouseClick);
        _mc.addEventListener(MouseEvent.MOUSE_OUT, OnMouseOut);
        
        // Draw
        this.Draw(_primary_color);
        
        addChild(_mc);
    }
    
    private function Draw(color:uint):void
    {
        // Gradient filter        
        var m:Matrix = new Matrix();
        m.createGradientBox(100, 30, Math.PI * 0.5);
        _mc.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0x5e5e5e], null, null, m);
        
        // Rect
        _mc.graphics.lineStyle(1, 0xFFFFFF, 1);
        _mc.graphics.drawRect(0, 0, 100, 29);
        _mc.graphics.endFill();
        
        _mc.graphics.lineStyle(0, 0, 0);
        
        // Create the button face
        if (!_paused)
        {
            // Draw an arrow
            _mc.graphics.beginFill(color);
            _mc.graphics.moveTo(45, 5);
            _mc.graphics.lineTo(45, 25);
            _mc.graphics.lineTo(60, 15);
            _mc.graphics.lineTo(45, 5);
            _mc.graphics.endFill();
        }
        else
        {
            // Draw two lines
            _mc.graphics.beginFill(color);
            _mc.graphics.moveTo(45, 5);
            _mc.graphics.lineTo(45, 25);
            _mc.graphics.lineTo(50, 25);
            _mc.graphics.lineTo(50, 5);
            _mc.graphics.lineTo(45, 5);
            _mc.graphics.moveTo(55, 5);
            _mc.graphics.lineTo(55, 25);
            _mc.graphics.lineTo(60, 25);
            _mc.graphics.lineTo(60, 5);
            _mc.graphics.lineTo(55, 5);
            _mc.graphics.endFill();
        }
        
        // Create gradient shine
        m.createGradientBox(97, 10, Math.PI * 0.5);
        _mc.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xFFFFFF], [0.5, 0], null, m);
        _mc.graphics.lineStyle(0, 0, 0);
        _mc.graphics.drawRect(2, 2, 97, 10);
        _mc.graphics.endFill();
    }
    
    private function OnMouseDown(e:MouseEvent):void
    {
        this.Draw(_secondary_color);
    }
    
    private function OnMouseClick(e:MouseEvent):void
    {
        _paused = !_paused;
        this.Draw(_primary_color);
    }
    
    private function OnMouseOut(e:MouseEvent):void
    {
        this.Draw(_primary_color);
    }
    
    public function SetPosition(x:Number, y:Number):void
    {
        _mc.x = x;
        _mc.y = y;
    }
}

/**
*
* @author SeikimaIII
* v1.0
*
* Previous Button Class
* Makes a previous button.
*
*/
class PreviousButton extends MovieClip
{
    public var _mc:MovieClip;
    
    private var _primary_color:uint;
    private var _secondary_color:uint;
    
    public function PreviousButton():void
    {
        _mc = new MovieClip();
        
        // Member variables
        _primary_color = 0xFFFFFF;
        _secondary_color = 0x675122;
        
        // Button modifiers
        _mc.buttonMode = true;
        _mc.useHandCursor = true;
        
        // Events
        _mc.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
        _mc.addEventListener(MouseEvent.CLICK, OnMouseClick);
        _mc.addEventListener(MouseEvent.MOUSE_OUT, OnMouseOut);
        
        // Draw
        this.Draw(_primary_color);
        
        addChild(_mc);
    }
    
    private function Draw(color:uint):void
    {
        // Gradient filter        
        var m:Matrix = new Matrix();
        m.createGradientBox(100, 30, Math.PI * 0.5);
        _mc.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0x5e5e5e], null, null, m);
        
        // Rect
        _mc.graphics.lineStyle(1, 0xFFFFFF, 1);
        _mc.graphics.drawRect(0, 0, 100, 29);
        _mc.graphics.endFill();
        
        _mc.graphics.lineStyle(0, 0, 0);
        
        // Create the button face
        _mc.graphics.beginFill(color);
        _mc.graphics.moveTo(55, 5);
        _mc.graphics.lineTo(55, 25);
        _mc.graphics.lineTo(40, 15);
        _mc.graphics.lineTo(55, 5);
        _mc.graphics.endFill();
        
        _mc.graphics.beginFill(color);
        _mc.graphics.moveTo(60, 5);
        _mc.graphics.lineTo(60, 25);
        _mc.graphics.lineTo(45, 15);
        _mc.graphics.lineTo(60, 5);
        _mc.graphics.endFill();
        
        // Create gradient shine
        m.createGradientBox(97, 10, Math.PI * 0.5);
        _mc.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xFFFFFF], [0.5, 0], null, m);
        _mc.graphics.lineStyle(0, 0, 0);
        _mc.graphics.drawRect(2, 2, 97, 10);
        _mc.graphics.endFill();
    }
    
    private function OnMouseDown(e:MouseEvent):void
    {
        this.Draw(_secondary_color);
    }
    
    private function OnMouseClick(e:MouseEvent):void
    {
        this.Draw(_primary_color);
    }
    
    private function OnMouseOut(e:MouseEvent):void
    {
        this.Draw(_primary_color);
    }
    
    public function SetPosition(x:Number, y:Number):void
    {
        _mc.x = x;
        _mc.y = y;
    }
}

/**
*
* @author SeikimaIII
* v1.0
*
* Next Button Class
* Makes a next button.
*
*/
class NextButton extends MovieClip
{
    public var _mc:MovieClip;
    
    private var _primary_color:uint;
    private var _secondary_color:uint;
    
    public function NextButton():void
    {
        _mc = new MovieClip();
        
        // Member variables
        _primary_color = 0xFFFFFF;
        _secondary_color = 0x675122;
        
        // Button modifiers
        _mc.buttonMode = true;
        _mc.useHandCursor = true;
        
        // Events
        _mc.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
        _mc.addEventListener(MouseEvent.CLICK, OnMouseClick);
        _mc.addEventListener(MouseEvent.MOUSE_OUT, OnMouseOut);
        
        // Draw
        this.Draw(_primary_color);
        
        addChild(_mc);
    }
    
    private function Draw(color:uint):void
    {
        // Gradient filter        
        var m:Matrix = new Matrix();
        m.createGradientBox(100, 30, Math.PI * 0.5);
        _mc.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0x5e5e5e], null, null, m);
        
        // Rect
        _mc.graphics.lineStyle(1, 0xFFFFFF, 1);
        _mc.graphics.drawRect(0, 0, 100, 29);
        _mc.graphics.endFill();
        
        _mc.graphics.lineStyle(0, 0, 0);
        
        // Create the button face
        _mc.graphics.beginFill(color);
        _mc.graphics.moveTo(40, 5);
        _mc.graphics.lineTo(40, 25);
        _mc.graphics.lineTo(55, 15);
        _mc.graphics.lineTo(40, 5);
        _mc.graphics.endFill();
        
        _mc.graphics.beginFill(color);
        _mc.graphics.moveTo(45, 5);
        _mc.graphics.lineTo(45, 25);
        _mc.graphics.lineTo(60, 15);
        _mc.graphics.lineTo(45, 5);
        _mc.graphics.endFill();
        
        // Create gradient shine
        m.createGradientBox(97, 10, Math.PI * 0.5);
        _mc.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xFFFFFF], [0.5, 0], null, m);
        _mc.graphics.lineStyle(0, 0, 0);
        _mc.graphics.drawRect(2, 2, 97, 10);
        _mc.graphics.endFill();
    }
    
    private function OnMouseDown(e:MouseEvent):void
    {
        this.Draw(_secondary_color);
    }
    
    private function OnMouseClick(e:MouseEvent):void
    {
        this.Draw(_primary_color);
    }
    
    private function OnMouseOut(e:MouseEvent):void
    {
        this.Draw(_primary_color);
    }
    
    public function SetPosition(x:Number, y:Number):void
    {
        _mc.x = x;
        _mc.y = y;
    }
}

/**
*
* @author SeikimaIII
* v1.0
*
* Volume Button Class
* Makes a volume slider
*
*/
class VolumeButton extends MovieClip
{
    public var _mc:MovieClip;
    private var _slider:MovieClip;
    private var _bar:MovieClip;
    private var _shine:Shape;
    
    private var _primary_color:uint;
    private var _secondary_color:uint;
    
    private var _volumeChangedCallBack:Function;
    
    private var _isDragging:Boolean = false;
    
    public function VolumeButton(volumeCallBack:Function):void
    {
        _mc = new MovieClip();
        
        // Member variables
        _primary_color = 0xFFFFFF;
        _secondary_color = 0x675122;
        _volumeChangedCallBack = volumeCallBack;
        
        // Draw
        this.Draw(_primary_color);
        
        addChild(_mc);
    }
    
    private function Draw(color:uint):void
    {
        // Gradient filter        
        var m:Matrix = new Matrix();
        m.createGradientBox(100, 30, Math.PI * 0.5);
        _mc.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0x5e5e5e], null, null, m);
        
        // Rect
        _mc.graphics.lineStyle(1, 0xFFFFFF, 1);
        _mc.graphics.drawRect(0, 0, 99, 29);
        _mc.graphics.endFill();
        
        // Create the bar
        _bar = new MovieClip();
        m.createGradientBox(80, 10, Math.PI * 0.5);
        _bar.graphics.lineStyle(1, 0x666666, 1);
        _bar.graphics.beginGradientFill(GradientType.LINEAR, [0x1e1e1e, 0x65e5e5e], null, null, m);
        _bar.graphics.drawRect(0, 0, 80, 6);
        _bar.graphics.endFill();
        _mc.addChild(_bar);
        _bar.x = 10;
        _bar.y = 12;
        
        // Create the slider
        _slider = new MovieClip();
        m.createGradientBox(20, 20, Math.PI * 1.5);
        _slider.graphics.lineStyle(1, 0x333333, 1);
        _slider.graphics.beginGradientFill(GradientType.LINEAR, [0x333333, 0x666666], null, null, m);
        _slider.graphics.drawRect(-8, -8, 16, 16);
        _slider.graphics.endFill();
        _slider.graphics.moveTo(-4, -6);
        _slider.graphics.lineTo(-4, 6);
        _slider.graphics.moveTo(0, -6);
        _slider.graphics.lineTo(0, 6);
        _slider.graphics.moveTo(4, -6);
        _slider.graphics.lineTo(4, 6);
        _mc.addChild(_slider);
        _slider.x = 85;
        _slider.y = 15;
        
        // Create gradient shine
        _shine = new Shape();
        m.createGradientBox(97, 10, Math.PI * 0.5);
        _shine.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xFFFFFF], [0.5, 0], null, m);
        _shine.graphics.lineStyle(0, 0, 0);
        _shine.graphics.drawRect(2, 2, 97, 10);
        _shine.graphics.endFill();
        _mc.addChild(_shine);
        
        // Events
        _slider.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
        _slider.addEventListener(MouseEvent.MOUSE_UP, OnMouseUp);
        _slider.addEventListener(MouseEvent.MOUSE_OUT, OnMouseOut);
        _slider.addEventListener(MouseEvent.MOUSE_MOVE, OnMouseMove);
        
        // Button modifiers
        _slider.buttonMode = true;
        _slider.useHandCursor = true;
    }
    
    private function OnMouseDown(e:MouseEvent):void
    {
        _slider.startDrag(true, new Rectangle(15, 15, 70, 0));
        _isDragging = true;
    }
    
    private function OnMouseUp(e:MouseEvent):void
    {
        _slider.stopDrag();
        _isDragging = false;
    }
    
    private function OnMouseOut(e:MouseEvent):void
    {
        _slider.stopDrag();
        _isDragging = false;
    }
    
    private function OnMouseMove(e:MouseEvent):void
    {
        if (_isDragging)
        {
            var volume:Number = ((_slider.x - 15) / 70);
            _volumeChangedCallBack(volume);
        }
    }
    
    public function SetPosition(x:Number, y:Number):void
    {
        _mc.x = x;
        _mc.y = y;
    }
}

/**
*
* @author SeikimaIII
* v1.0
*
* InfoBar Class
* Contains all the information layers for the player (song title, song position, etc.).
* Controls the player position via mouse down event on the top bar.
*
*/
class InfoBar extends MovieClip
{
    private var _mc:MovieClip;
    
    private var _playPosition:TextField;
    private var _playTime:Number = 0;
    
    private var _songTitle:TextField;
    private var _songTitleMask:MovieClip;
    
    private var _playBar:MovieClip;
    private var _loadBar:MovieClip;
    private var _visBar:MovieClip;

    private var _heights:Array;    
    private var _bytes:ByteArray;
    private var _steps:Number;
    private var _resolution:Number;
    private var _width:Number;
    private var _height:Number;
    
    private var _positionChangedCallback:Function;
    
    public function InfoBar(positionChangedCallback:Function):void
    {
        _mc = new MovieClip();    
        
        // Background
        _mc.graphics.beginFill(0xCCCCCC);
        _mc.graphics.drawRect(0, 0, 400, 30); 
        _mc.graphics.endFill();
        _mc.width = 400;
        _mc.height = 30;

        // Load position bar
        _loadBar = new MovieClip();
        _loadBar.graphics.beginFill(0x675122);
        _loadBar.graphics.drawRect(0, 0, 400, 30);
        _loadBar.graphics.endFill();
        _mc.addChild(_loadBar);
        
        // Play position bar
        _playBar = new MovieClip();
        _playBar.graphics.beginFill(0x352a14);
        _playBar.graphics.drawRect(0, 0, 400, 30);
        _playBar.graphics.endFill();
        _mc.addChild(_playBar);
        
        // Play position text
        _playPosition = new TextField();
        _playPosition.x = 335;
        _playPosition.y = 2;
        _playPosition.multiline = false;
        _playPosition.text = "00:00";
        _playPosition.setTextFormat(new TextFormat("Verdana", 18, 0xFFFFFF));
        _playPosition.width = _playPosition.textWidth + 10;
        _playPosition.height = 25;
        _playPosition.selectable = false;
        _mc.addChild(_playPosition);
        
        // Song title mask        
        _songTitleMask = new MovieClip();
        _songTitleMask.graphics.beginFill(0);
        _songTitleMask.graphics.drawRect(0, 0, 330, 30);        
        _songTitleMask.graphics.endFill();
        
        // Song title text
        _songTitle = new TextField();
        _songTitle.mask = _songTitleMask;
        _songTitle.x = 200;
        _songTitle.y = 8;
        _songTitle.multiline = false;
        _songTitle.text = "waiting...";
        _songTitle.setTextFormat(new TextFormat("Verdana", 10, 0xFFFFFF));
        _songTitle.width = _songTitle.textWidth + 10;
        _songTitle.height = 18;
        _songTitle.selectable = false;
        _mc.addChild(_songTitle);
        
        // Visualization Bar
        _visBar = new MovieClip();
        // I have to draw something here otherwise it will not show up
        _visBar.graphics.beginFill(0x888888);
        _visBar.graphics.drawRect(0, 0, 400, 30);
        _visBar.graphics.endFill();
        _visBar.graphics.clear();
        _mc.addChild(_visBar);
        // Variables
        _heights = new Array();
        _bytes = new ByteArray();
        _resolution = 16;
        _steps = 256/_resolution;
        _width = 400/_resolution;
        _height = 30;
        // Setup
        for (var i:uint = 0; i < _steps; i++)
        {
            _heights[i] = 0;
        }
        
        _mc.addEventListener(MouseEvent.MOUSE_UP, OnMouseUp);
        addChild(_mc);
        
        // Callback event
        _positionChangedCallback = positionChangedCallback;
    }
    
    public function Update(position:Number, length:Number, loaded:Number):void
    {
        // Play bar
        var newPlayPosition:Number = Math.floor(position/length * 400);
        if (newPlayPosition > _playBar.width)
        {
            _playBar.width = newPlayPosition;
        }
        
        // Load bar
        var newLoadPosition:Number = Math.floor(loaded * 400);
        if (newLoadPosition > _loadBar.width)
        {
            _loadBar.width = newLoadPosition;
        }
        
        // Play Position
        var minutes:Number = Math.floor(position/60000);
        var seconds:Number = Math.ceil((position - minutes*60000)/1000);
        // Check the time
        if (isNaN(minutes) || isNaN(seconds))
        {
            _playPosition.text = "00:00";
        }
        else
        {
            if (minutes < 10)
            {
                _playPosition.text = "0";
                _playPosition.appendText(String(minutes));
            }
            else
            {
                _playPosition.text = String(minutes);
            }
            if (seconds < 10)
            {
                _playPosition.appendText(":0");
                _playPosition.appendText(String(seconds));
            }
            else
            {
                _playPosition.appendText(":");
                _playPosition.appendText(String(seconds));
            }
        }
        _playPosition.setTextFormat(new TextFormat("Verdana", 18, 0xFFFFFF)); // Why do I have to do this every time?
        _playPosition.width = _playPosition.textWidth + 4;
        _playPosition.x = 400 - _playPosition.width - 10;
                
        // Song Title 
        _songTitle.x = _songTitle.x - 1;
        if (_songTitle.x <= (0 - _songTitle.textWidth))
        {
            _songTitle.x = 330;
        }
        
        // Spectrum Bar
        _visBar.graphics.clear();
                
        _bytes.position = 0;
        SoundMixer.computeSpectrum(_bytes, true);
        
        for (var i:uint = 0; i < _steps; i++)
        {
            var l:Number = GetMax(_bytes, i*_resolution*4, _resolution);
            var r:Number = GetMax(_bytes, i*_resolution*4 + 1024, _resolution);
            var avg:Number = (l + r) / 2;
            var n:Number = (avg * _height);
            
            if (n > _heights[i])
            {
                _heights[i] = n;
            }
            else
            {
                if (_heights[i] > 0)
                {
                    _heights[i] -= (_heights[i]) * 0.05;
                }
                if (_heights[i] < 0)
                {
                    _heights[i] = 0;
                }
            }
            
            //_visBar.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xFFFFFF], [1, 0], null);
            _visBar.graphics.beginFill(0xffffff, (_heights[i]/_height)/2);
            _visBar.graphics.drawRect(i*_width, _height, _width, -1 * _heights[i]);
            _visBar.graphics.endFill();
        }
    }
    
    public function GetMax(bytes:ByteArray, start:Number, length:Number):Number
    {
        var max:Number = 0;
        bytes.position = start;
        for (var i:uint = 0; i < length; i++)
        {
            var test:Number = bytes.readFloat();
            if (test > max)
            {
                max = test;
            }
        }
        return max;
    }
    
    public function GetAvg(bytes:ByteArray, start:Number, length:Number):Number
        {
            var avg:Number = 0;
            bytes.position = start;
            for (var i:uint = 0; i < length; i++)
            {
                avg += bytes.readFloat();
            }
            avg /= length;
            return avg;
        }
    
    public function Pause():void
    {
        // Song Title 
        _songTitle.x = _songTitle.x - 1;
        if (_songTitle.x <= (0 - _songTitle.textWidth))
        {
            _songTitle.x = 330;
        }
    }
    
    public function SetSongTitle(title:String):void
    {
        _songTitle.text = title;
        _songTitle.setTextFormat(new TextFormat("Verdana", 10, 0xFFFFFF));
        _songTitle.width = _songTitle.textWidth + 4;
    }
    
    public function GetSongTitle():String
    {
        return _songTitle.text;    
    }
    
    public function Reset():void
    {
        _playTime = 0;
        _playBar.width = 0;
        _loadBar.width = 0;
        _songTitle.text = "";
    }
    
    public function OnMouseUp(e:MouseEvent):void
    {
        _playBar.width = Math.min(mouseX, _loadBar.width);
        _positionChangedCallback(_playBar.width/400);
    }
}