- AudioPlayer interface extends MediaPlayer.

- Mp3AudioPlayer implements AudioPlayer.


git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@706 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
Ray Greenwell
2008-11-15 02:21:51 +00:00
parent 3ce7fc7f6a
commit 2b81e25445
3 changed files with 227 additions and 2 deletions
@@ -0,0 +1,13 @@
//
// $Id$
package com.threerings.flash.media {
/**
* Implemented by audio-playing backends.
*/
public interface AudioPlayer extends MediaPlayer
{
// surely we'll think of something unique to audio. :)
}
}
@@ -282,9 +282,7 @@ public class FlvVideoPlayer extends EventDispatcher
protected function updateState (newState :int) :void
{
const oldState :int = _state;
_state = newState;
dispatchEvent(new ValueEvent(MediaPlayerCodes.STATE, newState));
if (_state == MediaPlayerCodes.STATE_PLAYING) {
_positionChecker.start();
@@ -295,6 +293,8 @@ public class FlvVideoPlayer extends EventDispatcher
handlePositionCheck(null);
}
}
dispatchEvent(new ValueEvent(MediaPlayerCodes.STATE, newState));
}
protected const log :Log = Log.getLog(this);
@@ -0,0 +1,212 @@
//
// $Id: SoundPlayer.as 10500 2008-08-07 19:14:38Z mdb $
package com.threerings.flash.media {
import flash.errors.IOError;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.net.URLRequest;
import flash.utils.Timer;
import com.threerings.util.Log;
import com.threerings.util.ValueEvent;
public class Mp3AudioPlayer extends EventDispatcher
implements AudioPlayer
{
public function Mp3AudioPlayer (loop :Boolean = false)
{
trace(".............. v3");
_loop = loop;
_positionChecker = new Timer(25);
_positionChecker.addEventListener(TimerEvent.TIMER, handlePositionCheck);
}
/**
* Load and immediately start playing some audio!
*/
public function load (url :String) :void
{
_isComplete = false;
_lastPosition = 0;
_sound = new Sound();
_sound.addEventListener(Event.ID3, handleId3); // TODO
_sound.addEventListener(IOErrorEvent.IO_ERROR, handleError);
_sound.addEventListener(Event.COMPLETE, handleSoundComplete);
_sound.load(new URLRequest(url));
play();
}
// from AudioPlayer
public function getState () :int
{
return _state;
}
// from AudioPlayer
public function play () :void
{
play0();
updateState(
(_chan != null) ? MediaPlayerCodes.STATE_PLAYING : MediaPlayerCodes.STATE_PAUSED);
}
// from AudioPlayer
public function pause () :void
{
handlePositionCheck(null); // update _lastPosition and dispatch an event
pause0();
updateState(MediaPlayerCodes.STATE_PAUSED);
}
// from AudioPlayer
public function getDuration () :Number
{
if (_sound == null) {
return NaN;
}
return _sound.length / 1000;
}
// from AudioPlayer
public function getPosition () :Number
{
if (_chan == null) {
return _lastPosition;
}
return _chan.position / 1000;
}
// from AudioPlayer
public function seek (position :Number) :void
{
_lastPosition = position;
if (_state == MediaPlayerCodes.STATE_PLAYING) {
pause0();
play0();
} else {
handlePositionCheck(null);
}
}
// from AudioPlayer
public function setVolume (volume :Number) :void
{
_volume = Math.max(0, Math.min(1, volume));
if (_chan != null) {
_chan.soundTransform = new SoundTransform(_volume);
}
}
// from AudioPlayer
public function getVolume () :Number
{
return _volume;
}
// from AudioPlayer
public function unload () :void
{
if (_sound != null) {
try {
_sound.close();
} catch (err :IOError) {
// ignore
}
}
pause0();
_positionChecker.reset();
_lastPosition = NaN;
}
protected function play0 () :void
{
pause0();
_chan = _sound.play(_lastPosition * 1000, _loop ? int.MAX_VALUE : 0,
new SoundTransform(_volume));
if (_chan == null) {
Log.getLog(this).warning("All sound channels are in use; " +
"unable to play sound.");
}
}
protected function pause0 () :void
{
if (_chan != null) {
_chan.stop();
_chan = null;
}
}
protected function handlePositionCheck (event :TimerEvent) :void
{
if (!_isComplete) {
dispatchEvent(new ValueEvent(MediaPlayerCodes.DURATION, getDuration()));
}
_lastPosition = getPosition();
dispatchEvent(new ValueEvent(MediaPlayerCodes.POSITION, _lastPosition));
}
protected function updateState (newState :int) :void
{
_state = newState;
if (_state == MediaPlayerCodes.STATE_PLAYING) {
_positionChecker.start();
} else {
_positionChecker.reset();
// pause() ends up checking the position one last time before dispatching state..
}
dispatchEvent(new ValueEvent(MediaPlayerCodes.STATE, newState));
}
protected function handleId3 (event :Event) :void
{
trace("got ID3: Duration is now : " + _sound.length);
}
/**
*/
protected function handleSoundComplete (event :Event) :void
{
handlePositionCheck(null); // also updates duration
_isComplete = true;
}
protected function handleError (event :IOErrorEvent) :void
{
dispatchEvent(new ValueEvent(MediaPlayerCodes.ERROR, event.text));
}
protected var _sound :Sound;
protected var _chan :SoundChannel;
protected var _loop :Boolean;
protected var _state :int = MediaPlayerCodes.STATE_UNREADY;
protected var _volume :Number = 1;
protected var _isComplete :Boolean;
protected var _lastPosition :Number = NaN;
protected var _positionChecker :Timer;
}
}