2020-10-20 00:58:15 +02:00

682 lines
19 KiB
ActionScript
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
*/
package com.yahoo.astra.fl.controls.mediaPlayerClasses
{
import flash.events.*;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.media.SoundLoaderContext;
import com.yahoo.astra.fl.controls.mediaPlayerClasses.IMediaClip;
import flash.net.URLRequest;
import fl.core.UIComponent;
import com.yahoo.astra.fl.events.MediaEvent;
import flash.utils.Timer;
import flash.display.DisplayObjectContainer;
//--------------------------------------
// Events
//--------------------------------------
/**
* Dispatched when on an interval while the clip is playing.
*
* @eventType com.yahoo.astra.fl.events.MediaEvent.MEDIA_POSITION
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
[Event(name="mediaPosition", type="com.yahoo.astra.fl.events.MediaEvent")]
/**
* Dispatched when the clip is paused or played.
*
* @eventType com.yahoo.astra.fl.events.MediaEvent.MEDIA_PLAY_PAUSE
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
[Event(name="mediaPlayPause", type="com.yahoo.astra.fl.events.MediaEvent")]
/**
* Dispatched when the volume level is changed.
*
* @eventType com.yahoo.astra.fl.events.MediaEvent.VOLUME_CHANGE
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
[Event(name="volumeChange", type="com.yahoo.astra.fl.events.MediaEvent")]
/**
* Dispatched when the id3 event is received.
*
* @eventType com.yahoo.astra.fl.events.MediaEvent.INFO_CHANGE
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
[Event(name="infoChange", type="com.yahoo.astra.fl.events.MediaEvent")]
/**
* Dispatched when a clip has completely loaded.
*
* @eventType com.yahoo.astra.fl.events.MediaEvent.MEDIA_LOADED
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
[Event(name="mediaLoaded", type="com.yahoo.astra.fl.events.MediaEvent")]
/**
* Dispatched when a clip reaches its end point.
*
* @eventType com.yahoo.astra.fl.events.MediaEvent.MEDIA_ENDED
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
[Event(name="mediaEnded", type="com.yahoo.astra.fl.events.MediaEvent")]
//--------------------------------------
// Class description
//--------------------------------------
/**
* The AudioClip class extends the EventDispatcher class and wraps the
* Sound, SoundChannel, SoundLoaderContext and SoundTransform classes.
*
* @see flash.media.Sound
* @see flash.media.SoundChannel
* @see flash.media.SoundTransform
* @see flash.media.SoundLoaderContext
* @see flash.events.EventDispatcher
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public class AudioClip extends EventDispatcher implements IMediaClip
{
//--------------------------------------
// Constructor
//--------------------------------------
/**
* Constructor
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function AudioClip():void
{
super();
_soundTransform = new SoundTransform(_volume, _panning);
_positionTimer = new Timer(50);
_positionTimer.addEventListener(TimerEvent.TIMER, positionUpdateHandler);
}
//--------------------------------------
// Properties
//--------------------------------------
/**
* @private (protected)
*/
protected var _mediaAvailable:Boolean = false;
/**
* @private (protected)
*/
protected var _length:Number = 0;
/**
* @private (protected)
*/
protected var _artist:String;
/**
* @private (protected)
*/
protected var _title:String;
/**
* @private (protected)
* The Sound object
*/
protected var _clip:Sound;
/**
* @private (protected)
* The SoundChannel
*/
protected var _channel:SoundChannel;
/**
* @private (protected)
* Timer used to dispatch "mediaPosition" events.
*/
protected var _positionTimer:Timer;
/**
* @private (protected)
* place holder for position.
*/
protected var _position:Number;
/**
* @private (protected)
* indicates whether the state of the clip is paused
*/
protected var _playing:Boolean = true;
/**
* @private (protected)
* indicates whether the sound is muted
*/
protected var _mute:Boolean = false;
/**
* @private (protected)
*/
protected var _volume:Number = 1;
/**
* @private (protected)
*/
protected var _panning:Number = 0;
/**
* @private (protected)
*/
protected var _soundTransform:SoundTransform;
/**
* @private (protected)
*/
protected var _autoStart:Boolean = false;
/**
* Gets the url to be used for an AudioClip (read-only)
*/
public function get url():String
{
return _clip.url;
}
/**
* Gets or sets the position of the playhead
*/
public function get position():Number
{
return _channel.position;
}
/**
* @private (setter)
* sets the position for a clip (cues and rewinds)
* if the clip is paused, the _position property is set to the received value
* otherwise the clip is played from that position
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function set position(value:Number):void
{
if(_mediaAvailable)
{
_position = Math.min(value, _length);
_channel.removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
_channel = _clip.play(_position);
_channel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
_channel.soundTransform = _soundTransform;
if(!_playing) pause();
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_POSITION, false, false, _playing?Number(_channel.position.toFixed(2)):_position, _length, _soundTransform.volume, _mute));
}
}
/**
* Length of the Audio (read-only)
*/
public function get length():Number
{
return _length;
}
/**
* Boolean indicating if the audio is playing. (read-only) us pause() and play() methods to change playing
*/
public function get playing():Boolean
{
return _playing;
}
/**
* Gets or sets the volume, ranging from 0 (silent) to 1 (full volume).
*/
public function get volume():Number
{
return _soundTransform.volume;
}
/**
* @private (setter)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function set volume(value:Number):void
{
//sets the volume property of the _soundTransform object
//sets the _soundTransform object to the _channel
//dispatches a VOLUME_CHANGE MediaEvent
_soundTransform.volume = _volume = Math.max(0, Math.min(value, 1));
_mute = false;
if(_mediaAvailable)
{
_channel.soundTransform = _soundTransform;
dispatchEvent(new MediaEvent(MediaEvent.VOLUME_CHANGE, false, false, Number(_channel.position.toFixed(2)), _length, Number(_channel.soundTransform.volume), _mute));
}
else
{
dispatchEvent(new MediaEvent(MediaEvent.VOLUME_CHANGE, false, false, _position, 0, _soundTransform.volume, _mute));
}
}
/**
* Gets or sets the mute property of the AudioClip
*/
public function get mute():Boolean
{
return _mute;
}
/**
* @private (setter)
* Sets the mute property of the audio
*/
public function set mute(value:Boolean):void
{
//sets the value of _mute
//sets the volume of the _soundTransform object to 0 if +_mute is true and to _volume if _mute is false
//sets the _soundTransform object to the _channel
//dispatches a VOLUME_CHANGE MediaEvent
_mute = value;
_soundTransform.volume = _mute?0:_volume;
if(_mediaAvailable)
{
_channel.soundTransform = _soundTransform;
dispatchEvent(new MediaEvent(MediaEvent.VOLUME_CHANGE, false, false, Number(_channel.position.toFixed(2)), _length, Number(_channel.soundTransform.volume), _mute));
}
else
{
dispatchEvent(new MediaEvent(MediaEvent.VOLUME_CHANGE, false, false, _position, 0, _soundTransform.volume, _mute));
}
}
/**
* Gets the artist for the audio clip (read-only). This information is available:
* <ul>
* <li>If the SWF is in the same domain as the sound file.</li>
* <li>If the <code>checkPolicyFile</code> property is true and there
* is a cross-domain policy file on the server from which the sound is
* loaded that permits the domain of the loading SWF file. </li>
* </ul>
*
*/
public function get artist():String
{
return _artist;
}
/**
* Gets the title of the clip (read-only). This information is available:
* <ul>
* <li>If the SWF is in the same domain as the sound file.</li>
* <li>If the <code>checkPolicyFile</code> property is true and there is a cross-domain policy file on the
* server from which the sound is loaded that permits the domain of the loading SWF file. </li>
* </ul>
*
*/
public function get title():String
{
return _title;
}
/**
* Gets or sets the autoStart property of an AudioClip
*/
public function get autoStart():Boolean
{
return _autoStart;
}
/**
* @private (setter)
*/
public function set autoStart(value:Boolean):void
{
_autoStart = value;
}
/**
* @private (protected)
*/
protected var _soundLoaderContext:SoundLoaderContext;
/**
* @private (protected)
*/
protected var _bufferTime:Number = 1000;
/**
* Gets or sets buffer time. (milliseconds)
*/
public function get bufferTime():Number
{
return _bufferTime;
}
/**
* @private (setter)
*/
public function set bufferTime(value:Number):void
{
_bufferTime = value;
}
/**
* @private (protected)
*/
protected var _checkForPolicyFile:Boolean = true;
/**
* Gets or sets checkForPolicyFile property of the SoundLoaderContext. Specifies whether Flash Player should check
* for the existence of a cross-domain policy file upon loading the object (true) or not.
*
* @see flash.media.SoundLoaderContext;
*
*/
public function get checkForPolicyFile():Boolean
{
return _checkForPolicyFile;
}
/**
* @private (setter)
*/
public function set checkForPolicyFile(value:Boolean):void
{
_checkForPolicyFile = value;
}
//--------------------------------------
// Public Methods
//--------------------------------------
/**
* Loads an audio clip
*
* @param urlValue string for the location of the clip
* @param autoStart Boolean indicating whether the clip starts playing when it loads
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function loadMedia(urlValue:String, autoStart:Boolean = true):void
{
_soundLoaderContext = new SoundLoaderContext(bufferTime, checkForPolicyFile);
_length = 0;
_playing = autoStart;
_mediaAvailable = true;
_position = 0;
var request:URLRequest = new URLRequest(urlValue);
if(_clip != null)
{
removeClipListeners(_clip);
_positionTimer.reset();
}
if(_channel != null)
{
if(_channel.hasEventListener(Event.SOUND_COMPLETE)) _channel.removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
_channel.stop();
}
_clip = new Sound();
addClipListeners(_clip);
_clip.load(request, _soundLoaderContext);
_channel = _clip.play();
_channel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
_channel.soundTransform = _soundTransform;
_positionTimer.start();
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_POSITION, false, false, _position, _length, _channel.soundTransform.volume, _mute));
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_PLAY_PAUSE, false, false, _position, _length, _channel.soundTransform.volume, _mute));
dispatchEvent(new MediaEvent(MediaEvent.VOLUME_CHANGE, false, false, _position, _length, _channel.soundTransform.volume, _mute));
if(!autoStart)
{
pause();
_position = 0;
}
//dispatchEvent(new MediaEvent(MediaEvent.MEDIA_READY));
}
/**
* Pauses the audio
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function pause():void
{
//sets pause to true
//dispatches a MEDIA_PLAY_PAUSE event
//calls the stop function
if(_mediaAvailable)
{
_playing = false;
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_PLAY_PAUSE, false, false, Number(_channel.position.toFixed(2)), _length, Number(_channel.soundTransform.volume), _mute));
stop();
_positionTimer.stop();
}
}
/**
* Plays the audio
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function play():void
{
//sets _playing to true
//dispatches a MEDIA_PLAY_PAUSE event
//set the SoundChannel object to the play method of the Sound object using the _position value
if(_mediaAvailable)
{
_positionTimer.start();
_playing = true;
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_PLAY_PAUSE, false, false, Number(_channel.position.toFixed(2)), _length, Number(_channel.soundTransform.volume), _mute));
_channel.removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
_channel = _clip.play(_position);
_channel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
_channel.soundTransform = _soundTransform;
}
}
/**
* Stops the audio
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function stop():void
{
//sets _position to the current position of the sound object
//calls the stop method on the SoundChannel object
//used by pause method, to stop the playback when audio is in a paused state
//used by the controller to stop the video while the MediaScrubber seeks
if(_mediaAvailable)
{
_position = Number(_channel.position.toFixed(2));
_channel.stop();
}
}
//--------------------------------------
// Protected Methods
//--------------------------------------
/**
* @private (protected)
* Dispatches a MediaEvent.MEDIA_POSITION event with the _positionTimer event
* @param event The TimerEvent
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function positionUpdateHandler(event:TimerEvent):void
{
//if paused, update with the _position value. if not, update with the actual position of the sound channel
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_POSITION, false, false, _playing?Number(_channel.position.toFixed(2)):_position, _length, Number(_channel.soundTransform.volume), _mute));
}
/**
* @private (protected)
* Adds event listeners to a sound object when set clip is called.
* @param soundDispatcher
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function addClipListeners(soundDispatcher:Sound):void
{
soundDispatcher.addEventListener(Event.COMPLETE, completeHandler);
soundDispatcher.addEventListener(Event.ID3, id3Handler);
soundDispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
soundDispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
/**
* @private (protected)
* Removes listeners from the sound object before a new clip is set
* @param soundDispatcher
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function removeClipListeners(soundDispatcher:Sound):void
{
soundDispatcher.removeEventListener(Event.COMPLETE, completeHandler);
soundDispatcher.removeEventListener(Event.ID3, id3Handler);
soundDispatcher.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
soundDispatcher.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
/**
* @private (protected)
* Resets a clip to the beginning and dispatches MediaEvent.MEDIA_POSITION and MediaEvent.MEDIA_ENDED events.
* @param event soundComplete event
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function soundCompleteHandler(event:Event):void
{
pause();
position = 0;
//does not always fire. may need to add a catch in the timer to force an end
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_POSITION, false, false, _playing?Number(_channel.position.toFixed(2)):_position, _length, _soundTransform.volume, _mute));
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_ENDED, false, false, _playing?Number(_channel.position.toFixed(2)):_position, _length, _soundTransform.volume, _mute));
}
/**
* @private (protected)
* Dispatches a MediaEvent.MEDIA_LOADED event when the media has loaded
* @param event Event.COMPLETE event
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function completeHandler(event:Event):void
{
_length = _clip.length;
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_LOADED));
}
/**
* @private (protected)
* Dispatches a MediaEvent.INFO_CHANGE event when the ID3 event is received from the Sound object
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function id3Handler(event:Event):void
{
try
{
_title = _clip.id3.songName as String;
_artist = _clip.id3.artist as String;
}
catch(e:SecurityError)
{
_artist = "Artist Unavailable";
_title = "Title Unavailable";
}
dispatchEvent(new MediaEvent(MediaEvent.INFO_CHANGE, false, false));
}
/**
* @private
* dispatches the ProgressEvent to registered listeners
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function progressHandler(event:ProgressEvent):void
{
_length = _clip.length * (event.bytesTotal/event.bytesLoaded);
dispatchEvent(event);
}
/**
* @private
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function ioErrorHandler(event:IOErrorEvent):void
{
//need to reset everything here.
_mediaAvailable = false;
_positionTimer.stop();
_length = 0;
_artist = "Artist Unavailable";
_title = "Title Unavailable";
dispatchEvent(new MediaEvent(MediaEvent.INFO_CHANGE, false, false));
}
public function kill():void
{
if(_mediaAvailable)
{
pause();
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_POSITION, false, false, _playing?Number(_channel.position.toFixed(2)):_position, _length, _soundTransform.volume, _mute));
dispatchEvent(new MediaEvent(MediaEvent.MEDIA_ENDED, false, false, _playing?Number(_channel.position.toFixed(2)):_position, _length, _soundTransform.volume, _mute));
}
}
}
}