X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F07_audio%2F00_XAudio.js;h=e923109aa33bf4b677c3e15da9c22c02d7233b9c;hb=2956150a7c2798e60639b36d69b0c13f6b20a62a;hp=acae4369fc7ae69a8b9c76763669835473df5a81;hpb=adbf9e9a2c7d8e6857774f774742a7ff6fb50600;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 acae436..e923109 100644 --- a/0.6.x/js/07_audio/00_XAudio.js +++ b/0.6.x/js/07_audio/00_XAudio.js @@ -10,15 +10,7 @@ QuickTime : 8, */ -var X_Audio_BACKENDS = [], // Array. - X_Audio_WRAPPER_LIST = []; // Array. - -function X_Audio_getAudioWrapper( proxy ){ - var i = X_Audio_WRAPPER_LIST.length; - for( ; i; ){ - if( X_Audio_WRAPPER_LIST[ --i ].proxy === proxy ) return X_Audio_WRAPPER_LIST[ i ]; - }; -}; +var X_Audio_BACKENDS = []; // Array. /* * X_EVENT_BACKEND_READY @@ -40,13 +32,13 @@ function X_Audio_getAudioWrapper( proxy ){ * X_EVENT_MEDIA_SEEKING シーク中に音声が待機状態に。間もなく X_EVENT_MEDIA_PLAYING に移行。 */ +// TODO この内容は、AudioBackend の Abstract クラスにする。AudioSprite は Audio ではなく AudioBackend をマネージする X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( 'X.Audio', X_Class.POOL_OBJECT, { 'source' : '', 'backendName' : '', - _backend : -1, 'Constructor' : function( sourceList, opt_option ){ X_Audio_startDetectionBackend( @@ -57,41 +49,27 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( }, 'play' : function( startTime, endTime, loop, loopStartTime, loopEndTime ){ - var state, duration; - if( 0 <= startTime ){ - this[ 'state' ]( { - currentTime : startTime, - startTime : startTime, - endTime : endTime, - loop : loop, - loopStartTime : loopStartTime, - loopEndTime : loopEndTime - } ); - }; - this._backend !== -1 && X_Audio_getAudioWrapper( this ).play(); + var pair = X_Pair_get( this ); + pair && pair.play( startTime, endTime, loop, loopStartTime, loopEndTime ); return this; }, 'seek' : function( seekTime ){ - var state = this[ 'state' ](), - end = X_AudioWrapper_getEndTime( X_Audio_getAudioWrapper( this ) ); - if( seekTime < end ){ - this[ 'state' ]( { currentTime : seekTime } ); - }; + var pair = X_Pair_get( this ); + pair && pair.seek( seekTime ); return this; }, 'pause' : function(){ - this[ 'state' ]().playing && X_Audio_getAudioWrapper( this ).pause(); + var pair = X_Pair_get( this ); + pair && pair.pause(); return this; }, 'state' : function( obj ){ - var backend = this._backend !== -1 && X_Audio_getAudioWrapper( this ); - + var pair = X_Pair_get( this ); if( obj === undefined ){ - return backend ? - backend.state() : + return pair ? pair.getState() : { 'startTime' : -1, 'endTime' : -1, @@ -102,58 +80,51 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( 'looded' : false, 'error' : false, 'playing' : false, - 'source' : this[ 'source' ] || '', 'duration' : 0 }; }; - backend && backend.state( obj ); + pair && pair.setState( obj ); return this; }, 'loop' : function( v ){ - var backend = this._backend !== -1 && X_Audio_getAudioWrapper( this ); - if( v === undefined ){ - return backend && backend.state().loop; - }; - backend && backend.state( { loop : v } ); + var pair = X_Pair_get( this ); + pair && pair.loop( v ); return this; }, 'volume' : function( v ){ - var backend = this._backend !== -1 && X_Audio_getAudioWrapper( this ); - if( v === undefined ){ - return backend && backend.state().volume; - }; - backend && backend.state( { volume : v } ); + var pair = X_Pair_get( this ); + pair && pair.volume( v ); return this; }, 'currentTime' : function( v ){ - var backend = this._backend !== -1 && X_Audio_getAudioWrapper( this ); - if( v === undefined ){ - return backend && backend.state().currentTime; - }; - backend && backend.state( { currentTime : v } ); + var pair = X_Pair_get( this ); + pair && pair.currentTime( v ); return this; }, 'isPlaying' : function(){ - return this._backend !== -1 && X_Audio_getAudioWrapper( this ).state().playing; + var pair = X_Pair_get( this ); + return pair && pair.playing; } } ); function X_Audio_handleEvent( e ){ + var backend; + switch( e.type ){ case X_EVENT_BACKEND_READY : + backend = X_Audio_BACKENDS[ e[ 'backendID' ] ]; + this[ 'unlisten' ]( X_EVENT_BACKEND_NONE, X_Audio_handleEvent ); - this[ 'source' ] = e.source; - this[ 'backendName' ] = X_Audio_BACKENDS[ this._backend ].backendName; - X_Audio_WRAPPER_LIST.push( - new X_Audio_BACKENDS[ this._backend ] - .klass( this, e.source, e.option ) ); + this[ 'source' ] = e[ 'source' ]; + this[ 'backendName' ] = backend.backendName; + X_Pair_create( this, backend.klass( this, e[ 'source' ], e[ 'option' ] ) ); break; case X_EVENT_BACKEND_NONE : @@ -161,7 +132,9 @@ function X_Audio_handleEvent( e ){ break; case X_EVENT_KILL_INSTANCE : - this._backend !== -1 && X_Audio_getAudioWrapper( this ).close(); + backend = X_Pair_get( this ); + backend && backend[ 'kill' ](); + X_Pair_release( this, backend ); break; }; }; @@ -171,126 +144,256 @@ function X_Audio_handleEvent( e ){ * TODO preplayerror play してみたら error が出た、backend の変更。 */ -function X_Audio_startDetectionBackend( backend, proxy, sourceList, option ){ +function X_Audio_startDetectionBackend( backend, xaudio, sourceList, option ){ var source = sourceList[ 0 ] || '', ext = X_URL_getEXT( source ), sup; if( source && backend ){ - sup = [ proxy, sourceList, option, source, ext ]; + sup = [ xaudio, sourceList, option, source, ext ]; sup[ 5 ] = sup; - proxy[ 'listenOnce' ]( X_EVENT_COMPLETE, backend, X_Audio_onEndedDetection, sup ); - backend.detect( proxy, source, ext ); + xaudio[ 'listenOnce' ]( X_EVENT_COMPLETE, backend, X_Audio_onEndedDetection, sup ); + backend.detect( xaudio, source, ext ); } else { - proxy[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE ); + xaudio[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE ); }; }; -function X_Audio_onEndedDetection( e, proxy, sourceList, option, source, ext, sup ){ +function X_Audio_onEndedDetection( e, xaudio, sourceList, option, source, ext, sup ){ var i = X_Audio_BACKENDS.indexOf( this ), backend; if( e.canPlay ){ - proxy._backend = i; - proxy[ 'asyncDispatch' ]( { + xaudio._backend = i; + xaudio[ 'asyncDispatch' ]( { type : X_EVENT_BACKEND_READY, 'option' : option, 'source' : source, - 'backendName' : this[ 'backendName' ] + 'backendName' : this[ 'backendName' ], + 'backendID' : i } ); } else { console.log( 'No ' + source + ' ' + this[ 'backendName' ] ); if( sup[ 3 ] = source = sourceList[ sourceList.indexOf( source ) + 1 ] ){ sup[ 4 ] = ext = X_URL_getEXT( source ); - proxy[ 'listenOnce' ]( X_EVENT_COMPLETE, this, X_Audio_onEndedDetection, sup ); - this.detect( proxy, source, ext ); + xaudio[ 'listenOnce' ]( X_EVENT_COMPLETE, this, X_Audio_onEndedDetection, sup ); + this.detect( xaudio, source, ext ); } else if( backend = X_Audio_BACKENDS[ i + 1 ] ){ - X_Audio_startDetectionBackend( backend, proxy, sourceList, option ); + X_Audio_startDetectionBackend( backend, xaudio, sourceList, option ); } else { - proxy[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE ); + xaudio[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE ); }; }; }; -function X_AudioWrapper_updateStates( audioWrapper, obj ){ - var playing = audioWrapper.playing, - k, v, - end = 0, seek = 0, volume = 0; - - for( k in obj ){ - v = obj[ k ]; - switch( k ){ - case 'currentTime' : - v = X_AudioWrapper_timeStringToNumber( v ); - if( X_Type_isNumber( v ) ){ - if( playing ){ - if( audioWrapper.state().currentTime !== v ){ - audioWrapper.seekTime = v; - seek = 2; +var X_Audio_AbstractAudioBackend = X_EventDispatcher[ 'inherits' ]( + 'X.AbstractAudioBackend', + X_Class.ABSTRACT, + { + + url : '', + target : null, + + startTime : 0, + endTime : -1, + loopStartTime : -1, + loopEndTime : -1, + seekTime : -1, + duration : 0, + + playing : false, + error : 0, + autoLoop : false, + looped : false, + autoplay : false, + gain : 0.5, + + play : function( startTime, endTime, loop, loopStartTime, loopEndTime ){ + if( 0 <= startTime ){ + this.setState( { + currentTime : startTime, + startTime : startTime, + endTime : endTime, + loop : loop, + loopStartTime : loopStartTime, + loopEndTime : loopEndTime + } ); + }; + this.actualPlay(); + }, + + seek : function( seekTime ){ + if( seekTime < X_AudioWrapper_getEndTime( this ) ){ + this.setState( { currentTime : seekTime } ); + }; + }, + + pause : function(){ + this.playing && this.actualPause(); + }, + + loop : function( v ){ + if( v === undefined ){ + return this.autoLoop; + }; + this.setState( { loop : v } ); + }, + + volume : function( v ){ + if( v === undefined ){ + return this.gain; + }; + this.setState( { volume : v } ); + }, + + currentTime : function( v ){ + if( v === undefined ){ + return this.playing ? this.getActualCurrentTime() : this.seekTime; + }; + this.setState( { currentTime : v } ); + }, + + getState : function(){ + + return { + 'startTime' : this.startTime, + 'endTime' : this.endTime < 0 ? this.duration : this.endTime, + 'loopStartTime' : this.loopStartTime < 0 ? this.startTime : this.loopStartTime, + 'loopEndTime' : this.loopEndTime < 0 ? ( this.endTime || this.duration ) : this.loopEndTime, + 'loop' : this.autoLoop, + 'looped' : this.looped, + 'volume' : this.gain, + 'playing' : this.playing, + 'duration' : this.duration, + + 'currentTime' : this.playing ? this.getActualCurrentTime() : this.seekTime, + 'error' : this.getActualError ? this.getActualError() : this.error + }; + }, + + setState : function( obj ){ + var playing = this.playing, + k, v, + end = 0, seek = 0, volume = 0; + + for( k in obj ){ + v = obj[ k ]; + switch( k ){ + case 'currentTime' : + v = X_AudioWrapper_timeStringToNumber( v ); + if( X_Type_isNumber( v ) ){ + if( playing ){ + if( this.getActualCurrentTime() !== v ){ + seek = 2; + this.seekTime = v; + }; + } else { + this.seekTime = v; + }; + } else { + continue; }; - } else { - audioWrapper.seekTime = v; - }; - } else { - continue; - }; - break; + break; + + case 'startTime' : + v = X_AudioWrapper_timeStringToNumber( v ); + if( v || v === 0 ){ + if( this.startTime !== v ){ + this.startTime = v; + }; + } else { + delete this.startTime; + }; + break; - case 'startTime' : - case 'endTime' : - case 'loopStartTime' : - case 'loopEndTime' : - v = X_AudioWrapper_timeStringToNumber( v ); - console.log( k + ' ' + v ); - if( v || v === 0 ){ - if( audioWrapper[ k ] !== v ){ - audioWrapper[ k ] = v; + case 'endTime' : + v = X_AudioWrapper_timeStringToNumber( v ); + if( v || v === 0 ){ + if( this.endTime !== v ){ + this.endTime = v; + if( playing ) end = 1; + }; + } else { + delete this.endTime; + if( playing ) end = 1; + }; + break; - // 再生中の endTime の変更 - if( playing && ( k === 'endTime' || k === 'loopEndTime' ) ) end = 1; - }; - } else { - delete audioWrapper[ k ]; - if( playing && ( k === 'endTime' || k === 'loopEndTime' ) ) end = 1; - }; - break; - - case 'looped' : - if( playing ) seek = 2; - case 'loop' : - case 'autoplay' : - if( X_Type_isBoolean( v ) && audioWrapper[ k ] !== v ){ - audioWrapper[ k ] = v; + case 'loopStartTime' : + v = X_AudioWrapper_timeStringToNumber( v ); + if( v || v === 0 ){ + if( this.loopStartTime !== v ){ + this.loopStartTime = v; + }; + } else { + delete this.loopStartTime; + }; + break; + + case 'loopEndTime' : + v = X_AudioWrapper_timeStringToNumber( v ); + if( v || v === 0 ){ + if( this.loopEndTime !== v ){ + this.loopEndTime = v; + if( playing ) end = 1; + }; + } else { + delete this.loopEndTime; + if( playing ) end = 1; + }; + break; + + case 'looped' : + if( X_Type_isBoolean( v ) && this.looped !== v ){ + this.looped = v; + if( playing ) seek = 2; + }; + break; + + case 'loop' : + if( X_Type_isBoolean( v ) && this.autoLoop !== v ){ + this.autoLoop = v; + }; + break; + + case 'autoplay' : + if( X_Type_isBoolean( v ) && this.autoplay !== v ){ + this.autoplay = v; + }; + break; + + case 'volume' : + if( X_Type_isNumber( v ) ){ + v = v < 0 ? 0 : 1 < v ? 1 : v; + if( this.gain !== v ){ + this.gain = v; + // if playing -> update + if( playing ) volume = 4; + }; + }; + break; }; - break; + }; + + if( this.endTime < this.startTime || + ( this.loopEndTime < 0 ? this.endTime : this.loopEndTime ) < ( this.loopStartTime < 0 ? this.startTime : this.loopStartTime ) || + X_AudioWrapper_getEndTime( this ) < this.seekTime// || + //this.duration < this.endTime + ){ + console.log( 'setState 0:' + this.startTime + ' -> ' + this.endTime + ' d:' + this.duration + ' 1:' + this.loopStartTime + ' -> ' + this.loopEndTime ); + return; + }; + + v = end + seek + volume; + return v && this.afterUpdateState( v ); + } + + } +); - case 'volume' : - if( X_Type_isNumber( v ) ){ - v = v < 0 ? 0 : 1 < v ? 1 : v; - if( audioWrapper[ k ] !== v ){ - audioWrapper[ k ] = v; - // if playing -> update - if( playing ) volume = 4; - }; - }; - break; - }; - }; - - if( audioWrapper.endTime < audioWrapper.startTime || - ( audioWrapper.loopEndTime < 0 ? audioWrapper.endTime : audioWrapper.loopEndTime ) < ( audioWrapper.loopStartTime < 0 ? audioWrapper.startTime : audioWrapper.loopStartTime ) || - X_AudioWrapper_getEndTime( audioWrapper ) < audioWrapper.seekTime// || - //audioWrapper.duration < audioWrapper.endTime - ){ - console.log( 'error @updateStateObject() begin:' + audioWrapper.startTime + ' end:' + audioWrapper.endTime + ' d:' + audioWrapper.duration + ' ls:' + audioWrapper.loopStartTime ); - return 0; - }; - - return end + seek + volume; -}; function X_AudioWrapper_timeStringToNumber( time ){ var ary, ms, s = 0, m = 0, h = 0;