/*
	VERSION:		3.6
	3.6		Added "isFading" flag
	3.5		New songs interrupt fadeTo() tranitions  (make them immediatley jump to their final volume levels)
	
	DESCRIPTION:
		This is a movieClip-based music system.
		It streams external .mp3 files.
	
	KNOWN GLITCH:
		If you play a song at a volume less than 100, you will not be able to increase the volume.
	TEMP SOLUTION:
		Always start the music at 100% volume, then adjust afterwords.
			music.songVolume = 100;
			music.volume = 100;
			music.play( "song.mp3" );
			music.songVolume = myVolume;
	
	MINIMAL USAGE:
		#include "makeStreamingMusic.as"
		MUSIC = makeStreamingMusic();
		MUSIC.play( "songName.mp3" );
		
		
	MAX USAGE:
		#include "makeStreamingMusic.as"
		MUSIC = makeStreamingMusic( target_mc:MovieClip, newName:String, [newDepth:Number] );
		MUSIC.play( "songName.mp3" );
		
		
	FUNCTIONS:
		play( "songName.mp3" );					// Plays the songName_intro tune, then switches to songName (which should loop)
		playLoop( "songName.mp3" );			// Skip any intros and specifically play the main loop of the song
		stopMusic();										// Stops the music and forgets the last song
		fadeTo( newVolume, seconds );		// Fades the song volume to a new level
		
	VARIABLES:
		songName								// file path of the last song sent to this system
		isPlaying								// whether the current song is playing or stopped
		
	PROPERTIES:
		volume								// scalar (percentage) that gets or sets the maximum playback volume of all music
		songVolume							// gets or sets the intensity of THIS song  (used for fades)
		
		Playback volume  =  songVolume * (volume/100)
		To change the volume of all music played, use "volume".
		To change the volume of only the current song, use "songVolume".
		All songs start playback with a "songVolume" of 100.
	
	EVENTS:
		onLoad()									// Called when a song or song intro successfully starts.
		onSoundComplete()					// Called when a song or song intro completes.  (the song doesn't neccesarily stop)
		onFadeComplete()					// Called when a fadeTo() completes.
		onID3()										// Called each time an ID3 tag is loaded.  (if there are two versions in a file, it gets called twice)
		onStop()									// Called when the music is explicitly stopped
		
	INTROS & LOOPS:
		You may add folders before the fileNames.
		Name your files / linkages like so:
			songName_intro.mp3			play("songName.mp3")				(The extension must be .mp3)
			songName.mp3					playLoop("songName.mp3")			(This is the looping version of the song.)
		When play() is used, it'll automatically attempt to load an intro for the song. If there's no intro, it'll play the loop.
		
	DEPENDANCIES:
		nextDepth.as
*/



makeStreamingMusic = function( target_mc, newName, newDepth )
{
	// resolve optional parameters
	var target_mc = (target_mc != undefined) ? target_mc : this;
	var newName = (newName != undefined) ? newName : "musicSystem_mc";
	#include "nextDepth.as"
	var newDepth = (newDepth) ? newDepth : nextDepth(target_mc);
	
	// create containers
	var _this = target_mc.createEmptyMovieClip( newName, newDepth );
	_this.music = new Sound();
	_this._volume = 1;										// multiplier:  1 = 100%
	_this._songVolume = 1;								// multiplier:  1 = 100%
	_this.isPlaying = false;
	_this.songName = "";
	
	// Mimic Sound events		(these can be externally defined)
	_this.onID3 = function(){}
	_this.onLoad = function(){}
	_this.onSoundComplete = function(){}
	_this.onFadeComplete = function(){}		// triggers when fadeTo() completes
	_this.isFading = false;								// the existence of _this.fade could also indicate whether a fade isoccurring,  but a flag like this is more descriptive and allows the underlying implementation to change
	
	
	
	
	
	// FUNCTIONS
	_this.playSong = function( songName, skipIntro )
	{
		if(_this.songName != songName)
		{
			// immediately complete the fade tween if it exists
			_this.fade.fforward();
			_this.fade.onMotionFinished();
			delete _this.fade;
			
			// transition:  intro  ->  loop
			_this.music.onSoundComplete = function()
			{
				// play normally
				var songName = _this.songName;
				_this.songName = "";					// spoof it so it'll play the same song again
				setTimeout( _this.playLoop, 1, songName );
//				_this.playLoop( songName );		// play the regular (looping) version
				// broadcast events
				_this.broadcastMessage( "onSoundComplete" );
				_this.onSoundComplete();
			}// onSoundComplete()
			
			// If there is no intro,  immediately play the loop
			_this.music.onLoad = function(success)
			{
				if(!success)
					_this.music.onSoundComplete();
					
				// broadcast events
				if(success)
					_this.broadcastMessage( "onLoad" );
				_this.onLoad(success);
			}// songLoaded()
			
			_this.music.stop();
			_this.songName = songName;
			_this.isPlaying = false;
			if(_this._songVolume==0){
				_this.songVolume = 100;
			}
			if(skipIntro)
			{// if:  skip intro
				_this.playLoop( songName );
			}// if:  skip intro
			else
			{// if:  use intro
				var nameLength = songName.lastIndexOf(".");
				var introName = songName.substr(0, nameLength) + "_intro" + ".mp3";		// songName.mp3  ->  songName_intro.mp3
				_this.music.loadSound( introName, true );
			}// if:  use intro
		}// if: a new song is specified
		
		if( _this.isPlaying == false )
		{
			_this.music.start();
			_this.applyVolume();
			_this.isPlaying = true;
		}// if:  music is not playing
	}// play()
	_this.play = _this.playSong;
	
	
	
	_this.playLoop = function( songName )
	{
		if(_this.songName != songName)
		{
			// Looping method
			_this.music.onSoundComplete = function()
			{
				_this.music.start();
				// broadcast events
				_this.broadcastMessage( "onSoundComplete" );
				_this.onSoundComplete();
			}// onSoundComplete()
			
			// Remove the no-intro detection
			_this.music.onLoad = function(){}
			
			_this.music.loadSound( songName, true );
			_this.songName = songName;
			_this.isPlaying = false;
			
			// broadcast events
			if(success)
				_this.broadcastMessage( "onLoad" );
			_this.onLoad(success);
		}// if: a new song is specified
		
		if( _this.isPlaying == false )
		{
			//_this.music.stop();		// might be redundant
			_this.music.start();
			_this.applyVolume();
			_this.isPlaying = true;
		}// if:  music is not playing
	}// playLoop()
	
	
	
	/*
	// Alternative looping method
	_this.checkLoop = function()
	{
		var current = _this.music.position;
		var end = _this.music.duration;
		if( current >= end-0 )
		{
			//_this.music.stop();
			_this.music.start();
		}
	}// checkLoop()
	_this.checkLoopInterval = setInterval( _this.checkLoop , 1 );
	_this.onUnload = function()
	{
		clearInterval( _this.checkLoopInterval );
	}// onUnload()
	*/
	
	
	
	_this.stopMusic = function()
	{
		// remove the fade tween if it exists
		_this.fade.stop();
		delete _this.fade;
		delete _this.fadeVol;
		// stop the music
		_this.music.stop();
		_this.isPlaying = false;
		_this.songName = "";
		_this.broadcastMessage( "onStop" );
	}// stopMusic()
	
	
	
	_this.stop = _this.stopMusic;		// compatible with my simpler music system
	
	
	
	// getVolume()
	_this.getVolume = function()
	{
		return _this._volume *100;
	}// volume		(get)
	// setVolume()
	_this.setVolume = function( newVolume )
	{
		_this._volume = newVolume / 100;
		_this.applyVolume();
	}// volume		(set)
	_this.addProperty( "volume", _this.getVolume, _this.setVolume );
	
	
	
	_this.getSongVolume = function()
	{
		return _this._songVolume *100;		// song volume  (global volume factored out);
	}// volume		(get)
	_this.setSongVolume = function( newVolume )
	{
		_this._songVolume = newVolume / 100;
		_this.applyVolume();
	}// volume		(set)
	_this.addProperty( "songVolume", _this.getSongVolume, _this.setSongVolume );
	
	
	
	_this.fadeTo = function( endVolume, seconds )
	{
		// tween volume from current to target
		var startVolume = _this._songVolume *100;
		delete _this.fade;		// cancel previous fade
		_this.isFading = true;
		_this.fadeVol = startVolume;
		_this.fade = new mx.transitions.Tween( _this, "fadeVol", null, startVolume, endVolume, seconds, true);
		
		// onChange
		_this.fade.onMotionChanged = function()
		{
			_this.setSongVolume( this.position );
		}// onMotionChanged()
		
		// onDone
		_this.fade.onMotionFinished = function()
		{
			_this.fade.stop();
			delete _this.fade;
			delete _this.fadeVol;
			if(_this._songVolume == 0)
				_this.stopMusic();
			
			// call events
			_this.broadcastMessage( "onFadeComplete" );
			_this.onFadeComplete();
			_this.isFading = false;
		}// onMotionFinished()
		
		if(!_this.isPlaying)
			_this.fade.onMotionFinished();
	}// fadeTo()
	
	
	
	// set volume
	_this.applyVolume = function()
	{
		_this.music.setVolume( 100 *_this._volume *_this._songVolume );
	}// applyVolume()
	
	
	
	// pass Sound events
	_this.passSoundEvents = function()
	{
		_this.music.onID3 = function()
		{
			_this.broadcastMessage( "onID3" );
			_this.onID3();
		}
	}// passSoundEvents()
	
	
	
	
	
	
	// SETUP
	AsBroadcaster.initialize( _this );
	// pass sound events		(allows addListener(), which is not available in normal Sound objects)
	_this.passSoundEvents();
	
	return _this;
}// makeStreamingMusic()