From: itozyun Date: Sun, 14 Dec 2014 22:14:02 +0000 (+0900) Subject: Version 0.6.119, add ended event to X.Audio.Sprite & GPU layer off. X-Git-Url: http://git.osdn.jp/view?a=commitdiff_plain;h=b8b45541169da1fad8e5454c266f837ea3c52961;p=pettanr%2FclientJs.git Version 0.6.119, add ended event to X.Audio.Sprite & GPU layer off. --- diff --git a/0.6.x/js/02_dom/02_XNode.js b/0.6.x/js/02_dom/02_XNode.js index 01588f9..9c44e1d 100644 --- a/0.6.x/js/02_dom/02_XNode.js +++ b/0.6.x/js/02_dom/02_XNode.js @@ -1377,6 +1377,8 @@ var X_Node__afterActualCreate = var X_Node__actualRemove = X_UA_DOM.W3C ? + // GPUレイヤーにいるうちは remove しない。-> GPU解除してから remove する + // Firefox34 では遭遇せず、Safari で何度かアニメーションしているうちに発生 ( function( that, isChild ){ var xnodes = that._xnodes, elm = that._rawObject, diff --git a/0.6.x/js/02_dom/10_XNodeAnime.js b/0.6.x/js/02_dom/10_XNodeAnime.js index 2adfebb..0343ec8 100644 --- a/0.6.x/js/02_dom/10_XNodeAnime.js +++ b/0.6.x/js/02_dom/10_XNodeAnime.js @@ -64,7 +64,8 @@ var X_Node_ANIMATIONS = [], X_Node_Anime_needsDetection = false, X_Node_Anime_hasTransform = !!X_Node_CSS_VENDER_PREFIX[ 'transform' ], /* Opera mobile で translateZ(0) が有効だと XY が 0 0 になる */ - X_Node_Anime_translateZ = X_Node_CSS_VENDER_PREFIX[ 'perspective' ] && !X.UA.OperaMobile && !X.UA.OperaTablet ? ' translateZ(0)' : '', + /* GPUレイヤーにいる間に要素のコンテンツを変更をすると transitionend が動かなくなるっぽい Mac safari と firefox, 手当てが済むまでここは常に false */ + X_Node_Anime_translateZ = '', //X_Node_CSS_VENDER_PREFIX[ 'perspective' ] && !X.UA.OperaMobile && !X.UA.OperaTablet ? ' translateZ(0)' : '', X_Node_Anime_hasTransition = !!X_Node_CSS_VENDER_PREFIX[ 'transitionDelay' ] && !X.UA.Opera, // Opera12(XP,8.1) 切った方がスムース X_Node_Anime_transitionProps = X_Node_Anime_hasTransform ? X_Node_CSS_VENDER_PREFIX[ 'transform' ] : 'left,top'; @@ -134,10 +135,10 @@ function X_Node_Anime_reserveUpdate( before ){ X_Node_Anime_reserved = true; if( X_Node_updateTimerID ){ - console.log( before ? '> BEFORE_UPDATE' : '> UPDATED' ); + //console.log( before ? '> BEFORE_UPDATE' : '> UPDATED' ); X_System.listenOnce( before ? X.Event.BEFORE_UPDATE : X.Event.UPDATED, X_Node_Anime_updateAnimations ); } else { - console.log( '> Timer' ); + //console.log( '> Timer' ); // Opera12 requestAnimationFrame では transition が動かない、、、 X_Node_Anime_updateTimerID = X_UA.Opera ? @@ -150,7 +151,7 @@ function X_Node_Anime_reserveUpdate( before ){ function X_Node_Anime_updateAnimations( v ){ var i = X_Node_ANIMATIONS.length, ret, c = false; - console.log( v.type || v ); + //console.log( v.type || v ); //console.log( 'updateAnimations ' + i + ' ' + X_Node_Anime_needsDetection ); @@ -311,14 +312,14 @@ function X_Node_Anime_updateAnimation( xnode ){ case 15 : // GPU有効で停止(待機)している xnode の解除 - console.log( 'GPU有効で停止(待機)している xnode の解除' + xnode._tag + xnode.getOrder() ); + //console.log( 'GPU有効で停止(待機)している xnode の解除' + xnode._tag + xnode.getOrder() ); X_Node_Anime_clearTransition( xnode ); X_Node_Anime_updatePosition( xnode, obj.destX, obj.destY, obj.destA, false ); obj.gpuTimerID && X.Timer.remove( obj.gpuTimerID ); return true; case 100 : // stop() : アニメーションの中断して削除 - console.log( 'stop() gpu:' + obj.gpuParent ); + //console.log( 'stop() gpu:' + obj.gpuParent ); current = X_Node_Anime_getComputedPosition( xnode ); X_Node_Anime_clearTransition( xnode ); @@ -350,7 +351,7 @@ function X_Node_Anime_onTransitionEnd(){ this._anime.phase = 3; X_Node_Anime_needsDetection = true; X_Node_Anime_reserveUpdate(); - console.log( 'トランジション終了' ); + //console.log( 'トランジション終了' ); return X.Callback.UN_LISTEN | X.Callback.PREVENT_DEFAULT | X.Callback.STOP_PROPAGATION; }; diff --git a/0.6.x/js/05_util/01_XNinjaIframe.js b/0.6.x/js/05_util/01_XNinjaIframe.js index 8a026f0..a72e64d 100644 --- a/0.6.x/js/05_util/01_XNinjaIframe.js +++ b/0.6.x/js/05_util/01_XNinjaIframe.js @@ -13,7 +13,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits( _iwin : null, - _html : '', + _contentHTML : '', _name : '', _ready : false, @@ -47,7 +47,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits( this.xnodeIframe.css( { position : 'absolute' } ); }; - if( html ) this._html = html; + if( html ) this._contentHTML = html; }, handleEvent : function( e ){ @@ -64,7 +64,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits( this.xnodeIframe.listen( [ X_UA.IE < 9 ? 'readystatechange' : 'load', 'error' ], this ); if( !( X_UA.IE < 9 ) ){ - this._html && X_Util_NinjaIframe_writeToIframe( this ); + this._contentHTML && X_Util_NinjaIframe_writeToIframe( this ); this._ready = true; return; }; @@ -73,7 +73,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits( if( ( raw.readyState !== 'complete' && raw.readyState !== 'loaded' ) ) return X.Callback.STOP_PROPAGATION; // ie9- if( !this._ready ){ - this._html && X_Util_NinjaIframe_writeToIframe( this ); + this._contentHTML && X_Util_NinjaIframe_writeToIframe( this ); this._ready = true; return; }; @@ -90,14 +90,14 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits( return X.Callback.STOP_PROPAGATION; }, - refresh : function( opt_html ){ + refresh : function( opt_contentHTML ){ var raw = this.xnodeIframe._rawObject, idoc; this._ready = false; if( !this._iwin ){ - this._html = opt_html; + this._contentHTML = opt_html; return this; }; @@ -109,7 +109,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits( if( !opt_html ) return this; - this._html = opt_html; + this._contentHTML = opt_html; X_UA.IE < 9 || X_Util_NinjaIframe_writeToIframe( this ); return this; @@ -127,9 +127,9 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits( function X_Util_NinjaIframe_writeToIframe( that ){ var raw = that.xnodeIframe._rawObject, idoc = raw.contentDocument || that._iwin.document, - html = that._html; + html = that._contentHTML; - delete that._html; + delete that._contentHTML; that._ready = true; idoc.open(); diff --git a/0.6.x/js/06_net/01_XNetXHR.js b/0.6.x/js/06_net/01_XNetXHR.js index 1ea396c..2ecd889 100644 --- a/0.6.x/js/06_net/01_XNetXHR.js +++ b/0.6.x/js/06_net/01_XNetXHR.js @@ -94,6 +94,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ _type : '', _busy : false, _canceled : false, + _error : false, _percent : 0, _timerID : 0, @@ -175,17 +176,17 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ if( raw.timeout !== undefined ){ raw.timeout = timeout; } else { - //this._timerID = X.Timer.once( timeout, this, this.onTimeout ); + this._timerID = X.Timer.once( timeout, this, this.onTimeout ); }; // send 前にフラグを立てる,回線が早いと raw.send() 内で onload -> _busy = false ののち、 _busy = true するため。 this._busy = true; - //raw.send( postbody || '' ); - this._timerID = X.Timer.once( 16, this, this._lazySend, [ postbody || '', timeout ] ); + raw.send( postbody || '' ); + //this._timerID = X.Timer.once( 16, this, this._lazySend, [ postbody || '', timeout ] ); }, - + /* // send() 内で onload するケースがあり、そのときはイベントリスナが間に合わないので、タイマーをかませる。 _lazySend : function( postbody, timeout ){ if( this._rawObject.timeout === undefined ){ @@ -198,7 +199,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ // sendをonreadystatechangeの前に記述すると、ieでは動作しなくなります、、、。 // konquerorでエラーが発生するのでここでは、とりあえず、send('') としました。 this._rawObject.send( postbody ); - }, + }, */ cancel : function(){ /* X.Net.XHR.CANCELABLE && */ this._rawObject.abort && this._rawObject.abort(); @@ -215,8 +216,14 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ // domes.lingua.heliohost.org/dom-intro/load-save2.html // 規定上は open() を呼び出すと XMLHttpRequest オブジェクトが未送信状態に戻りますが、 // Opera 10.10、Safari 4.1 では、同一オリジン制限に違反した XMLHttpRequest オブジェクトは再度 open() しても未送信状態に戻りません。 - if( X_UA.Opera || X_UA.Webkit ){ - + + // Timeout した Gecko の xhr.response に触るとエラー?? + if( X_UA.Opera || X_UA.Webkit || X_UA.Gecko ){ + if( this._error ){ + X_EventDispatcher_toggleAllEvents( this, false ); + this._rawObject = new XMLHttpRequest(); + X_EventDispatcher_toggleAllEvents( this, true ); + }; }; // XMLHttpRequest の使い方 @@ -225,7 +232,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ this._rawObject.abort && this._rawObject.abort(); this._method = this._type = ''; - this._canceled = this._busy = false; + this._canceled = this._busy = this._error = false; this._timerID && X.Timer.remove( this._timerID ); this._percent = this._timerID = 0; }, @@ -276,7 +283,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ case 'load' : if( !live ) return this.reset(); - if( this._percent === 100 ) return; + if( !this._busy ) return; this._percent = 100; @@ -325,9 +332,9 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ break; }; - this.asyncDispatch( { type : X.Event.SUCCESS, status : status || 200, data : data } ); + this.asyncDispatch( 32, { type : X.Event.SUCCESS, status : status || 200, data : data } ); } else { - live && this.asyncDispatch( { type : X.Event.ERROR, status : raw.status || 0, percent : 100 } ); + live && this.asyncDispatch( 32, { type : X.Event.ERROR, status : raw.status || 0, percent : 100 } ); }; break; @@ -340,12 +347,14 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ case 'error' : //console.dir( e ); - this._busy = false; - live && this.asyncDispatch( { type : X.Event.ERROR, status : raw.status } ); + this._busy = false; + this._error = X_UA.Opera || X_UA.Webkit; + live && this.asyncDispatch( 32, { type : X.Event.ERROR, status : raw.status } ); break; case 'timeout' : // Gecko 12.0 https://developer.mozilla.org/ja/docs/XMLHttpRequest/Synchronous_and_Asynchronous_Requests - this._busy = false; + this._busy = false; + this._error = !!X_UA.Gecko; this.asyncDispatch( X.Event.TIMEOUT ); break; }; diff --git a/0.6.x/js/07_audio/00_XAudio.js b/0.6.x/js/07_audio/00_XAudio.js index 8a44956..5572486 100644 --- a/0.6.x/js/07_audio/00_XAudio.js +++ b/0.6.x/js/07_audio/00_XAudio.js @@ -47,7 +47,12 @@ function X_Audio_detectComplete( e, proxy, option, sourceList, source, ext, sup switch( e.type ){ case 'support' : proxy._backend = i; - proxy.asyncDispatch( { type : 'backendfound', option : option, source : source, backendName : this.backendName } ); + proxy.asyncDispatch( { + type : 'backendfound', + option : option, + source : source, + backendName : this.backendName + } ); break; case 'nosupport' : if( backend = X_Audio_BACKENDS[ i + 1 ] ){ diff --git a/0.6.x/js/07_audio/01_XWebAudio.js b/0.6.x/js/07_audio/01_XWebAudio.js index bb64a98..abd163b 100644 --- a/0.6.x/js/07_audio/01_XWebAudio.js +++ b/0.6.x/js/07_audio/01_XWebAudio.js @@ -85,9 +85,16 @@ if( X_Audio_WebAudio_context ){ return; case X.Event.SUCCESS : - console.log( 'WebAudio xhr success! ' + !!X_Audio_WebAudio_context.decodeAudioData ); + console.log( 'WebAudio xhr success! ' + !!X_Audio_WebAudio_context.decodeAudioData + ' t:' + typeof e.data ); // TODO 旧api // https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext + + // http://qiita.com/sou/items/5688d4e7d3a37b4e2ff1 + // iOS 7.1 で decodeAudioData に処理が入った瞬間にスクリーンを長押しする(スクロールを繰り返す)と + // decoeAudioData の処理がキャンセルされることがある(エラーやコールバックの発火もなく、ただ処理が消滅する)。 + if( X_Audio_WebAudio_context.createBuffer && X_UA.iOS ){ + this._onDecodeSuccess( X_Audio_WebAudio_context.createBuffer( e.data, false ) ); + } else if( X_Audio_WebAudio_context.decodeAudioData ){ X_Audio_WebAudio_context.decodeAudioData( e.data, this.onDecodeSuccess = X_Callback_create( this, this._onDecodeSuccess ), @@ -250,8 +257,10 @@ if( X_Audio_WebAudio_context ){ }; if( this.loop ){ - this.looped = true; - ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play(); + if( !( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) ){ + this.looped = true; + this.play(); + }; } else { this.pause(); this.proxy.dispatch( 'ended' ); @@ -315,10 +324,9 @@ if( X_Audio_WebAudio_context ){ { backendName : 'Web Audio', + // detect : function( proxy, source, ext ){ - var ok = ext === 'mp3' || ext === 'ogg'; - - proxy.asyncDispatch( ok ? 'support' : 'nosupport' ); + proxy.asyncDispatch( X_Audio_codecs[ ext ] ? 'support' : 'nosupport' ); }, klass : X_Audio_WebAudioWrapper diff --git a/0.6.x/js/07_audio/02_XHTMLAudio.js b/0.6.x/js/07_audio/02_XHTMLAudio.js index ee712a5..e2cdca3 100644 --- a/0.6.x/js/07_audio/02_XHTMLAudio.js +++ b/0.6.x/js/07_audio/02_XHTMLAudio.js @@ -13,16 +13,43 @@ var X_Audio_HTMLAudio_playTrigger = // Opera Mobile 12 android4.4.4 & 2.3.5 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する X_Audio_HTMLAudioWrapper_currentTimeFix = !!X_UA.OperaMobile || !!X_UA.OperaTablet, // 一方 Desktop の Opera12 は、loadeddata 等では duration が infinity で、再生後の durationchange 時に duration が判明する。 + // opera12 volume, mute の変更が2度目以降できない // duration 判明後には currentTime によるシークと、現在時間の取得が可能になる。 // canplay で play() durationchange で duration が取れたら loadedmetadata->loadeddata -> canplay する // boombox.js に書いてあった currentTime の効かないブラウザってこいつのことみたい、、、 - X_Audio_HTMLAudioWrapper_currentTimeFix2 = !X_Audio_HTMLAudioWrapper_currentTimeFix && X_UA.Opera, + // Opera12.17 Win32(XP) portable apps は勝手に再生が始まる、、、その際には timeupdate が発行されない、、、 iframe+image+audio で使わないときは破棄する、とか。 + // opera11、10.54 WinXP はまとも、、、 + // X_Audio_Sprite_handleEvent でも使用 + X_Audio_HTMLAudioWrapper_durationFix = !X_Audio_HTMLAudioWrapper_currentTimeFix && 12 < X_UA.Opera, - X_Audio_HTMLAudioWrapper_shortPlayFix = !!X_UA.AndroidBrowser4; + X_Audio_HTMLAudioWrapper_shortPlayFix = !!X_UA.AndroidBrowser4, + + X_Audio_codecs; if( window.HTMLAudioElement ){ + X_Audio_rawAudio = new Audio; + + X_Audio_codecs = { + mp3 : X_Audio_rawAudio.canPlayType('audio/mpeg;'), + opus : X_Audio_rawAudio.canPlayType('audio/ogg; codecs="opus"'), + ogg : X_Audio_rawAudio.canPlayType('audio/ogg; codecs="vorbis"'), + wav : X_Audio_rawAudio.canPlayType('audio/wav; codecs="1"'), + aac : X_Audio_rawAudio.canPlayType('audio/aac;'), + m4a : (X_Audio_rawAudio.canPlayType('audio/x-m4a;') || X_Audio_rawAudio.canPlayType('audio/m4a;') || X_Audio_rawAudio.canPlayType('audio/aac;')), + mp4 : (X_Audio_rawAudio.canPlayType('audio/x-mp4;') || X_Audio_rawAudio.canPlayType('audio/mp4;') || X_Audio_rawAudio.canPlayType('audio/aac;')), + weba : X_Audio_rawAudio.canPlayType('audio/webm; codecs="vorbis"') + }; + + (function( k, v ){ + for( k in X_Audio_codecs ){ + v = X_Audio_codecs[ k ]; + X_Audio_codecs[ k ] = v && v !== 'no'; + }; + })(); + + X_Audio_HTMLAudioWrapper = X.EventDispatcher.inherits( 'X.AV.HTML5AudioWrapper', X.Class.POOL_OBJECT, @@ -44,13 +71,12 @@ if( window.HTMLAudioElement ){ autoplay : false, volume : 0.5, - _timerID : 0, _playTime : 0, _closed : true, _loaded : false, - _playForDuration : false, - _currentTimeFix : 0, - _shortFix : 0, + _beginTime : 0, + _playForDuration : 0, + _src : '', Constructor : function( proxy, source, option ){ this.proxy = proxy; @@ -74,6 +100,8 @@ if( window.HTMLAudioElement ){ //this._rawObject.load(); } else { this._rawObject = X_Audio_rawAudio || new Audio( source );// X_Doc_create( 'audio', { src : source } ).appendToRoot();//( X.X_Node_systemNode ); + this._rawObject.autobuffer = false; + this._src = source; }; this.listen( [ @@ -106,7 +134,7 @@ if( window.HTMLAudioElement ){ */ handleEventProxy : function( e ){ var loaded; - console.log( 'HTMLAudio ' + e.type ); + console.log( 'HTMLAudio ' + e.type + ' ' + this._rawObject.currentTime ); switch( e.type ){ case 'loadstart' : // ブラウザがコンテンツの検索を開始した場合に発生 @@ -119,17 +147,18 @@ if( window.HTMLAudioElement ){ break; case 'canplay' : // 今すぐに再生を再開できるが、バッファリングが不十分でコンテンツを最後まで表示できないと予測している場合に発生 - if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){ - console.log( 'play ' + this.duration ); - this._playForDuration = true; - this._rawObject.currentTime = 0; + if( X_Audio_HTMLAudioWrapper_durationFix && this._playForDuration === 0 ){ + console.log( 'start DurationFix for Desktop Opera12 - ' + this._rawObject.duration ); + this._playForDuration = 1; + //this._rawObject.currentTime = 0; this._rawObject.play(); - this._rawObject.currentTime = 0; + this._rawObject.currentTime = this._beginTime / 1000; // 必要! + return; }; case 'loadedmetadata' : // ブラウザがメディアリソースの長さと寸法を判定した場合に発生 case 'loadeddata' : // コンテンツの表示を現在の再生位置で初めて行えるようになった場合に発生 case 'canplaythrough' : // 今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生 - if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ) return; + if( X_Audio_HTMLAudioWrapper_durationFix && this._playForDuration !== 2 ) return; this.duration = this._rawObject.duration * 1000; console.log( this.duration ); break; @@ -150,50 +179,70 @@ if( window.HTMLAudioElement ){ case 'seeked' : // シークがfalseに変化した場合に発生 case 'ratechange' : // defaultPlaybackRate属性とplaybackRate属性のどちらかが更新された場合に発生 case 'volumechange' : // volume属性とmuted属性のどちらかが変化した場合に発生 - if( this._playForDuration ) return; + if( this._playForDuration === 1 ) return; break; case 'timeupdate' : // 通常の再生が行われ現在の再生位置の変化が起こった場合に発生 - // console.log( this._rawObject.currentTime ); - if( this._playForDuration ) return; + console.log( this._rawObject.currentTime ); + if( this._playForDuration === 1 ){ + this._rawObject.currentTime = this._beginTime / 1000; // 必要! + return; + }; this._onEnded(); break; case 'ended' : - if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){ - delete this._currentTimeFix; - }; if( !this._closed && this.loop ){ this.looped = true; ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play(); } else { - this._timerID && X.Timer.remove( this._timerID ); this.seekTime = 0; - delete this._timerID; delete this.playing; }; break; case 'durationchange' : // duration属性が更新された場合に発生 - this.duration = this._rawObject.duration * 1000; - // console.log( this._rawObject.duration ); - if( this._playForDuration ){ - this._rawObject.pause(); - this._rawObject.currentTime = 0.001; - delete this._playForDuration; + if( !X_Audio_HTMLAudioWrapper_durationFix ){ + this.duration = this._rawObject.duration * 1000; + } else + // Desktop Opera + if( this._rawObject.duration !== 1 / 0 ){ + + console.log( this._rawObject.duration ); + + this.duration = this._rawObject.duration * 1000; + + if( this._playForDuration === 0 ) this._playForDuration = 2; + + if( this._playForDuration === 1 ){ + this._playForDuration = 2; + + console.log( 'Loaded ' + this._loaded ); + + if( this._loaded ){ + this._rawObject.currentTime = this._beginTime / 1000; + 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( 'Desktop Opera のための currentTime と duration の fix が完了' + this.duration ); + + if( this.autoplay ){ + this._rawObject.currentTime = this._beginTime / 1000; + } else { + // Opera12.17 WinXP で勝手に再生される不具合 + // これで一応再生は止まる、、、 + this._rawObject.src = ''; + //this._rawObject.load(); + }; + }; - this.proxy.asyncDispatch( 'loadedmetadata' ); - this.proxy.asyncDispatch( 'loadeddata' ); - this.proxy.asyncDispatch( 'canplay' ); - this.proxy.asyncDispatch( 'canplaythrough' ); - loaded = true; - console.log( 'DEsktop Opera のための currentTime と duration の fix が完了' + this.duration ); - }; - if( this._currentTimeFix === 1 ){ - this._currentTimeFix++; - this._rawObject.currentTime = this._beginTime / 1000; - return; }; break; @@ -233,21 +282,20 @@ if( window.HTMLAudioElement ){ end = X_AudioWrapper_getEndTime( this ); begin = X_AudioWrapper_getStartTime( this, end, true ); - if( X_Audio_HTMLAudioWrapper_shortPlayFix ){ begin -= end - begin > 1000 ? 200 : 400; begin = begin < 0 ? 0 : begin; - }; - - this._rawObject.currentTime = begin / 1000; - + }; - if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){ - //this._currentTimeFix++; + if( !this._rawObject.src ){ this._beginTime = begin; + this._rawObject.src = this._src; + delete this._playForDuration; }; + this._rawObject.currentTime = begin / 1000; + console.log( '[HTMLAudio] play ' + begin + ' -> ' + end ); if( !this.playing ){ @@ -263,15 +311,8 @@ if( window.HTMLAudioElement ){ }; if( X_Audio_HTMLAudioWrapper_currentTimeFix ){ - //this._timerID && X.Timer.remove( this._timerID ); this._beginTime = begin; - this._playTime = X_Timer_now(); - - if( end < this.duration ){ - //this._timerID = X.Timer.once( end - begin, this, this._onEnded ); - } else { - delete this._timerID; - }; + this._playTime = X_Timer_now(); }; }, @@ -284,28 +325,23 @@ if( window.HTMLAudioElement ){ _onEnded : function(){ var currentTime, time; - delete this._timerID; - if( this.playing ){ currentTime = X_Audio_HTMLAudioWrapper_currentTimeFix ? X_Timer_now() - this._playTime + this._beginTime : this._rawObject.currentTime * 1000 | 0; time = currentTime - X_AudioWrapper_getEndTime( this ); - if( X_Audio_HTMLAudioWrapper_shortPlayFix ){ - //time -= this._shortFix; - }; - if( time < 0 ){ console.log( '> onEnd ' + (-time) + ' ' + currentTime + '/' + ( X_AudioWrapper_getEndTime( this ) ) ); - //if( X_Audio_HTMLAudioWrapper_currentTimeFix ) this._timerID = X.Timer.once( -time, this, this._onEnded ); return; }; if( this.loop ){ - this.looped = true; - ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play(); + if( !( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) ){ + this.looped = true; + this.play(); + }; } else { this.pause(); - this.dispatch( 'ended' ); + this.proxy.dispatch( 'ended' ); }; }; }, @@ -314,13 +350,7 @@ if( window.HTMLAudioElement ){ if( !this.playing ) return; this.seekTime = this.state().currentTime; - - if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){ - delete this._currentTimeFix; - }; - - //this._timerID && X.Timer.remove( this._timerID ); - //delete this._timerID; + delete this._playTime; !this._rawObject.error && this._rawObject.pause(); @@ -412,6 +442,7 @@ if( window.HTMLAudioElement ){ * - FireFox3.6, Android 2.3.6については、src変更後、load()を呼び出さないと切り替わらなかった。iPhoneはload()が不要。 */ detect : function( proxy, source, ext ){ + /* var ok, mineType = 'audio/' + ext; switch( ext ){ case 'mp3' : @@ -443,7 +474,9 @@ if( window.HTMLAudioElement ){ ok = X_Audio_rawAudio.canPlayType( mineType ); }; - proxy.asyncDispatch( ok ? 'support' : 'nosupport' ); + proxy.asyncDispatch( ok ? 'support' : 'nosupport' ); */ + + proxy.asyncDispatch( X_Audio_codecs[ ext ] ? 'support' : 'nosupport' ); }, klass : X_Audio_HTMLAudioWrapper diff --git a/0.6.x/js/07_audio/03_XSilverlightAudio.js b/0.6.x/js/07_audio/03_XSilverlightAudio.js index 02c1ec1..5ef3c25 100644 --- a/0.6.x/js/07_audio/03_XSilverlightAudio.js +++ b/0.6.x/js/07_audio/03_XSilverlightAudio.js @@ -307,11 +307,13 @@ if( X.Pulgin.SilverlightEnabled ){ }; if( this.loop ){ - this.looped = true; - ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play(); + if( !( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) ){ + this.looped = true; + this.play(); + }; } else { this.pause(); - this.proxy.dispatch( 'ended' ); + this.proxy.dispatch( 'ended' ); }; }; }, diff --git a/0.6.x/js/07_audio/10_XAudioSprite.js b/0.6.x/js/07_audio/10_XAudioSprite.js index 4152fa2..39751ae 100644 --- a/0.6.x/js/07_audio/10_XAudioSprite.js +++ b/0.6.x/js/07_audio/10_XAudioSprite.js @@ -6,8 +6,8 @@ */ var X_Audio_Sprite_shouldUse = window.HTMLAudioElement && ( X_UA.iOS || X_UA.AndroidBrowser || X_UA.OperaMobile || X_UA.OperaTablet ), X_Audio_Sprite_useVideoForMulti = 4 <= X_UA.AndroidBrowser && 534.3 < X_UA.AndroidBrowserWebkit, // ドスパラパッドはビデオのインライン再生が不可 + X_Audio_Sprite_needTouchAndroid = X_Audio_Sprite_useVideoForMulti, X_Audio_Sprite_needTouchFirst = !!X_UA.iOS || X_Audio_Sprite_useVideoForMulti, - X_Audio_Sprite_inTouchAction = false, X_Audio_Sprite_enableMultiTrack = !( X_UA.iOS && !X_Audio_WebAudio_context ) && !( X_UA.AndroidBrowser4 && X_UA.AndroidBrowserWebkit <= 534.3 ), X_Audio_Sprite_enableVolume = window.HTMLAudioElement && ( !X_UA.iOS && !X_UA.AndroidBrowser && !X_UA.OperaMobile && !X_UA.OperaTablet ), X_Audio_Sprite_maxTracks = !X_Audio_Sprite_enableMultiTrack ? 1 : X_Audio_Sprite_useVideoForMulti ? 2 : 9, @@ -301,17 +301,39 @@ X_Audio_Sprite_members = { }; function X_Audio_Sprite_handleEvent( e ){ - var i, tracks, track; + var i, tracks, track, _e; switch( e.type ){ case 'backendfound' : - this.asyncDispatch( e ); + _e = { + type : e.type, + source : e.source, + backendName : e.backendName + }; + + if( X_Audio_Sprite_needTouchFirst ){ + if( e.backendName === 'Web Audio' ){ + _e[ 'needTouchForPlay' ] = true; + } else { + _e[ 'needTouchForLoad' ] = true; + }; + }; + this.asyncDispatch( _e ); + e.target.unlisten( 'nobackend', this, X_Audio_Sprite_handleEvent ); if( e.backendName === 'HTML Audio' ){ - e.target.listenOnce( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata' ], this, X_Audio_Sprite_handleEvent ); + // Android 4.4.4 Y!Browser でたまにロードを検出できていない?問題を解決できないかな? -> , 'canplaythrough' + // タッチイベント内でloadを開始。ロード完了したら無音の再生を実施。timeupdate が返ったらいつでも再生が出来る状態になる。 + e.target.listenOnce( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata', 'canplaythrough' ], this, X_Audio_Sprite_handleEvent ); } else { e.target.listenOnce( 'canplaythrough', this, X_Audio_Sprite_handleEvent ); }; + // READY, needTouchForPlay, needTouchForLoad + if( X_Audio_HTMLAudioWrapper_durationFix ){ + for( i = 0; i < X_Audio_Sprite_TEMP.tracks.length; ++i ){ + X_Audio_Sprite_instance.pause( i ); + }; + }; break; case 'nobackend' : @@ -324,7 +346,7 @@ function X_Audio_Sprite_handleEvent( e ){ case 'loadeddata' : e.target.unlisten( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata', 'canplaythrough' ], this, X_Audio_Sprite_handleEvent ); - if( X_Audio_Sprite_useVideoForMulti ){ + if( X_Audio_Sprite_needTouchAndroid ){ for( i = 0; i < X_Audio_Sprite_TEMP.tracks.length; ++i ){ X_Audio_Sprite_instance.pause( i ); }; @@ -339,6 +361,8 @@ function X_Audio_Sprite_handleEvent( e ){ if( e.target === X_Audio_Sprite_TEMP.bgmTrack ){ X_Audio_Sprite_TEMP.bgmLooped = true; } else { + e.target.state().looped || this.asyncDispatch( 'ended' ); // uid + // single track | iOS if( X_Audio_Sprite_TEMP.bgmPlaying && !X_Audio_Sprite_TEMP.bgmTrack ){ X_Audio_Sprite_TEMP.bgmTrack = e.target;