X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F07_audio%2F00_XAudio.js;h=4664aa0b2cc0f9e6f1e700c0b1f217f7376f7950;hb=4e4ab3be10850546063d4a4b93250ed142bb8cd2;hp=49d1ee13fe313f332283d521b93156e50d9bca3b;hpb=3c07e12e13272820cedf983e0d9fe46e5f0a4bd9;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/07_audio/00_XAudio.js b/0.6.x/js/07_audio/00_XAudio.js index 49d1ee1..4664aa0 100644 --- a/0.6.x/js/07_audio/00_XAudio.js +++ b/0.6.x/js/07_audio/00_XAudio.js @@ -25,29 +25,36 @@ X_TEMP.onSystemReady.push( }); /** - *

複数のバックエンドから、与えられた音声を再生可能なものを見つけ、音声を再生します。 + *

複数のオーディオ・バックエンドから、与えられた音声を再生可能なものを見つけ、音声を再生します。 *

HTMLAudio の動作・機能がブラウザ毎にバラバラなのに業を煮やし、メソッドやイベントは独自に定義しています。 *

バックエンドの種類

- *

HTMLAudio, WebAudio, Silverlight + *

HTMLAudio, WebAudio, Silverlight, WMP *

イベント

*
- *
X.Event.BACKEND_READY
音声(src リスト)を再生可能なバックエンドが見つかった。 - *
X.Event.BACKEND_NONE
音声を再生可能なバックエンドが見つからなかった。 - *
X.Event.READY
再生可能、実際の状態は canplay から loadeddata まで様々、、、 - *
X.Event.ERROR
+ *

ソースリストに与える url 文字列

+ *

ハッシュフラグメント以下にデータを書くことで、各オーディオバックエンドが再生可能性の判断にあたって参考にするデータを渡すことができます。 + *

+ *
CBR=1
audio が固定ビットレートであることを示す。Android 用 Opera12- は可変ビットレートの mp3 を正しくシークできない。 + * [ 'snd.mp3', 'snd.mp3#CBR=1' ] と指定すると、Android 用 Opera12- では CBR な mp3 が、他の環境ではよりファイルサイズの小さい VBR な mp3 が使用される。(未実装) + *
ext=mp3
パスに拡張子が含まれない場合、または上書き指定したい場合に指定する * * @alias X.Audio * @class 各種オーディオ機能をラップしインターフェイスを共通化する。 @@ -56,12 +63,11 @@ X_TEMP.onSystemReady.push( * @param {array|string} sourceList * @param {object=} opt_option * @example // - * var audio = X.Audio( [ 'etc/special.mp3', 'etc/special.ogg', 'etc/special.wav' ] ) - .listenOnce( X.Event.READY, onReady ); + * var audio = X.Audio( [ 'etc/special.mp3', 'etc/special.ogg', 'etc/special.wav' ] ).listenOnce( X.Event.READY, onReady ); */ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( 'X.Audio', - X_Class.POOL_OBJECT, + X_Class.NONE, { /** * 音声の url。X.Event.BACKEND_READY で設定される。 @@ -69,13 +75,14 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( * @type {string} */ 'source' : '', + /** * 音声再生バックエンドの名前。X.Event.BACKEND_READY で設定される。 * @alias Audio.prototype.backendName * @type {string} */ 'backendName' : '', - + 'Constructor' : function( sourceList, opt_option ){ X_Audio_startDetectionBackend( X_Audio_BACKENDS[ 0 ], this, @@ -88,6 +95,12 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( /** * 再生。開始位置・終了位置、ループの有無、ループ以降の開始位置、ループ以降の終了位置 * @alias Audio.prototype.play + * @param {number=} startTime 開始時間を ms で + * @param {number=} endTime 終了時間を ms で + * @param {boolean=} loop endTimeに達した際に曲をループさせるか + * @param {number=} loopStartTime ループ以後の開始時間を ms で + * @param {number=} loopEndTime ループ以後の終了時間を ms で + * @return {Audio} メソッドチェーン */ 'play' : function( startTime, endTime, loop, loopStartTime, loopEndTime ){ var pair = X_Pair_get( this ); @@ -95,8 +108,10 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( return this; }, /** - * シーク + * シーク、再生中で無い場合は次回再生開始位置の指定のみ * @alias Audio.prototype.seek + * @param {number} seekTime シーク位置を ms で + * @return {Audio} メソッドチェーン */ 'seek' : function( seekTime ){ var pair = X_Pair_get( this ); @@ -106,6 +121,7 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( /** * ポーズ * @alias Audio.prototype.pause + * @return {Audio} メソッドチェーン */ 'pause' : function(){ var pair = X_Pair_get( this ); @@ -115,6 +131,21 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( /** * 状態の getter と setter * @alias Audio.prototype.state + * @param {object=} obj setter の場合、上書きする値を格納したobject + * @return {Audio|object} + * @example +audio.setState( + { + 'startTime' : 0, + 'endTime' : 80000, + 'loopStartTime' : 120000, + 'loopEndTime' : 200000, + 'currentTime' : 0, + 'loop' : true, + 'looded' : false, + 'volume' : 1, + 'autoplay' : true +}); */ 'state' : function( obj ){ var pair = X_Pair_get( this ); @@ -128,18 +159,22 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( 'currentTime' : -1, 'loop' : false, 'looded' : false, - 'error' : false, + 'error' : 0, + 'autoplay' : false, 'playing' : false, - 'source' : this[ 'source' ] || '', - 'duration' : 0 + 'source' : this[ 'source' ], + 'duration' : 0, + 'volume' : 0.5 }; }; pair && pair.setState( obj ); return this; }, /** - * ループの getter と setter + * ループの setter * @alias Audio.prototype.loop + * @param {boolean} v + * @return {Audio} */ 'loop' : function( v ){ var pair = X_Pair_get( this ); @@ -147,8 +182,10 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( return this; }, /** - * ボリュームの getter と setter 実装不十分! + * ボリュームの setter 実装不十分! * @alias Audio.prototype.volume + * @param {number} v 0~1 + * @return {Audio} */ 'volume' : function( v ){ var pair = X_Pair_get( this ); @@ -156,8 +193,10 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( return this; }, /** - * 再生位置。 + * 再生位置のsetter。 * @alias Audio.prototype.currentTime + * @param {number} v msで + * @return {Audio} */ 'currentTime' : function( v ){ var pair = X_Pair_get( this ); @@ -167,6 +206,7 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( /** * 再生中か? * @alias Audio.prototype.isPlaying + * @return {boolean} */ 'isPlaying' : function(){ var pair = X_Pair_get( this ); @@ -177,7 +217,7 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( ); function X_Audio_handleEvent( e ){ - var backend, pair; + var backend, src, pair; switch( e.type ){ case X_EVENT_BACKEND_READY : @@ -218,8 +258,9 @@ function X_Audio_handleEvent( e ){ */ function X_Audio_startDetectionBackend( backend, xaudio, sourceList, option ){ - var source = sourceList[ 0 ] || '', - ext = X_URL_getEXT( source ), + var source = sourceList[ 0 ] || '', + hash = X_URL_paramToObj( X_URL_getHash( source ) ), + ext = hash[ 'ext' ] || X_URL_getEXT( source ), sup; if( source && backend ){ @@ -227,29 +268,36 @@ function X_Audio_startDetectionBackend( backend, xaudio, sourceList, option ){ sup[ 5 ] = sup; xaudio[ 'listenOnce' ]( X_EVENT_COMPLETE, backend, X_Audio_onEndedDetection, sup ); - backend.detect( xaudio, source, ext ); + backend.detect( xaudio, ext, hash ); } else { xaudio[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE ); }; }; function X_Audio_onEndedDetection( e, xaudio, sourceList, option, source, ext, sup ){ - var i = X_Audio_BACKENDS.indexOf( this ), backend; + var i = X_Audio_BACKENDS.indexOf( this ), _e, hash, backend; if( e.canPlay ){ - xaudio[ 'asyncDispatch' ]( { + _e = { type : X_EVENT_BACKEND_READY, 'option' : option, 'source' : source, - 'backendName' : this[ 'backendName' ], + 'backendName' : this.backendName, 'backendID' : i - } ); + }; + // WebAudio + if( this.backendID === 1 ) _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch; + // HTMLAudio + if( this.backendID === 2 ) _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch; + + xaudio[ 'asyncDispatch' ]( _e ); } else { - console.log( 'No ' + source + ' ' + this[ 'backendName' ] ); + console.log( 'No ' + source + ' ' + this.backendName ); if( sup[ 3 ] = source = sourceList[ sourceList.indexOf( source ) + 1 ] ){ - sup[ 4 ] = ext = X_URL_getEXT( source ); + hash = X_URL_paramToObj( X_URL_getHash( source ) ); + sup[ 4 ] = ext = hash[ 'ext' ] || X_URL_getEXT( source ); xaudio[ 'listenOnce' ]( X_EVENT_COMPLETE, this, X_Audio_onEndedDetection, sup ); - this.detect( xaudio, source, ext ); + this.detect( xaudio, ext, hash ); } else if( backend = X_Audio_BACKENDS[ i + 1 ] ){ X_Audio_startDetectionBackend( backend, xaudio, sourceList, option ); @@ -345,6 +393,7 @@ var X_AudioBase = X_EventDispatcher[ 'inherits' ]( 'volume' : this.gain, 'playing' : this.playing, 'duration' : this.duration, + 'autoplay' : this.autoplay, 'currentTime' : this.playing ? this.getActualCurrentTime() : this.seekTime, 'error' : this.getActualError ? this.getActualError() : this.error