\r
var X_Node__actualRemove =\r
X_UA_DOM.W3C ?\r
+ // GPUレイヤーにいるうちは remove しない。-> GPU解除してから remove する\r
+ // Firefox34 では遭遇せず、Safari で何度かアニメーションしているうちに発生\r
( function( that, isChild ){\r
var xnodes = that._xnodes,\r
elm = that._rawObject,\r
X_Node_Anime_needsDetection = false,\r
X_Node_Anime_hasTransform = !!X_Node_CSS_VENDER_PREFIX[ 'transform' ],\r
/* Opera mobile で translateZ(0) が有効だと XY が 0 0 になる */\r
- X_Node_Anime_translateZ = X_Node_CSS_VENDER_PREFIX[ 'perspective' ] && !X.UA.OperaMobile && !X.UA.OperaTablet ? ' translateZ(0)' : '',\r
+ /* GPUレイヤーにいる間に要素のコンテンツを変更をすると transitionend が動かなくなるっぽい Mac safari と firefox, 手当てが済むまでここは常に false */\r
+ X_Node_Anime_translateZ = '', //X_Node_CSS_VENDER_PREFIX[ 'perspective' ] && !X.UA.OperaMobile && !X.UA.OperaTablet ? ' translateZ(0)' : '',\r
X_Node_Anime_hasTransition = !!X_Node_CSS_VENDER_PREFIX[ 'transitionDelay' ] && !X.UA.Opera, // Opera12(XP,8.1) 切った方がスムース\r
X_Node_Anime_transitionProps = X_Node_Anime_hasTransform ? X_Node_CSS_VENDER_PREFIX[ 'transform' ] : 'left,top';\r
\r
X_Node_Anime_reserved = true;\r
\r
if( X_Node_updateTimerID ){\r
- console.log( before ? '> BEFORE_UPDATE' : '> UPDATED' );\r
+ //console.log( before ? '> BEFORE_UPDATE' : '> UPDATED' );\r
X_System.listenOnce( before ? X.Event.BEFORE_UPDATE : X.Event.UPDATED, X_Node_Anime_updateAnimations );\r
} else {\r
- console.log( '> Timer' );\r
+ //console.log( '> Timer' );\r
// Opera12 requestAnimationFrame では transition が動かない、、、\r
X_Node_Anime_updateTimerID =\r
X_UA.Opera ?\r
function X_Node_Anime_updateAnimations( v ){\r
var i = X_Node_ANIMATIONS.length, ret, c = false;\r
\r
- console.log( v.type || v );\r
+ //console.log( v.type || v );\r
\r
//console.log( 'updateAnimations ' + i + ' ' + X_Node_Anime_needsDetection );\r
\r
\r
case 15 :\r
// GPU有効で停止(待機)している xnode の解除\r
- console.log( 'GPU有効で停止(待機)している xnode の解除' + xnode._tag + xnode.getOrder() );\r
+ //console.log( 'GPU有効で停止(待機)している xnode の解除' + xnode._tag + xnode.getOrder() );\r
X_Node_Anime_clearTransition( xnode );\r
X_Node_Anime_updatePosition( xnode, obj.destX, obj.destY, obj.destA, false );\r
obj.gpuTimerID && X.Timer.remove( obj.gpuTimerID );\r
return true;\r
\r
case 100 : // stop() : アニメーションの中断して削除\r
- console.log( 'stop() gpu:' + obj.gpuParent );\r
+ //console.log( 'stop() gpu:' + obj.gpuParent );\r
current = X_Node_Anime_getComputedPosition( xnode );\r
\r
X_Node_Anime_clearTransition( xnode );\r
this._anime.phase = 3;\r
X_Node_Anime_needsDetection = true;\r
X_Node_Anime_reserveUpdate();\r
- console.log( 'トランジション終了' );\r
+ //console.log( 'トランジション終了' );\r
return X.Callback.UN_LISTEN | X.Callback.PREVENT_DEFAULT | X.Callback.STOP_PROPAGATION;\r
};\r
\r
\r
_iwin : null,\r
\r
- _html : '',\r
+ _contentHTML : '',\r
_name : '',\r
_ready : false,\r
\r
this.xnodeIframe.css( { position : 'absolute' } );\r
};\r
\r
- if( html ) this._html = html;\r
+ if( html ) this._contentHTML = html;\r
},\r
\r
handleEvent : function( e ){\r
this.xnodeIframe.listen( [ X_UA.IE < 9 ? 'readystatechange' : 'load', 'error' ], this );\r
\r
if( !( X_UA.IE < 9 ) ){\r
- this._html && X_Util_NinjaIframe_writeToIframe( this );\r
+ this._contentHTML && X_Util_NinjaIframe_writeToIframe( this );\r
this._ready = true;\r
return;\r
};\r
if( ( raw.readyState !== 'complete' && raw.readyState !== 'loaded' ) ) return X.Callback.STOP_PROPAGATION;\r
// ie9-\r
if( !this._ready ){\r
- this._html && X_Util_NinjaIframe_writeToIframe( this );\r
+ this._contentHTML && X_Util_NinjaIframe_writeToIframe( this );\r
this._ready = true;\r
return;\r
};\r
return X.Callback.STOP_PROPAGATION; \r
},\r
\r
- refresh : function( opt_html ){\r
+ refresh : function( opt_contentHTML ){\r
var raw = this.xnodeIframe._rawObject,\r
idoc;\r
\r
this._ready = false;\r
\r
if( !this._iwin ){\r
- this._html = opt_html;\r
+ this._contentHTML = opt_html;\r
return this;\r
};\r
\r
\r
if( !opt_html ) return this;\r
\r
- this._html = opt_html;\r
+ this._contentHTML = opt_html;\r
X_UA.IE < 9 || X_Util_NinjaIframe_writeToIframe( this );\r
\r
return this;\r
function X_Util_NinjaIframe_writeToIframe( that ){\r
var raw = that.xnodeIframe._rawObject,\r
idoc = raw.contentDocument || that._iwin.document,\r
- html = that._html;\r
+ html = that._contentHTML;\r
\r
- delete that._html;\r
+ delete that._contentHTML;\r
that._ready = true;\r
\r
idoc.open();\r
_type : '',\r
_busy : false,\r
_canceled : false,\r
+ _error : false,\r
_percent : 0,\r
_timerID : 0,\r
\r
if( raw.timeout !== undefined ){\r
raw.timeout = timeout;\r
} else {\r
- //this._timerID = X.Timer.once( timeout, this, this.onTimeout );\r
+ this._timerID = X.Timer.once( timeout, this, this.onTimeout );\r
}; \r
\r
// send 前にフラグを立てる,回線が早いと raw.send() 内で onload -> _busy = false ののち、 _busy = true するため。\r
this._busy = true;\r
\r
\r
- //raw.send( postbody || '' );\r
- this._timerID = X.Timer.once( 16, this, this._lazySend, [ postbody || '', timeout ] );\r
+ raw.send( postbody || '' );\r
+ //this._timerID = X.Timer.once( 16, this, this._lazySend, [ postbody || '', timeout ] );\r
},\r
- \r
+ /*\r
// send() 内で onload するケースがあり、そのときはイベントリスナが間に合わないので、タイマーをかませる。\r
_lazySend : function( postbody, timeout ){\r
if( this._rawObject.timeout === undefined ){\r
// sendをonreadystatechangeの前に記述すると、ieでは動作しなくなります、、、。\r
// konquerorでエラーが発生するのでここでは、とりあえず、send('') としました。\r
this._rawObject.send( postbody ); \r
- },\r
+ }, */\r
\r
cancel : function(){\r
/* X.Net.XHR.CANCELABLE && */ this._rawObject.abort && this._rawObject.abort();\r
// domes.lingua.heliohost.org/dom-intro/load-save2.html\r
// 規定上は open() を呼び出すと XMLHttpRequest オブジェクトが未送信状態に戻りますが、\r
// Opera 10.10、Safari 4.1 では、同一オリジン制限に違反した XMLHttpRequest オブジェクトは再度 open() しても未送信状態に戻りません。\r
- if( X_UA.Opera || X_UA.Webkit ){\r
- \r
+ \r
+ // Timeout した Gecko の xhr.response に触るとエラー??\r
+ if( X_UA.Opera || X_UA.Webkit || X_UA.Gecko ){\r
+ if( this._error ){\r
+ X_EventDispatcher_toggleAllEvents( this, false );\r
+ this._rawObject = new XMLHttpRequest();\r
+ X_EventDispatcher_toggleAllEvents( this, true );\r
+ };\r
};\r
\r
// XMLHttpRequest の使い方\r
this._rawObject.abort && this._rawObject.abort();\r
\r
this._method = this._type = '';\r
- this._canceled = this._busy = false;\r
+ this._canceled = this._busy = this._error = false;\r
this._timerID && X.Timer.remove( this._timerID );\r
this._percent = this._timerID = 0;\r
},\r
case 'load' :\r
\r
if( !live ) return this.reset();\r
- if( this._percent === 100 ) return;\r
+ if( !this._busy ) return;\r
\r
\r
this._percent = 100;\r
break;\r
};\r
\r
- this.asyncDispatch( { type : X.Event.SUCCESS, status : status || 200, data : data } ); \r
+ this.asyncDispatch( 32, { type : X.Event.SUCCESS, status : status || 200, data : data } ); \r
} else {\r
- live && this.asyncDispatch( { type : X.Event.ERROR, status : raw.status || 0, percent : 100 } );\r
+ live && this.asyncDispatch( 32, { type : X.Event.ERROR, status : raw.status || 0, percent : 100 } );\r
};\r
break;\r
\r
\r
case 'error' :\r
//console.dir( e );\r
- this._busy = false;\r
- live && this.asyncDispatch( { type : X.Event.ERROR, status : raw.status } );\r
+ this._busy = false;\r
+ this._error = X_UA.Opera || X_UA.Webkit;\r
+ live && this.asyncDispatch( 32, { type : X.Event.ERROR, status : raw.status } );\r
break;\r
\r
case 'timeout' : // Gecko 12.0 https://developer.mozilla.org/ja/docs/XMLHttpRequest/Synchronous_and_Asynchronous_Requests\r
- this._busy = false;\r
+ this._busy = false;\r
+ this._error = !!X_UA.Gecko;\r
this.asyncDispatch( X.Event.TIMEOUT );\r
break;\r
};\r
switch( e.type ){\r
case 'support' :\r
proxy._backend = i;\r
- proxy.asyncDispatch( { type : 'backendfound', option : option, source : source, backendName : this.backendName } );\r
+ proxy.asyncDispatch( {\r
+ type : 'backendfound',\r
+ option : option,\r
+ source : source,\r
+ backendName : this.backendName\r
+ } );\r
break;\r
case 'nosupport' :\r
if( backend = X_Audio_BACKENDS[ i + 1 ] ){\r
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 ),
};
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' );
{
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
// Opera Mobile 12 android4.4.4 & 2.3.5 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する\r
X_Audio_HTMLAudioWrapper_currentTimeFix = !!X_UA.OperaMobile || !!X_UA.OperaTablet,\r
// 一方 Desktop の Opera12 は、loadeddata 等では duration が infinity で、再生後の durationchange 時に duration が判明する。\r
+ // opera12 volume, mute の変更が2度目以降できない\r
// duration 判明後には currentTime によるシークと、現在時間の取得が可能になる。\r
// canplay で play() durationchange で duration が取れたら loadedmetadata->loadeddata -> canplay する\r
// boombox.js に書いてあった currentTime の効かないブラウザってこいつのことみたい、、、\r
- X_Audio_HTMLAudioWrapper_currentTimeFix2 = !X_Audio_HTMLAudioWrapper_currentTimeFix && X_UA.Opera,\r
+ // Opera12.17 Win32(XP) portable apps は勝手に再生が始まる、、、その際には timeupdate が発行されない、、、 iframe+image+audio で使わないときは破棄する、とか。\r
+ // opera11、10.54 WinXP はまとも、、、\r
+ // X_Audio_Sprite_handleEvent でも使用\r
+ X_Audio_HTMLAudioWrapper_durationFix = !X_Audio_HTMLAudioWrapper_currentTimeFix && 12 < X_UA.Opera,\r
\r
- X_Audio_HTMLAudioWrapper_shortPlayFix = !!X_UA.AndroidBrowser4;\r
+ X_Audio_HTMLAudioWrapper_shortPlayFix = !!X_UA.AndroidBrowser4,\r
+ \r
+ X_Audio_codecs;\r
\r
\r
if( window.HTMLAudioElement ){\r
\r
+ X_Audio_rawAudio = new Audio;\r
+ \r
+ X_Audio_codecs = {\r
+ mp3 : X_Audio_rawAudio.canPlayType('audio/mpeg;'),\r
+ opus : X_Audio_rawAudio.canPlayType('audio/ogg; codecs="opus"'),\r
+ ogg : X_Audio_rawAudio.canPlayType('audio/ogg; codecs="vorbis"'),\r
+ wav : X_Audio_rawAudio.canPlayType('audio/wav; codecs="1"'),\r
+ aac : X_Audio_rawAudio.canPlayType('audio/aac;'),\r
+ m4a : (X_Audio_rawAudio.canPlayType('audio/x-m4a;') || X_Audio_rawAudio.canPlayType('audio/m4a;') || X_Audio_rawAudio.canPlayType('audio/aac;')),\r
+ mp4 : (X_Audio_rawAudio.canPlayType('audio/x-mp4;') || X_Audio_rawAudio.canPlayType('audio/mp4;') || X_Audio_rawAudio.canPlayType('audio/aac;')),\r
+ weba : X_Audio_rawAudio.canPlayType('audio/webm; codecs="vorbis"')\r
+ };\r
+ \r
+ (function( k, v ){\r
+ for( k in X_Audio_codecs ){\r
+ v = X_Audio_codecs[ k ];\r
+ X_Audio_codecs[ k ] = v && v !== 'no';\r
+ };\r
+ })();\r
+ \r
+ \r
X_Audio_HTMLAudioWrapper = X.EventDispatcher.inherits(\r
'X.AV.HTML5AudioWrapper',\r
X.Class.POOL_OBJECT,\r
autoplay : false,\r
volume : 0.5,\r
\r
- _timerID : 0,\r
_playTime : 0,\r
_closed : true,\r
_loaded : false,\r
- _playForDuration : false,\r
- _currentTimeFix : 0,\r
- _shortFix : 0,\r
+ _beginTime : 0,\r
+ _playForDuration : 0,\r
+ _src : '',\r
\r
Constructor : function( proxy, source, option ){\r
this.proxy = proxy;\r
//this._rawObject.load();\r
} else {\r
this._rawObject = X_Audio_rawAudio || new Audio( source );// X_Doc_create( 'audio', { src : source } ).appendToRoot();//( X.X_Node_systemNode );\r
+ this._rawObject.autobuffer = false;\r
+ this._src = source;\r
};\r
\r
this.listen( [\r
*/\r
handleEventProxy : function( e ){\r
var loaded;\r
- console.log( 'HTMLAudio ' + e.type );\r
+ console.log( 'HTMLAudio ' + e.type + ' ' + this._rawObject.currentTime );\r
\r
switch( e.type ){\r
case 'loadstart' : // ブラウザがコンテンツの検索を開始した場合に発生\r
break;\r
\r
case 'canplay' : // 今すぐに再生を再開できるが、バッファリングが不十分でコンテンツを最後まで表示できないと予測している場合に発生\r
- if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){\r
- console.log( 'play ' + this.duration );\r
- this._playForDuration = true;\r
- this._rawObject.currentTime = 0;\r
+ if( X_Audio_HTMLAudioWrapper_durationFix && this._playForDuration === 0 ){\r
+ console.log( 'start DurationFix for Desktop Opera12 - ' + this._rawObject.duration );\r
+ this._playForDuration = 1;\r
+ //this._rawObject.currentTime = 0;\r
this._rawObject.play();\r
- this._rawObject.currentTime = 0;\r
+ this._rawObject.currentTime = this._beginTime / 1000; // 必要!\r
+ return;\r
};\r
case 'loadedmetadata' : // ブラウザがメディアリソースの長さと寸法を判定した場合に発生\r
case 'loadeddata' : // コンテンツの表示を現在の再生位置で初めて行えるようになった場合に発生\r
case 'canplaythrough' : // 今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生\r
- if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ) return;\r
+ if( X_Audio_HTMLAudioWrapper_durationFix && this._playForDuration !== 2 ) return;\r
this.duration = this._rawObject.duration * 1000;\r
console.log( this.duration );\r
break;\r
case 'seeked' : // シークがfalseに変化した場合に発生\r
case 'ratechange' : // defaultPlaybackRate属性とplaybackRate属性のどちらかが更新された場合に発生\r
case 'volumechange' : // volume属性とmuted属性のどちらかが変化した場合に発生\r
- if( this._playForDuration ) return;\r
+ if( this._playForDuration === 1 ) return;\r
break;\r
\r
case 'timeupdate' : // 通常の再生が行われ現在の再生位置の変化が起こった場合に発生\r
- // console.log( this._rawObject.currentTime );\r
- if( this._playForDuration ) return; \r
+ console.log( this._rawObject.currentTime );\r
+ if( this._playForDuration === 1 ){\r
+ this._rawObject.currentTime = this._beginTime / 1000; // 必要!\r
+ return;\r
+ }; \r
this._onEnded();\r
break;\r
\r
case 'ended' :\r
- if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){\r
- delete this._currentTimeFix;\r
- };\r
if( !this._closed && this.loop ){\r
this.looped = true;\r
( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play();\r
} else {\r
- this._timerID && X.Timer.remove( this._timerID );\r
this.seekTime = 0;\r
- delete this._timerID;\r
delete this.playing;\r
};\r
break;\r
\r
case 'durationchange' : // duration属性が更新された場合に発生\r
- this.duration = this._rawObject.duration * 1000;\r
- // console.log( this._rawObject.duration );\r
\r
- if( this._playForDuration ){\r
- this._rawObject.pause();\r
- this._rawObject.currentTime = 0.001;\r
- delete this._playForDuration;\r
+ if( !X_Audio_HTMLAudioWrapper_durationFix ){\r
+ this.duration = this._rawObject.duration * 1000;\r
+ } else\r
+ // Desktop Opera\r
+ if( this._rawObject.duration !== 1 / 0 ){\r
+ \r
+ console.log( this._rawObject.duration );\r
+ \r
+ this.duration = this._rawObject.duration * 1000;\r
+ \r
+ if( this._playForDuration === 0 ) this._playForDuration = 2;\r
+ \r
+ if( this._playForDuration === 1 ){\r
+ this._playForDuration = 2;\r
+ \r
+ console.log( 'Loaded ' + this._loaded );\r
+ \r
+ if( this._loaded ){\r
+ this._rawObject.currentTime = this._beginTime / 1000;\r
+ console.log( '設定 ' + this._beginTime );\r
+ return;\r
+ };\r
+ \r
+ this.proxy.asyncDispatch( 'loadedmetadata' );\r
+ this.proxy.asyncDispatch( 'loadeddata' );\r
+ this.proxy.asyncDispatch( 'canplay' );\r
+ this.proxy.asyncDispatch( 'canplaythrough' );\r
+ loaded = true;\r
+ console.log( 'Desktop Opera のための currentTime と duration の fix が完了' + this.duration );\r
+ \r
+ if( this.autoplay ){\r
+ this._rawObject.currentTime = this._beginTime / 1000; \r
+ } else {\r
+ // Opera12.17 WinXP で勝手に再生される不具合\r
+ // これで一応再生は止まる、、、\r
+ this._rawObject.src = '';\r
+ //this._rawObject.load(); \r
+ };\r
+ };\r
\r
- this.proxy.asyncDispatch( 'loadedmetadata' );\r
- this.proxy.asyncDispatch( 'loadeddata' );\r
- this.proxy.asyncDispatch( 'canplay' );\r
- this.proxy.asyncDispatch( 'canplaythrough' );\r
- loaded = true;\r
- console.log( 'DEsktop Opera のための currentTime と duration の fix が完了' + this.duration );\r
- };\r
- if( this._currentTimeFix === 1 ){\r
- this._currentTimeFix++;\r
- this._rawObject.currentTime = this._beginTime / 1000;\r
- return;\r
};\r
break;\r
\r
\r
end = X_AudioWrapper_getEndTime( this );\r
begin = X_AudioWrapper_getStartTime( this, end, true );\r
- \r
\r
if( X_Audio_HTMLAudioWrapper_shortPlayFix ){\r
begin -= end - begin > 1000 ? 200 : 400;\r
begin = begin < 0 ? 0 : begin;\r
- }; \r
- \r
- this._rawObject.currentTime = begin / 1000;\r
-\r
+ };\r
\r
- if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){\r
- //this._currentTimeFix++;\r
+ if( !this._rawObject.src ){\r
this._beginTime = begin;\r
+ this._rawObject.src = this._src;\r
+ delete this._playForDuration;\r
};\r
\r
+ this._rawObject.currentTime = begin / 1000;\r
+\r
console.log( '[HTMLAudio] play ' + begin + ' -> ' + end );\r
\r
if( !this.playing ){\r
};\r
\r
if( X_Audio_HTMLAudioWrapper_currentTimeFix ){\r
- //this._timerID && X.Timer.remove( this._timerID );\r
this._beginTime = begin;\r
- this._playTime = X_Timer_now();\r
- \r
- if( end < this.duration ){\r
- //this._timerID = X.Timer.once( end - begin, this, this._onEnded );\r
- } else {\r
- delete this._timerID;\r
- }; \r
+ this._playTime = X_Timer_now(); \r
};\r
\r
},\r
_onEnded : function(){\r
var currentTime, time;\r
\r
- delete this._timerID;\r
- \r
if( this.playing ){\r
currentTime = X_Audio_HTMLAudioWrapper_currentTimeFix ? X_Timer_now() - this._playTime + this._beginTime : this._rawObject.currentTime * 1000 | 0;\r
time = currentTime - X_AudioWrapper_getEndTime( this );\r
\r
- if( X_Audio_HTMLAudioWrapper_shortPlayFix ){\r
- //time -= this._shortFix;\r
- };\r
-\r
if( time < 0 ){\r
console.log( '> onEnd ' + (-time) + ' ' + currentTime + '/' + ( X_AudioWrapper_getEndTime( this ) ) );\r
- //if( X_Audio_HTMLAudioWrapper_currentTimeFix ) this._timerID = X.Timer.once( -time, this, this._onEnded );\r
return;\r
};\r
\r
if( this.loop ){\r
- this.looped = true;\r
- ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play();\r
+ if( !( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) ){\r
+ this.looped = true;\r
+ this.play();\r
+ };\r
} else {\r
this.pause();\r
- this.dispatch( 'ended' );\r
+ this.proxy.dispatch( 'ended' );\r
};\r
};\r
},\r
if( !this.playing ) return;\r
\r
this.seekTime = this.state().currentTime;\r
- \r
- if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){\r
- delete this._currentTimeFix;\r
- };\r
- \r
- //this._timerID && X.Timer.remove( this._timerID );\r
- //delete this._timerID;\r
+\r
delete this._playTime;\r
\r
!this._rawObject.error && this._rawObject.pause();\r
* - FireFox3.6, Android 2.3.6については、src変更後、load()を呼び出さないと切り替わらなかった。iPhoneはload()が不要。\r
*/ \r
detect : function( proxy, source, ext ){\r
+ /*\r
var ok, mineType = 'audio/' + ext;\r
switch( ext ){\r
case 'mp3' :\r
ok = X_Audio_rawAudio.canPlayType( mineType );\r
};\r
\r
- proxy.asyncDispatch( ok ? 'support' : 'nosupport' );\r
+ proxy.asyncDispatch( ok ? 'support' : 'nosupport' ); */\r
+ \r
+ proxy.asyncDispatch( X_Audio_codecs[ ext ] ? 'support' : 'nosupport' );\r
},\r
\r
klass : X_Audio_HTMLAudioWrapper\r
};\r
\r
if( this.loop ){\r
- this.looped = true;\r
- ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play();\r
+ if( !( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) ){\r
+ this.looped = true;\r
+ this.play();\r
+ };\r
} else {\r
this.pause();\r
- this.proxy.dispatch( 'ended' ); \r
+ this.proxy.dispatch( 'ended' );\r
};\r
};\r
},\r
*/\r
var X_Audio_Sprite_shouldUse = window.HTMLAudioElement && ( X_UA.iOS || X_UA.AndroidBrowser || X_UA.OperaMobile || X_UA.OperaTablet ),\r
X_Audio_Sprite_useVideoForMulti = 4 <= X_UA.AndroidBrowser && 534.3 < X_UA.AndroidBrowserWebkit, // ドスパラパッドはビデオのインライン再生が不可 \r
+ X_Audio_Sprite_needTouchAndroid = X_Audio_Sprite_useVideoForMulti, \r
X_Audio_Sprite_needTouchFirst = !!X_UA.iOS || X_Audio_Sprite_useVideoForMulti,\r
- X_Audio_Sprite_inTouchAction = false,\r
X_Audio_Sprite_enableMultiTrack = !( X_UA.iOS && !X_Audio_WebAudio_context ) && !( X_UA.AndroidBrowser4 && X_UA.AndroidBrowserWebkit <= 534.3 ),\r
X_Audio_Sprite_enableVolume = window.HTMLAudioElement && ( !X_UA.iOS && !X_UA.AndroidBrowser && !X_UA.OperaMobile && !X_UA.OperaTablet ),\r
X_Audio_Sprite_maxTracks = !X_Audio_Sprite_enableMultiTrack ? 1 : X_Audio_Sprite_useVideoForMulti ? 2 : 9,\r
};\r
\r
function X_Audio_Sprite_handleEvent( e ){\r
- var i, tracks, track;\r
+ var i, tracks, track, _e;\r
switch( e.type ){\r
case 'backendfound' :\r
- this.asyncDispatch( e );\r
+ _e = {\r
+ type : e.type,\r
+ source : e.source,\r
+ backendName : e.backendName\r
+ };\r
+ \r
+ if( X_Audio_Sprite_needTouchFirst ){\r
+ if( e.backendName === 'Web Audio' ){\r
+ _e[ 'needTouchForPlay' ] = true;\r
+ } else {\r
+ _e[ 'needTouchForLoad' ] = true;\r
+ };\r
+ };\r
+ this.asyncDispatch( _e );\r
+ \r
e.target.unlisten( 'nobackend', this, X_Audio_Sprite_handleEvent );\r
\r
if( e.backendName === 'HTML Audio' ){\r
- e.target.listenOnce( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata' ], this, X_Audio_Sprite_handleEvent );\r
+ // Android 4.4.4 Y!Browser でたまにロードを検出できていない?問題を解決できないかな? -> , 'canplaythrough'\r
+ // タッチイベント内でloadを開始。ロード完了したら無音の再生を実施。timeupdate が返ったらいつでも再生が出来る状態になる。\r
+ e.target.listenOnce( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata', 'canplaythrough' ], this, X_Audio_Sprite_handleEvent );\r
} else {\r
e.target.listenOnce( 'canplaythrough', this, X_Audio_Sprite_handleEvent );\r
};\r
+ // READY, needTouchForPlay, needTouchForLoad\r
+ if( X_Audio_HTMLAudioWrapper_durationFix ){\r
+ for( i = 0; i < X_Audio_Sprite_TEMP.tracks.length; ++i ){\r
+ X_Audio_Sprite_instance.pause( i );\r
+ };\r
+ };\r
break;\r
\r
case 'nobackend' :\r
case 'loadeddata' :\r
e.target.unlisten( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata', 'canplaythrough' ], this, X_Audio_Sprite_handleEvent );\r
\r
- if( X_Audio_Sprite_useVideoForMulti ){\r
+ if( X_Audio_Sprite_needTouchAndroid ){\r
for( i = 0; i < X_Audio_Sprite_TEMP.tracks.length; ++i ){\r
X_Audio_Sprite_instance.pause( i );\r
};\r
if( e.target === X_Audio_Sprite_TEMP.bgmTrack ){\r
X_Audio_Sprite_TEMP.bgmLooped = true;\r
} else {\r
+ e.target.state().looped || this.asyncDispatch( 'ended' ); // uid\r
+ \r
// single track | iOS\r
if( X_Audio_Sprite_TEMP.bgmPlaying && !X_Audio_Sprite_TEMP.bgmTrack ){\r
X_Audio_Sprite_TEMP.bgmTrack = e.target;\r