X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F07_audio%2F02_XHTMLAudio.js;h=fcf91f402d8f8200105501f156af0bfd04f39de7;hb=2956150a7c2798e60639b36d69b0c13f6b20a62a;hp=6da87e20577afa2fbb8f7b999f630bebc65253f0;hpb=adbf9e9a2c7d8e6857774f774742a7ff6fb50600;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/07_audio/02_XHTMLAudio.js b/0.6.x/js/07_audio/02_XHTMLAudio.js index 6da87e2..fcf91f4 100644 --- a/0.6.x/js/07_audio/02_XHTMLAudio.js +++ b/0.6.x/js/07_audio/02_XHTMLAudio.js @@ -10,7 +10,7 @@ var X_Audio_HTMLAudio_playTrigger = X_UA[ 'iOS' ] ? 'suspend' : X_UA[ 'AndroidBrowser2' ] ? 'stalled' : // Android 2.3.5(SBM101SH) では stalled は発生しない,,, X_UA[ 'AndroidBrowser4' ] ? 'loadeddata' : - X_UA[ 'OperaMobile' ] || X_UA[ 'OperaTablet' ] ? 'loadeddata' : 'canplay', + X_UA[ 'OperaMobile' ] || X_UA[ 'OperaTablet' ] ? 'loadeddata' : 'loadeddata', //'canplay', X_Audio_HTMLAudioWrapper, X_Audio_constructor = window[ 'Audio' ] || window.HTMLAudioElement, X_Audio_rawAudio, @@ -30,7 +30,8 @@ var X_Audio_HTMLAudio_playTrigger = X_Audio_HTMLAudioWrapper_ieMobile9Fix = ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ), X_Audio_HTMLAudioWrapper_durationFix = ( !X_Audio_HTMLAudioWrapper_currentTimeFix && 12 <= X_UA[ 'Opera' ] ), - X_Audio_HTMLAudioWrapper_shortPlayFix = X_UA[ 'AndroidBrowser2' ], + X_Audio_HTMLAudioWrapper_shortPlayFix = //X_UA[ 'AndroidBrowser2' ], + X_UA[ 'AndroidBrowser' ] && X_UA[ 'AndroidBrowserWebkit' ] < 534.3, // Android 4.1.1 でも遭遇 X_Audio_codecs; @@ -71,27 +72,10 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ }; }; - X_Audio_HTMLAudioWrapper = X_EventDispatcher[ 'inherits' ]( + X_Audio_HTMLAudioWrapper = X_Audio_AbstractAudioBackend[ 'inherits' ]( 'X.AV.HTML5AudioWrapper', X_Class.POOL_OBJECT, { - - proxy : null, - - startTime : 0, - endTime : -1, - loopStartTime : -1, - loopEndTime : -1, - seekTime : -1, - duration : 0, - - playing : false, - error : 0, - loop : false, - looped : false, - autoplay : false, - volume : 0.5, - _playTime : 0, _closed : true, _loaded : false, @@ -100,26 +84,26 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ _lastCurrentTime : 0, _src : '', - Constructor : function( proxy, source, option ){ + Constructor : function( target, source, option ){ var raw; - this.proxy = proxy; + this.target = target || this; this._closed = false; - X_AudioWrapper_updateStates( this, option ); + this.setState( option ); if( option[ 'useVideo' ] ){ - this[ '_rawObject' ] = raw = document.createElement( 'video' ); + this[ '_rawObject' ] = raw = document.createElement( 'video' ); raw.preload = 'none'; // auto, metadata, none //raw.autoplay = false, // no-auto - raw.loop = false; - raw.muted = false; - //raw.crossorigin = option[ 'crossorigin' ] || ''; //crossorigin: "anonymous", X.URL.isSameDomain() で切り替え + raw.loop = false; + raw.muted = false; + raw.crossorigin = option[ 'crossorigin' ] || ''; //crossorigin: "anonymous", X.URL.isSameDomain() で切り替え raw.style.cssText = 'position:absolute;bottom:0;left:-50px;width:100px;height:100px;opacity:0;'; raw.controls = false; raw.WebKitPlaysInline = true; raw.src = source; - //raw.onclick = "alert('play');this.play();"; + //raw.onclick = "alert('play');this.actualPlay();"; document.body.appendChild( raw ); //raw.load(); } else { @@ -159,6 +143,17 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ switch( e.type ){ case X_EVENT_KILL_INSTANCE : + // 【javascript】モバイル向けブラウザでも音を鳴らしたい【WebAudio】 + // http://ingaouhou.com/archives/3633 + // ・使い終わったインスタンスはload()しておくとやや安定 + this.playing && this.actualPause(); + delete this._closed; + delete this._loaded; + + this[ '_rawObject' ].src = ''; + this[ '_rawObject' ].load(); + + // removeChild for video break; }; }, @@ -170,7 +165,7 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ X_Audio_HTMLAudioWrapper_badOperaAndroid && alert( e.type ); - console.log( e.type ); + //console.log( e.type ); switch( e.type ){ case 'loadstart' : // ブラウザがコンテンツの検索を開始した場合に発生 @@ -230,11 +225,11 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ break; case 'ended' : - if( !this._closed && this.loop ){ - if( !( this.proxy[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_Callback_PREVENT_DEFAULT ) ){ + if( !this._closed && this.autoLoop ){ + if( !( this.target[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_Callback_PREVENT_DEFAULT ) ){ this.looped = true; - this.proxy[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED ); - this.play(); + this.target[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED ); + this.actualPlay(); }; return; }; @@ -250,11 +245,6 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ if( !this.duration && X_Type_isFinite( this[ '_rawObject' ].duration ) ){ this.duration = this.duration || this[ '_rawObject' ].duration * 1000; this._playForDuration = 2; - - //this.proxy[ 'asyncDispatch' ]( 'loadedmetadata' ); - //this.proxy[ 'asyncDispatch' ]( 'loadeddata' ); - //this.proxy[ 'asyncDispatch' ]( 'canplay' ); - //this.proxy[ 'asyncDispatch' ]( 'canplaythrough' ); loaded = true; //console.log( 'durationFix が完了' + this.duration ); break; @@ -264,8 +254,8 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ }; } else if( this[ '_rawObject' ].currentTime === this._lastCurrentTime ){ - //this.proxy[ 'dispatch' ]( 'seeking' ); - this.proxy[ 'dispatch' ]( X_EVENT_MEDIA_WAITING ); + //this.target[ 'dispatch' ]( 'seeking' ); + this.target[ 'dispatch' ]( X_EVENT_MEDIA_WAITING ); return; }; this._lastCurrentTime = this[ '_rawObject' ].currentTime; @@ -274,17 +264,18 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ if( this.playing ){ end = X_AudioWrapper_getEndTime( this ); - now = X_Audio_HTMLAudioWrapper_currentTimeFix ? X_Timer_now() - this._playTime + this._beginTime : this[ '_rawObject' ].currentTime * 1000 | 0; + now = this.getActualCurrentTime(); + //console.log( end + ' / ' + now ); if( 0 + end <= 0 + now ){ // なぜか iem9 で必要,,, - if( this.loop ){ - if( !( this.proxy[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_Callback_PREVENT_DEFAULT ) ){ + if( this.autoLoop ){ + if( !( this.target[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_Callback_PREVENT_DEFAULT ) ){ this.looped = true; - this.proxy[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED ); - this.play(); + this.target[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED ); + this.actualPlay(); }; } else { - this.pause(); - this.proxy[ 'dispatch' ]( X_EVENT_MEDIA_ENDED ); + this.actualPause(); + this.target[ 'dispatch' ]( X_EVENT_MEDIA_ENDED ); }; return; }; @@ -318,14 +309,7 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ console.log( '設定 ' + this._beginTime ); return; }; - - /* - this.proxy[ 'asyncDispatch' ]( 'loadedmetadata' ); - this.proxy[ 'asyncDispatch' ]( 'loadeddata' ); - this.proxy[ 'asyncDispatch' ]( 'canplay' ); - this.proxy[ 'asyncDispatch' ]( 'canplaythrough' ); */ - - + loaded = true; console.log( 'durationFix が完了' + this.duration ); @@ -348,27 +332,18 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ if( !this._loaded && ( loaded || e.type === X_Audio_HTMLAudio_playTrigger || e.type === 'loadeddata' ) ){ this.autoplay && X_Timer_once( 16, this, this.play ); this._loaded = true; - this.proxy[ 'dispatch' ]( X_EVENT_READY ); + this.target[ 'asyncDispatch' ]( X_EVENT_READY ); console.log( 'Loaded! ' + e.type + ' d:' + ( this.duration | 0 ) ); return; }; - loaded || ( type && this.proxy[ 'dispatch' ]( type ) ); - }, - - close : function(){ - // 【javascript】モバイル向けブラウザでも音を鳴らしたい【WebAudio】 - // http://ingaouhou.com/archives/3633 - // ・使い終わったインスタンスはload()しておくとやや安定 - this.playing && this.pause(); - delete this._closed; - delete this._loaded; - - this[ '_rawObject' ].src = ''; - this[ '_rawObject' ].load(); + if( !loaded && type ){ + this.target[ 'dispatch' ]( type ); + type === X_EVENT_ERROR && this[ 'kill' ](); + }; }, - - play : function(){ + + actualPlay : function(){ var begin, end; // もし kill 後に autoplayTimer で呼ばれても、_closed==true なので平気 @@ -397,14 +372,13 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ delete this._playForDuration; }; - if( !this.playing ){ if( X_UA[ 'Chrome' ] ){ // [CHROME][FIX] volume TODO どの version で 修正される? // [!] delay X_Timer_once( 0, this, this._fixForChrome ); this[ '_rawObject' ].volume = 0; } else { - this[ '_rawObject' ].volume = this.volume; + this[ '_rawObject' ].volume = this.gain; }; this[ '_rawObject' ].play(); this.playing = true; @@ -425,13 +399,13 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ // [CHROME][FIX] volume _fixForChrome : X_UA[ 'Chrome' ] && function(){ - !this._closed && ( this[ '_rawObject' ].volume = this.volume ); + !this._closed && ( this[ '_rawObject' ].volume = this.gain ); }, - pause : function(){ + actualPause : function(){ if( !this.playing ) return; - this.seekTime = this.state().currentTime; + this.seekTime = this.getActualCurrentTime(); delete this._playTime; @@ -443,55 +417,30 @@ if( X_Audio_constructor && !X_Audio_HTMLAudioWrapper_badOperaAndroid ){ }; delete this.playing; }, - - state : function( obj ){ - var result; - - if( obj === undefined ){ - 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.loop, - looped : this.looped, - volume : this.volume, - playing : this.playing, // && !this[ '_rawObject' ].error && !this[ '_rawObject' ].paused && !this[ '_rawObject' ].ended, - duration : this.duration, - - currentTime : - this.playing ? - ( X_Audio_HTMLAudioWrapper_currentTimeFix ? + + getActualCurrentTime : function(){ + return ( X_Audio_HTMLAudioWrapper_currentTimeFix ? X_Timer_now() - this._playTime + this._beginTime : - this[ '_rawObject' ].currentTime * 1000 | 0 ) : - this.seekTime, - /* - http://www.w3schools.com/tags/av_prop_error.asp - 1 = MEDIA_ERR_ABORTED - fetching process aborted by user - 2 = MEDIA_ERR_NETWORK - error occurred when downloading - 3 = MEDIA_ERR_DECODE - error occurred when decoding - 4 = MEDIA_ERR_SRC_NOT_SUPPORTED - audio/video not supported - */ - error : this[ '_rawObject' ].error || 0 // 0, 1 ~ 4 - }; - }; + this[ '_rawObject' ].currentTime * 1000 | 0 ); + }, + /* + http://www.w3schools.com/tags/av_prop_error.asp + 1 = MEDIA_ERR_ABORTED - fetching process aborted by user + 2 = MEDIA_ERR_NETWORK - error occurred when downloading + 3 = MEDIA_ERR_DECODE - error occurred when decoding + 4 = MEDIA_ERR_SRC_NOT_SUPPORTED - audio/video not supported + */ + getActualError : function(){ + return this[ '_rawObject' ].error || 0; + }, - result = X_AudioWrapper_updateStates( this, obj ); - - if( result & 2 ){ // seek - this.play(); - //} else - //if( result & 1 ){ - //if( X_Audio_HTMLAudioWrapper_currentTimeFix ){ - // this.play(); - //}; - + afterUpdateState : function( result ){ + if( result & 3 ){ // seek + this.actualPlay(); } else if( result & 4 ){ - this[ '_rawObject' ].volume = this.volume; - }; - + this[ '_rawObject' ].volume = this.gain; + }; } }