From 241005e2a5f9f8a7fddd6f610b76a915e9c05d30 Mon Sep 17 00:00:00 2001 From: itozyun Date: Mon, 19 Oct 2015 22:19:54 +0900 Subject: [PATCH] Version 0.6.180, fix X.Audio. --- 0.6.x/js/01_core/02_XUA.js | 82 +++++++++++++++---------------- 0.6.x/js/01_core/14_XEvent.js | 8 +-- 0.6.x/js/01_core/15_XEventDispatcher.js | 64 ++++++++++++++---------- 0.6.x/js/02_dom/03_XDomEvent.js | 7 ++- 0.6.x/js/07_audio/01_XWebAudio.js | 2 +- 0.6.x/js/07_audio/02_XHTMLAudio.js | 59 ++++++++++++---------- 0.6.x/js/07_audio/03_XSilverlightAudio.js | 2 +- 0.6.x/js/07_audio/10_XAudioSprite.js | 51 +++++++++++-------- 8 files changed, 154 insertions(+), 121 deletions(-) diff --git a/0.6.x/js/01_core/02_XUA.js b/0.6.x/js/01_core/02_XUA.js index c639e70..ec338a8 100644 --- a/0.6.x/js/01_core/02_XUA.js +++ b/0.6.x/js/01_core/02_XUA.js @@ -264,8 +264,13 @@ var X_UA = X[ 'UA' ] = {}, console.log( '>> Android : ' + X_UA[ 'Android' ] ); } else if( dua.indexOf( 'Android;' ) !== -1 ){ - // Fennec 用 - X_UA[ 'Android' ] = 2; + // Fennec41- 用 + // https://developer.mozilla.org/ja/docs/Gecko_user_agent_string_reference + // バージョン 41 以降の Android 版 Firefox では platform トークンに Android バージョンが含まれます。 + // 相互運用性向上のため、Android 4 以前のバージョンでブラウザが動作している場合は 4.4 と出力します。 + // Android バージョン 4 以降では実際のバージョン番号が出力されます。 + // なお、Gecko エンジンはすべての Android バージョンに対して同じ機能を提供しています。 + X_UA[ 'Android' ] = 2.2; }; }; @@ -318,8 +323,7 @@ var X_UA = X[ 'UA' ] = {}, */ X_UA[ 'NDS' ] = dua.indexOf( 'Nitro' ) !== -1; console.log( '>> Opera : ' + v ); - return; - }; + } else // Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko if( document.all || dav.indexOf( 'Trident/' ) !== -1 ){ @@ -457,8 +461,7 @@ var X_UA = X[ 'UA' ] = {}, console.log( '>> IE : ' + v + ' ActiveX : ' + X_UA[ 'ActiveX' ] + ' IEHost : ' + X_UA[ 'IEHost' ] ); // TODO XBox360, XBox1, Modern or Desktop, Standalone - return; - }; + } else // if( ( i = dua.indexOf( 'NetFront\/' ) !== -1 ) ){ @@ -469,14 +472,12 @@ var X_UA = X[ 'UA' ] = {}, */ X_UA[ 'NetFront' ] = parseFloat( dua.substr( i + 9 ) ) || 0.1; console.log( '>> NetFront : ' + X_UA[ 'NetFront' ] ); - return; - }; + } else if( X_UA[ 'Linux' ] && tv === 2 && dua.indexOf( 'Sony\/COM2\/' ) !== -1 ){ X_UA[ 'NetFront' ] = 3.4; console.log( '>> NetFront : ' + X_UA[ 'NetFront' ] ); - return; - }; + } else if( ( i = dua.toUpperCase().indexOf( 'PLAYSTATION 3' ) !== -1 ) ){ /** @@ -491,8 +492,7 @@ var X_UA = X[ 'UA' ] = {}, */ X_UA[ 'PS3' ] = parseFloat( dua.substr( i + 15 ) ) || 0.1; console.log( '>> PS3 : ' + X_UA[ 'PS3' ] ); - return; - }; + } else if( ( i = dua.indexOf( 'iCab' ) !== -1 ) ){ /** @@ -504,8 +504,7 @@ var X_UA = X[ 'UA' ] = {}, */ X_UA[ 'iCab' ] = parseFloat( dua.substr( i + 5 ) ) || 0.1; console.log( '>> iCab : ' + X_UA[ 'iCab' ] ); - return; - }; + } else if( 0 < dua.indexOf( 'Gecko\/' ) && ( i = dua.indexOf( 'rv:' ) ) ){ v = dua.substr( i + 3 ).split( '.' ); @@ -515,8 +514,7 @@ var X_UA = X[ 'UA' ] = {}, * @type {number} */ X_UA[ 'Gecko' ] = parseFloat( v[ 0 ] ) || 0 + - ( parseFloat( v[ 1 ] ) || 0 ) / 10 + - ( parseFloat( v[ 2 ] ) || 0 ) / 100; + ( parseFloat( v[ 1 ] ) || 0 ) / 10; /** * @alias X.UA.GeckoMajor * @type {number} @@ -542,8 +540,10 @@ var X_UA = X[ 'UA' ] = {}, */ X_UA[ 'Fennec' ] = parseFloat( dua.substr( i + 7 ) ); console.log( '>> Fennec : ' + X_UA[ 'Fennec' ] + ', Gecko : ' + X_UA[ 'Gecko' ] ); - return; - }; + } else + if( X_UA[ 'Android' ] ){ + X_UA[ 'Fennec' ] = X_UA[ 'Gecko' ]; + } else //Firefox //Netscape @@ -560,20 +560,17 @@ var X_UA = X[ 'UA' ] = {}, */ X_UA[ 'NN6' ] = true; console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] ); - return; } else //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax) //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3 if( ( i = dua.indexOf( 'Netscape/' ) ) !== -1 ){ X_UA[ 'NN' ] = parseFloat( dua.substr( i + 9 ) ) || 7; console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] ); - return; } else //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6 if( ( i = dua.indexOf( 'Navigator/' ) ) !== -1 ){ X_UA[ 'NN' ] = parseFloat( dua.substr( i + 10 ) ) || 9; console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] ); - return; }; console.log( '>> Gecko : ' + X_UA[ 'Gecko' ] ); @@ -687,31 +684,32 @@ var X_UA = X[ 'UA' ] = {}, }; console.log( '>> Webkit : ' + X_UA[ 'WebKit' ] + ' Safari : ' + X_UA[ 'Safari' ] ); - }; - - if( dua.toLowerCase().indexOf( 'iris' ) !== -1 ){ - /** - * http://www.useragentstring.com/pages/Iris/ - * @alias X.UA.Iris - * @type {boolean} - */ - X_UA[ 'Iris' ] = true; - }; - - if( // Kobo Mozilla/5.0 (Linux; U; Android 2.0; en-us;) AppleWebKit/533.1 (KHTML, like Gecko) Verson/4.0 Mobile Safari/533.1 (Kobo Touch) - dua.indexOf( 'Kobo' ) !== -1 || - // Kindle paperwhite Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+ - dua.indexOf( 'Kindle' ) !== -1 || - // Sony Reader Mozilla/5.0 (Linux; U; ja-jp; EBRD1101; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 - dua.indexOf( 'EBRD' ) !== -1 - ){ + + if( dua.toLowerCase().indexOf( 'iris' ) !== -1 ){ /** - * Kobo, Kindle, Sony Reader - * @alias X.UA.EInk + * http://www.useragentstring.com/pages/Iris/ + * @alias X.UA.Iris * @type {boolean} */ - X_UA[ 'EInk' ] = true; + X_UA[ 'Iris' ] = true; }; + + if( // Kobo Mozilla/5.0 (Linux; U; Android 2.0; en-us;) AppleWebKit/533.1 (KHTML, like Gecko) Verson/4.0 Mobile Safari/533.1 (Kobo Touch) + dua.indexOf( 'Kobo' ) !== -1 || + // Kindle paperwhite Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+ + dua.indexOf( 'Kindle' ) !== -1 || + // Sony Reader Mozilla/5.0 (Linux; U; ja-jp; EBRD1101; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 + dua.indexOf( 'EBRD' ) !== -1 + ){ + /** + * Kobo, Kindle, Sony Reader + * @alias X.UA.EInk + * @type {boolean} + */ + X_UA[ 'EInk' ] = true; + }; + }; + })(); (function(){ diff --git a/0.6.x/js/01_core/14_XEvent.js b/0.6.x/js/01_core/14_XEvent.js index 0741a18..0c52605 100644 --- a/0.6.x/js/01_core/14_XEvent.js +++ b/0.6.x/js/01_core/14_XEvent.js @@ -107,12 +107,13 @@ var // 内部イベント X_EVENT_MEDIA_ENDED = 46, X_EVENT_MEDIA_WAITING = 47, X_EVENT_MEDIA_SEEKING = 48, + X_EVENT_MEDIA_CAN_TOUCH_LOAD = 49, - X_EVENT_NEED_AUTH = 49, + X_EVENT_NEED_AUTH = 50, - X_EVENT_DEBUG = 50, + X_EVENT_DEBUG = 51, - X_Event_last = 50; + X_Event_last = 51; // in_page_jump // on_screen_keyboard_show @@ -222,6 +223,7 @@ X[ 'Event' ] = /** @lends X.Event */ 'MEDIA_ENDED' : X_EVENT_MEDIA_ENDED, 'MEDIA_WAITING' : X_EVENT_MEDIA_WAITING, 'MEDIA_SEEKING' : X_EVENT_MEDIA_SEEKING, + 'MEDIA_CAN_TOUCH_LOAD' : X_EVENT_MEDIA_CAN_TOUCH_LOAD, 'NEED_AUTH' : X_EVENT_NEED_AUTH, diff --git a/0.6.x/js/01_core/15_XEventDispatcher.js b/0.6.x/js/01_core/15_XEventDispatcher.js index d6140a4..34a5933 100644 --- a/0.6.x/js/01_core/15_XEventDispatcher.js +++ b/0.6.x/js/01_core/15_XEventDispatcher.js @@ -36,22 +36,30 @@ var X_LISTENERS_ACTUAL_HANDLER = 0, // ------------------------------------------------------------------------- // // ------------ local variables -------------------------------------------- // // ------------------------------------------------------------------------- // - -var X_EventDispatcher_once = false, - X_EventDispatcher_lock = false, - X_EventDispatcher_unlock = false, - X_EventDispatcher_needsIndex = false, - - X_EventDispatcher_safariPreventDefault = false, // Safari3- - - /** @const */ +var /** @const */ X_EventDispatcher_EVENT_TARGET_OTHER = 0, /** @const */ X_EventDispatcher_EVENT_TARGET_XHR = 1, /** @const */ - X_EventDispatcher_EVENT_TARGET_SILVER_LIGHT = 2, + X_EventDispatcher_EVENT_TARGET_SILVER_LIGHT = 2; + +var X_EventDispatcher_once = false, + X_EventDispatcher_lock = false, + X_EventDispatcher_unlock = false, + X_EventDispatcher_needsIndex = false, - X_EventDispatcher_LAZY_TIMERS = {}; // Object. number は timerID + X_EventDispatcher_safariPreventDefault = false, // Safari3- + + X_EventDispatcher_LAZY_TIMERS = {},// Object. number は timerID + + // iOS と MacOSX Iron36 で発生。連続してアニメーションが起こると、クロージャの束縛された obj へのアクセスに失敗する。Win では起きない? + // むしろ、MacOSX のブラウザ全般で起こる?? + X_EventDispatcher_ANIME_EVENTS = ( X_UA[ 'WebKit' ] || X_UA[ 'Blink' ] ) && { + 'transitionend' : true, 'webkitTransitionEnd' : true, 'mozTransitionEnd' : true, 'oTransitionEnd' : true, 'otransitionEnd' : true, + 'animationend' : true, 'webkitAnimationEnd' : true, 'oAnimationEnd' : true, + 'animationstart' : true, 'webkitAnimationStart' : true, 'oAnimationStart' : true, + 'animationiteration' : true, 'webkitAnimationIteration' : true, 'oAnimationIteration' : true + }; // ------------------------------------------------------------------------- // // --- interface ----------------------------------------------------------- // @@ -524,6 +532,7 @@ function X_EventDispatcher_unlistenAll( that ){ function X_EventDispatcher_actualAddEvent( that, type, raw, list ){ var i, f; + X_EventDispatcher_lock || ( type = X_Event_Rename[ type ] || type ); if( X_Type_isArray( type ) ){ @@ -552,13 +561,7 @@ function X_EventDispatcher_actualAddEvent( that, type, raw, list ){ }; default : - // iOS と MacOSX Iron36 で発生。連続してアニメーションが起こると、クロージャの束縛された obj へのアクセスに失敗する。Win では起きない? - // むしろ、MacOSX のブラウザ全般で起こる?? - if( ( X_UA[ 'WebKit' ] || X_UA[ 'Blink' ] ) && - ( type === 'webkitTransitionEnd' || type === 'transitionend' || - type === 'animationend' || type === 'webkitAnimationEnd' || - type === 'animationstart' || type === 'webkitAnimationStart' || - type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){ + if( X_EventDispatcher_ANIME_EVENTS && X_EventDispatcher_ANIME_EVENTS[ type ] ){ raw.addEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false ); } else { f = that[ '_listeners' ][ X_LISTENERS_ACTUAL_HANDLER ] || ( that[ '_listeners' ][ X_LISTENERS_ACTUAL_HANDLER ] = X_Closure_create( that, X_EventDispatcher_actualHandleEvent ) ); @@ -637,6 +640,7 @@ function X_EventDispatcher_sliverLightDispatch( sender, e, type ){ function X_EventDispatcher_actualRemoveEvent( that, type, raw, list, skip ){ var i; + X_EventDispatcher_unlock || ( type = X_Event_Rename[ type ] || type ); if( X_Type_isArray( type ) ){ @@ -662,13 +666,9 @@ function X_EventDispatcher_actualRemoveEvent( that, type, raw, list, skip ){ }; default : - if( ( X_UA[ 'WebKit' ] || X_UA[ 'Blink' ] ) && - ( type === 'webkitTransitionEnd' || type === 'transitionend' || - type === 'animationend' || type === 'webkitAnimationEnd' || - type === 'animationstart' || type === 'webkitAnimationStart' || - type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){ + if( X_EventDispatcher_ANIME_EVENTS && X_EventDispatcher_ANIME_EVENTS[ type ] ){ raw.removeEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false ); - } else + } else if( raw.addEventListener ){ raw.removeEventListener( type, that[ '_listeners' ][ X_LISTENERS_ACTUAL_HANDLER ], false ); } else { @@ -741,6 +741,7 @@ function X_EventDispatcher_actualRemoveEvent( that, type, raw, list, skip ){ // TODO ブラウザからの呼び出しの最後に登録された関数を呼び出す機能(例えば画面の更新) +var X_EventDispatcher_CURRENT_EVENTS = []; // handleEvent を拡張可能にするために、クロージャに移動した // Is this in regard to the Safari 1.x preventDefault bug on click/dblclick? @@ -748,9 +749,14 @@ function X_EventDispatcher_actualRemoveEvent( that, type, raw, list, skip ){ var X_EventDispatcher_actualHandleEvent = X_UA_EVENT.IE4 || X_UA_EVENT.IE ? // ie45678 EVENT_IE & EVENT_DOM0 for ie4 (function(){ - var e = event, ret; + var e = event, ret, + ev = new X_DomEvent( e, this, this[ '_rawObject' ] ); + + X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length ] = ev; - ret = this[ 'dispatch' ]( new X_DomEvent( e, this, this[ '_rawObject' ] ) ); + ret = this[ 'dispatch' ]( ev ); + + --X_EventDispatcher_CURRENT_EVENTS.length; if( ret & X_CALLBACK_STOP_PROPAGATION ){ e.cancelBubble = true; @@ -765,7 +771,9 @@ var X_EventDispatcher_actualHandleEvent = var ev = new X_DomEvent( e, this ), ret = X_CALLBACK_NONE, i, l; - //console.log( '>>>>>>>>>> ' + e.type ); + + X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length ] = ev; + // touch event -> pointer if( X_Type_isArray( ev ) ){ if( ev.length === 0 ){ @@ -781,6 +789,8 @@ var X_EventDispatcher_actualHandleEvent = ret = this[ 'dispatch' ]( ev ); }; + --X_EventDispatcher_CURRENT_EVENTS.length; + if( ret & X_CALLBACK_STOP_PROPAGATION ){ e.stopPropagation(); }; diff --git a/0.6.x/js/02_dom/03_XDomEvent.js b/0.6.x/js/02_dom/03_XDomEvent.js index 391cdb9..98d86f0 100644 --- a/0.6.x/js/02_dom/03_XDomEvent.js +++ b/0.6.x/js/02_dom/03_XDomEvent.js @@ -12,7 +12,9 @@ // http://msdn.microsoft.com/ja-jp/library/ie/dn255104%28v=vs.85%29.aspx var X_Dom_Event_devicePixelRatio = window.devicePixelRatio || ( window.screen.deviceXDPI / window.screen.logicalXDPI ), - X_Dom_Event_convertMSPointerType = window.MSPointerEvent && [ 0, 0, 'touch', 'pen', 'mouse' ],/*{ + + X_Dom_Event_convertMSPointerType = ( !window.PointerEvent && window.MSPointerEvent ) && [ 0, 0, 'touch', 'pen', 'mouse' ], // WP8.1 は PointerEvent と MSPointerEvent 両方ある + /*{ '2' : 'touch', '3' : 'pen', '4' : 'mouse' @@ -62,7 +64,7 @@ if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ this[ 'pressure' ] = e.pressure || ( e.button !== -1 ? 0.5 : 0 ); // ポインターの接触形状の スクリーン ピクセル単位の幅と高さ なので変換。(多分、、、) this[ 'width' ] = e.width / X_Dom_Event_devicePixelRatio; - this[ 'height' ] = e.height / X_Dom_Event_devicePixelRatio; + this[ 'height' ] = e.height / X_Dom_Event_devicePixelRatio; } else { this[ 'pointerType' ] = e.pointerType; this[ 'pressure' ] = e.pressure; @@ -320,6 +322,7 @@ if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ if( type = X_Event_toPointer[ originalType ] ){ this[ 'type' ] = type; + this[ 'pointerType' ] = 'mouse'; this[ 'clientX' ] = e.clientX; this[ 'clientY' ] = e.clientY; //this[ 'screenX' ] = e.screenX; diff --git a/0.6.x/js/07_audio/01_XWebAudio.js b/0.6.x/js/07_audio/01_XWebAudio.js index 8e06469..c9fa1ed 100644 --- a/0.6.x/js/07_audio/01_XWebAudio.js +++ b/0.6.x/js/07_audio/01_XWebAudio.js @@ -80,7 +80,7 @@ if( X_Audio_constructor ){ var X_WebAudio_context = !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] && // Android2 + Gecko で WebAudio が極めて不安定 - !( X_UA[ 'Gecko' ] && X_UA[ 'Android' ] ) && + !X_UA[ 'Fennec' ] && // Firefox40.0.5 + Windows8 で音声が途中から鳴らなくなる // Firefox41.0.1 + Windows8 で音声が途中から鳴らなくなる !( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 42 && X_UA[ 'Windows' ] ) && diff --git a/0.6.x/js/07_audio/02_XHTMLAudio.js b/0.6.x/js/07_audio/02_XHTMLAudio.js index 61f3ddd..10a5bfd 100644 --- a/0.6.x/js/07_audio/02_XHTMLAudio.js +++ b/0.6.x/js/07_audio/02_XHTMLAudio.js @@ -16,8 +16,7 @@ * * memo * 1. AOSP4.1 iframe 内の Audio は親に focus が移っても再生を継続する - * 2. AOSP4.2(Genymotion) どこかのタイミングでタッチによる play を行う - * 3. AOSP oggはシークが乱れる m4a, mp3 は優秀 + * 2. AOSP oggはシークが乱れる m4a, mp3 は優秀 */ /* * durationFix @@ -35,18 +34,7 @@ * -> opera11、10.54 WinXP はまとも、、、 portable が怪しい?? */ -var X_HTMLAudio_playTrigger = - X_UA[ 'iOS' ] < 5 ? 'stalled' : - X_UA[ 'iOS' ] < 6 ? 'suspend' : - X_UA[ 'iOS' ] < 7 ? 'suspend' : - X_UA[ 'iOS' ] ? 'loadeddata' : - X_UA[ 'Safari' ] < 4 ? 'canplaythrough' : - X_UA[ 'ChromeWV' ] ? 'canplaythrough' : - // Android 2.3.5(SBM101SH) では stalled は発生しない,,, ので必ず loadeddata もチェックする - //X_UA[ 'AOSP' ] < 3 ? 'stalled' : - //X_UA[ 'AOSP' ] ? 'playing' : - X_UA[ 'OperaMobile' ] || X_UA[ 'OperaTablet' ] ? 'loadeddata' : - 'loadeddata', //'canplay', +var X_HTMLAudio, // ended が発生しない timeupdate 内で play() を呼ぶ (未検証) 不具合確認は iOS4,6 @@ -58,7 +46,7 @@ var X_HTMLAudio_playTrigger = // ended 時に play() を実施, currentTime が duration に張り付き更新されなければ src='';src=src を実施。 X_HTMLAudio_endedFixAOSP4 = 4 <= X_UA[ 'AOSP' ], // ended 時に play() を実施 - X_HTMLAudio_endedFixCWV = X_UA[ 'ChromeWV' ], + X_HTMLAudio_endedFixCWV = X_UA[ 'ChromeWV' ] || ( X_UA[ 'Blink' ] && X_UA[ 'Android' ] ), // Opera Mobile 12 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する X_HTMLAudio_currentTimeFix = !!X_UA[ 'OperaMobile' ] || !!X_UA[ 'OperaTablet' ], @@ -73,12 +61,13 @@ var X_HTMLAudio_playTrigger = // X_HTMLAudio_pauseFix = ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] && 0 < ' XP XPSP2 2003|XP64'.indexOf( X_UA[ 'Windows' ] ) ), // XP + Opera12 のみ? - X_HTMLAudio_need1stTouch = X_UA[ 'iOS' ] || 4 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || X_UA[ 'WinPhone' ], - X_HTMLAudio_durationFix = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ), + X_HTMLAudio_need1stTouch = X_UA[ 'iOS' ] || 4 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || X_UA[ 'WinPhone' ] || ( X_UA[ 'Blink' ] && X_UA[ 'Android' ] ), - X_HTMLAudio_shortPlayFix = X_UA[ 'AOSP' ]; // Android 4.1.1 でも遭遇 + X_HTMLAudio_playTrigger = ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ? 'canplay' : X_UA[ 'iOS' ] ? 'suspend' : X_UA[ 'Blink' ] ? 'stalled' : 'canplaythrough', + X_HTMLAudio_durationFix = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ), + X_HTMLAudio_shortPlayFix = X_UA[ 'AOSP' ]; // Android 4.1.1 でも遭遇 if( X_Audio_constructor ){ @@ -91,6 +80,9 @@ if( X_Audio_constructor ){ _ready : false, _src : '', + _touchRequested : false, + _touched : false, + _currentFixStart : 0, _currentFixBegin : 0, @@ -176,7 +168,7 @@ if( X_Audio_constructor ){ var raw = this[ '_rawObject' ], actualEnded = e.type === 'ended', ended = actualEnded, - ready = e.type === X_HTMLAudio_playTrigger, + ready, eventType, duration, end, now; // global に公開 @@ -210,6 +202,7 @@ if( X_Audio_constructor ){ break; case 'loadeddata' : // コンテンツの表示を現在の再生位置で初めて行えるようになった場合に発生 + case 'canplaythrough' : // 今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生 if( !this._endedFixON ){ ready = true; }; @@ -220,7 +213,6 @@ if( X_Audio_constructor ){ raw.play(); raw.currentTime = 0; // 必要! }; - case 'canplaythrough' : // 今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生 if( this._endedFixON ){ console.log( '▽ onEndedFix の終了 @' + e.type ); this._endedFixON = false; @@ -228,7 +220,7 @@ if( X_Audio_constructor ){ }; case 'loadedmetadata' : // ブラウザがメディアリソースの長さと寸法を判定した場合に発生 case 'durationchange' : // duration属性が更新された場合に発生 - if( !this.duration ){ + if( !this.duration || this.duration !== raw.duration * 1000 ){ // Blink28 duration が変わる duration = raw.duration; }; break; @@ -328,7 +320,13 @@ if( X_Audio_constructor ){ this._loaded = this._loaded || ready; - // + // + if( X_HTMLAudio_need1stTouch && !this._touchRequested ){ + if( e.type === X_HTMLAudio_playTrigger ){ + this._touchRequested = true; + this.disatcher[ 'asyncDispatch' ]( X_EVENT_MEDIA_CAN_TOUCH_LOAD ); + }; + } else if( ended ){ if( !this._closed && this.autoLoop ){ if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){ @@ -359,7 +357,7 @@ if( X_Audio_constructor ){ actualPlay : function( forcePlay, forceReload ){ var raw = this[ '_rawObject' ], - begin, end; + e, begin, end; // もし kill 後に autoplayTimer で呼ばれても、_closed==true なので平気 if( this._closed ) return; @@ -371,6 +369,14 @@ if( X_Audio_constructor ){ //return; }; + if( this._touchRequested && !this._touched ){ + e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ]; + if( !e || !e[ 'pointerType' ] ){ + alert( 'タッチイベント以外での play! ' + e.type ); + return; + }; + this._touched = true; + } else if( !this._ready && ( !X_HTMLAudio_durationFix || !X_HTMLAudio_need1stTouch ) ){ this.autoplay = true; return; @@ -412,8 +418,11 @@ if( X_Audio_constructor ){ //http://himaxoff.blog111.fc2.com/blog-entry-97.html //Firefox3.6では一度も play() していない状態で currentTime = 0 を実行するとエラーになる。 - //また、GoogleChrome7 では currentTime = 0 直後に play() すると、pause()した位置前後の音が混ざることがある。(少なくとも自分の環境では) - raw.currentTime = this._lastCurrentTime; + //また、GoogleChrome7 では currentTime = 0 直後に play() すると、pause()した位置前後の音が混ざることがある。(少なくとも自分の環境では) + + // iOS で duration が 0 の時に触ると error + if( !X_HTMLAudio_durationFix || this.duration ) raw.currentTime = this._lastCurrentTime; + console.log( '[HTMLAudio] play ' + begin + ' -> ' + end + ' crt:' + ( raw.currentTime | 0 ) + ' last:' + this._lastCurrentTime ); if( forceReload || ( X_HTMLAudio_endedFixAOSP4 && raw.duration && raw.currentTime === raw.duration ) ){ diff --git a/0.6.x/js/07_audio/03_XSilverlightAudio.js b/0.6.x/js/07_audio/03_XSilverlightAudio.js index f451596..97582a7 100644 --- a/0.6.x/js/07_audio/03_XSilverlightAudio.js +++ b/0.6.x/js/07_audio/03_XSilverlightAudio.js @@ -323,7 +323,7 @@ if( X[ 'Pulgin' ][ 'Silverlight' ] ){ }; time -= X_Audio_getEndTime( this ); - if( time < 0 ){ + if( time < -50 ){ console.log( ' > まだ終わらない ' + time ); this._ended && this[ '_rawObject' ].play(); this._ended = false; diff --git a/0.6.x/js/07_audio/10_XAudioSprite.js b/0.6.x/js/07_audio/10_XAudioSprite.js index cd91dc4..6d4cdbb 100644 --- a/0.6.x/js/07_audio/10_XAudioSprite.js +++ b/0.6.x/js/07_audio/10_XAudioSprite.js @@ -147,11 +147,11 @@ X_AudioSprite_members = var i = 0, l = X_AudioSprite_TEMP.tracks.length; for( ; i < l; ++i ){ - if( X_UA[ 'iOS' ] ){ - X_AudioSprite_TEMP.tracks[ i ][ '_rawObject' ].load(); - } else { + //if( X_UA[ 'iOS' ] ){ + // X_AudioSprite_TEMP.tracks[ i ][ '_rawObject' ].load(); + //} else { X_AudioSprite_instance[ 'pause' ]( i ); - }; + //}; }; }, @@ -334,7 +334,7 @@ X_AudioSprite_members = }; function X_AudioSprite_backendHandler( e ){ - var i, backend, option, src, name, last, _e, touch; + var i, backend, option, src, name, last, _e; switch( e.type ){ case X_EVENT_BACKEND_READY : @@ -365,25 +365,36 @@ function X_AudioSprite_backendHandler( e ){ // touch 可能で backend ready if( name === 'WebAudio' ){ - _e[ 'needTouchForPlay' ] = touch = X_WebAudio_need1stTouch; + if( _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch ){ + last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_instance[ 'asyncDispatch' ], [ _e ] ); + } else { + X_AudioSprite_instance[ 'asyncDispatch' ]( _e ); + }; + last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler ); } else if( name === 'HTMLAudio' ){ - _e[ 'needTouchForLoad' ] = touch = X_HTMLAudio_need1stTouch; - }; - - X_AudioSprite_instance[ 'asyncDispatch' ]( _e ); - - console.log( 'AudioSprite - X_EVENT_BACKEND_READY' ); - - last[ 'listenOnce' ]( touch && !X_HTMLAudio_durationFix ? X_EVENT_MEDIA_PLAYING : X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler ); - - // READY, needTouchForPlay, needTouchForLoad - if( /* X_HTMLAudio_durationFix && */ !touch ){ - for( i = 0; i < X_AudioSprite_TEMP.tracks.length; ++i ){ - X_AudioSprite_instance[ 'pause' ]( i ); + if( _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch ){ + last[ 'listenOnce' ]( X_EVENT_MEDIA_CAN_TOUCH_LOAD, X_AudioSprite_instance, X_AudioSprite_instance[ 'asyncDispatch' ], [ _e ] ); + last[ 'listenOnce' ]( !X_HTMLAudio_durationFix ? X_EVENT_MEDIA_PLAYING : X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler ); + } else { + X_AudioSprite_instance[ 'asyncDispatch' ]( _e ); + last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler ); + + // READY, needTouchForPlay, needTouchForLoad + if( X_HTMLAudio_durationFix ){ + for( i = 0; i < X_AudioSprite_TEMP.tracks.length; ++i ){ + X_AudioSprite_instance[ 'pause' ]( i ); + }; + }; }; + + } else { + X_AudioSprite_instance[ 'asyncDispatch' ]( _e ); + + console.log( 'AudioSprite - X_EVENT_BACKEND_READY' ); + + last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler ); }; - return X_CALLBACK_STOP_NOW; case X_EVENT_BACKEND_NONE : -- 2.11.0