From a09eec2e19c91d656e784e71c73acacb8368f491 Mon Sep 17 00:00:00 2001 From: itozyun Date: Sat, 6 Dec 2014 00:02:49 +0900 Subject: [PATCH] Version 0.6.118, fix X.Audio.Sprite & etc. --- 0.6.x/js/01_core/02_XUA.js | 20 +++-- 0.6.x/js/01_core/03_XType.js | 6 +- 0.6.x/js/01_core/04_XObject.js | 3 +- 0.6.x/js/01_core/13_XEventDispatcher.js | 14 ++- 0.6.x/js/01_core/16_XViewPort.js | 10 +-- 0.6.x/js/02_dom/02_XNode.js | 5 +- 0.6.x/js/02_dom/05_XNodeAttr.js | 14 ++- 0.6.x/js/06_net/01_XNetXHR.js | 4 +- 0.6.x/js/07_audio/01_XWebAudio.js | 11 ++- 0.6.x/js/07_audio/02_XHTMLAudio.js | 137 ++++++++++++++++++++++++------ 0.6.x/js/07_audio/03_XSilverlightAudio.js | 2 +- 0.6.x/js/07_audio/10_XAudioSprite.js | 56 ++++++++---- 12 files changed, 215 insertions(+), 67 deletions(-) diff --git a/0.6.x/js/01_core/02_XUA.js b/0.6.x/js/01_core/02_XUA.js index 07803a8..7fbfc43 100644 --- a/0.6.x/js/01_core/02_XUA.js +++ b/0.6.x/js/01_core/02_XUA.js @@ -42,7 +42,7 @@ var X_UA = (function( n, undefined ){ }; if( sys === 'iPad' ){ acme.iPad = true; - if( i ) acme.iPod_2Mini1 = true; + if( i ) acme.iPad_2Mini1 = true; }; if( sys === 'iPod' ){ acme.iPod = true; @@ -67,6 +67,7 @@ var X_UA = (function( n, undefined ){ case 'WinCE' : acme[ sys ] = true; }; + // winRT } else if( sys.indexOf( 'Mac' ) + 1 ){ console.log( 'Mac' ); @@ -86,7 +87,7 @@ var X_UA = (function( n, undefined ){ acme.Linux = true; if( ( i = dua.indexOf( 'Android' ) ) !== -1 ){ - acme.Android = parseFloat( dua.substr( i + 8 ) ) || 0; + acme.Android = parseFloat( dua.substr( i + 8 ) ) || 0.1; // Firefox で Version が取れない! console.log( '>> Android : ' + acme.Android ); }; }; @@ -139,7 +140,7 @@ Sleipnir Mobile Android 2.1以上 Fenrir acme.IE7 = 7 <= acme.IE && acme.IE < 8; acme.IE8 = 8 <= acme.IE && acme.IE < 9; acme.IE9 = 9 <= acme.IE && acme.IE < 10; - acme.MacIE = dua.indexOf( 'Mac_PowerPC' ) !== -1 || dua.indexOf( 'Mac_PPC' ) !== -1 || dua.indexOf( 'Mac_68K' ) !== -1; + acme.MacIE = acme.Mac; acme.IEMobile = dua.toLowerCase().indexOf( 'iemobile' ) !== -1 || acme.WinCE; acme.WinPhone = dua.toLowerCase().indexOf( 'windows phone' ) !== -1; console.log( '>> IE : ' + acme.IE + ' ActiveX : ' + acme.ActiveX ); @@ -149,7 +150,7 @@ Sleipnir Mobile Android 2.1以上 Fenrir // http://qa.support.sony.jp/solution/S0812181056444/common/nfb34_dom_200jp/dom_dom0_JP.html if( ( i = dua.indexOf( 'NetFront\/' ) !== -1 ) ){ - acme.NetFront = parseFloat( dua.substr( i + 9 ) ) || 0; + acme.NetFront = parseFloat( dua.substr( i + 9 ) ) || 0.1; console.log( '>> NetFront : ' + acme.NetFront ); return acme; }; @@ -164,7 +165,7 @@ Sleipnir Mobile Android 2.1以上 Fenrir // Mozilla/5.0 (PLAYSTATION 3; 3.55) // Mozilla/4.0 (PS3 (PlayStation 3); 1.00) if( ( i = dua.toUpperCase().indexOf( 'PLAYSTATION 3' ) !== -1 ) ){ - acme.PS3 = parseFloat( dua.substr( i + 15 ) ) || 0; + acme.PS3 = parseFloat( dua.substr( i + 15 ) ) || 0.1; console.log( '>> PS3 : ' + acme.PS3 ); return acme; }; @@ -173,7 +174,7 @@ Sleipnir Mobile Android 2.1以上 Fenrir // iCab/3.0.2 (Macintosh; U; PPC Mac OS X) // Mozilla/5.0 (Macintosh; U; PPC Mac OS; en) iCab 3 if( ( i = dua.indexOf( 'iCab' ) !== -1 ) ){ - acme.iCab = parseFloat( dua.substr( i + 5 ) ) || 0; + acme.iCab = parseFloat( dua.substr( i + 5 ) ) || 0.1; console.log( '>> iCab : ' + acme.iCab ); return acme; }; @@ -234,13 +235,18 @@ Sleipnir Mobile Android 2.1以上 Fenrir } else if( ( i = dua.indexOf( 'Android ' ) ) !== -1 ){ - acme.AndroidBrowser = i = parseFloat( dua.substr( i + 8 ) ) || 0; + acme.AndroidBrowser = i = parseFloat( dua.substr( i + 8 ) ) || 0.1; acme.AndroidBrowser1 = 1 <= i && i < 2; acme.AndroidBrowser2 = 2 <= i && i < 3; acme.AndroidBrowser3 = 3 <= i && i < 4; acme.AndroidBrowser4 = 4 <= i && i < 5; acme.AndroidBrowser5 = 5 <= i && i < 6; console.log( '>> AndroidBrowser : ' + acme.Android ); + + i = parseFloat(dua.split('WebKit\/')[1]); + acme.AndroidBrowserWebkit = i; + alert( 'AudioSprite調査:Android標準ブラウザ Webkit Version ' + i ); + } else if( i = parseFloat(dua.split('WebKit\/')[1]) ){ acme.WebKit = i; diff --git a/0.6.x/js/01_core/03_XType.js b/0.6.x/js/01_core/03_XType.js index 212a803..e8067de 100644 --- a/0.6.x/js/01_core/03_XType.js +++ b/0.6.x/js/01_core/03_XType.js @@ -31,7 +31,7 @@ X.Type = { }, isString : function( v ){ - return typeof v === 'string'; // v === v + ''; + return typeof v === 'string'; // v === v + ''; // 文字列の加算は IE で遅いかも。 }, isNumber : function( v ){ @@ -51,7 +51,7 @@ X.Type = { ( X_UA.IE4 || X_UA.MacIE ) ? 'return v&&v.tagName&&v.insertAdjacentHTML&&true' : // ie4 or MacIE5.23, v.all <- error X_UA.NetFront < 4 ? - 'return v&&v.nodeType===1' : // instanceof not a function. + 'return v&&v.nodeType===1' : // instanceof not a function. netfront3.4 は html に instanceof をすると error になる window[ 'HTMLElement' ] ? 'return v instanceof HTMLElement' : //window[ 'Element' ] ? @@ -60,7 +60,7 @@ X.Type = { ), /* - * new Image した場合に HTMLElement の img が作られるブラウザもある + * new Image した場合に HTMLImageElement が作られるブラウザと,そうでないブラウザ(IE8-)がある */ isImage : function( v ){ diff --git a/0.6.x/js/01_core/04_XObject.js b/0.6.x/js/01_core/04_XObject.js index 60db866..be7f595 100644 --- a/0.6.x/js/01_core/04_XObject.js +++ b/0.6.x/js/01_core/04_XObject.js @@ -76,7 +76,8 @@ function X_Object_deepCopy_( src, objSrc, objCopy, n ) { }; function X_Object_cloneArray( ary ){ - var ret = [], i = ary.length; + var ret = [], + i = ary.length; if( !i ) return ret; for( ; i; ){ ret[ --i ] = ary[ i ]; diff --git a/0.6.x/js/01_core/13_XEventDispatcher.js b/0.6.x/js/01_core/13_XEventDispatcher.js index 594701c..b3763fc 100644 --- a/0.6.x/js/01_core/13_XEventDispatcher.js +++ b/0.6.x/js/01_core/13_XEventDispatcher.js @@ -510,7 +510,13 @@ var X_EventDispatcher_actualAddEvent = list.slcallback = X_Callback_create( that, X_EventDispatcher_sliverLightDispatch, [ type ] ); list.sltoken = raw.AddEventListener( type, list.slcallback ); } else - if( X.UA.iOS && ( type === 'webkitTransitionEnd' || type === 'transitionend' ) ){ + // 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' ) ){ raw.addEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false ); } else { console.log( 'event > ' + type ); @@ -602,7 +608,11 @@ var X_EventDispatcher_actualRemoveEvent = delete list.sltoken; delete list.slcallback; } else - if( X.UA.iOS && ( type === 'webkitTransitionEnd' || type === 'transitionend' ) ){ + if( ( X_UA.WebKit || X_UA.Blink ) && + ( type === 'webkitTransitionEnd' || type === 'transitionend' || + type === 'animationend' || type === 'webkitAnimationEnd' || + type === 'animationstart' || type === 'webkitAnimationStart' || + type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){ raw.removeEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false ); } else { diff --git a/0.6.x/js/01_core/16_XViewPort.js b/0.6.x/js/01_core/16_XViewPort.js index 29e6776..8b079cc 100644 --- a/0.6.x/js/01_core/16_XViewPort.js +++ b/0.6.x/js/01_core/16_XViewPort.js @@ -51,20 +51,20 @@ X_ViewPort = X_Class_override( break; case 'visibilitychange' : - X_ViewPort.asyncDispatch( ( X_ViewPort_active = document[ 'hidden' ] ) ? X.Event.VIEW_DEACTIVATE : X.Event.VIEW_ACTIVATE ); + X_ViewPort.dispatch( ( X_ViewPort_active = document[ 'hidden' ] ) ? X.Event.VIEW_DEACTIVATE : X.Event.VIEW_ACTIVATE ); break; case 'mozvisibilitychange' : - X_ViewPort.asyncDispatch( ( X_ViewPort_active = document[ 'mozHidden' ] ) ? X.Event.VIEW_DEACTIVATE : X.Event.VIEW_ACTIVATE ); + X_ViewPort.dispatch( ( X_ViewPort_active = document[ 'mozHidden' ] ) ? X.Event.VIEW_DEACTIVATE : X.Event.VIEW_ACTIVATE ); break; case 'webkitvisibilitychange' : - X_ViewPort.asyncDispatch( ( X_ViewPort_active = document[ 'webkitHidden' ] ) ? X.Event.VIEW_DEACTIVATE : X.Event.VIEW_ACTIVATE ); + X_ViewPort.dispatch( ( X_ViewPort_active = document[ 'webkitHidden' ] ) ? X.Event.VIEW_DEACTIVATE : X.Event.VIEW_ACTIVATE ); break; case 'pageshow' : case 'focus' : if( !X_ViewPort_active ){ X_ViewPort_active = true; - X_ViewPort.asyncDispatch( X.Event.VIEW_ACTIVATE ); + X_ViewPort.dispatch( X.Event.VIEW_ACTIVATE ); }; break; @@ -72,7 +72,7 @@ X_ViewPort = X_Class_override( case 'blur' : if( X_ViewPort_active ){ X_ViewPort_active = false; - X_ViewPort.asyncDispatch( X.Event.VIEW_DEACTIVATE ); + X_ViewPort.dispatch( X.Event.VIEW_DEACTIVATE ); }; break; }; diff --git a/0.6.x/js/02_dom/02_XNode.js b/0.6.x/js/02_dom/02_XNode.js index 162b25c..01588f9 100644 --- a/0.6.x/js/02_dom/02_XNode.js +++ b/0.6.x/js/02_dom/02_XNode.js @@ -834,15 +834,14 @@ function X_Node_html( html ){ }; /* - * 数値が来たら文字化 - * null が来たら '' + * null が来たら '', 数値等が来たら文字烈化 */ function X_Node_text( text ){ var xnodes, texts, i, l; // setter if( text !== undefined ){ - if( X.Type.isNumber( text ) ) text += ''; if( text === null ) text = ''; + text += ''; if( this._xnodeType === 3 ){ if( this._text !== text ){ diff --git a/0.6.x/js/02_dom/05_XNodeAttr.js b/0.6.x/js/02_dom/05_XNodeAttr.js index 5a5f16f..3fc530c 100644 --- a/0.6.x/js/02_dom/05_XNodeAttr.js +++ b/0.6.x/js/02_dom/05_XNodeAttr.js @@ -47,7 +47,18 @@ X_Node_Attr_HAS_VALUE = { SELECT : true, BUTTON : true, OBJECT : true, - PARAM : true // FlashVars が flash 側から書き換えられるケースがある + PARAM : true // FlashVars が flash 側から書き換えられるケースがある?? +}, + +// の場合、value の値はユーザーで変えることはない +// はユーザーによって常に変更される HTML5 ではこれにさらにいろいろ加わる +X_Node_Attr_STATIC_VALUE_TYPES = { + button : true, + hidden : true, + submit : true, + reset : true, + radio : true, + checkbox : true }, X_Node_Attr_renameForTag = {}; @@ -138,6 +149,7 @@ Node.prototype.attr = function( nameOrObj /* v */ ){ // 親ノードの selectedIndex の getter を呼んでおくと値が正しくなる、ということ?( by itozyun ) if( X_UA.WebKit ) this._rawObject.parentNode.selectedIndex; case 'value' : + if( this._tag === 'INPUT' && X_Node_Attr_STATIC_VALUE_TYPES[ attrs[ 'type' ] ] ) break; case 'checked' : case 'disabled' : case 'selectedIndex' : diff --git a/0.6.x/js/06_net/01_XNetXHR.js b/0.6.x/js/06_net/01_XNetXHR.js index 6c3c520..1ea396c 100644 --- a/0.6.x/js/06_net/01_XNetXHR.js +++ b/0.6.x/js/06_net/01_XNetXHR.js @@ -42,7 +42,7 @@ var X_Net_XHR_W3C = ( !X_UA.IE7 || !X_URL_IS_LOCAL ) && window[ 'XMLHttpReq 'for(;i<5;){', 'try{', 'return[v[++i],new ActiveXObject(n[i])]', - '}catch(e){return false}', + '}catch(e){}', '}' ].join( '' ) ) )(); @@ -147,7 +147,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ break; case 'json' : case 'moz-json' : - raw.responseType = this._type; + raw.responseType = X_UA.Gecko ? this._type : ''; // Iron 37 でエラー break; case 'document' : case 'xml' : diff --git a/0.6.x/js/07_audio/01_XWebAudio.js b/0.6.x/js/07_audio/01_XWebAudio.js index 1a60624..bb64a98 100644 --- a/0.6.x/js/07_audio/01_XWebAudio.js +++ b/0.6.x/js/07_audio/01_XWebAudio.js @@ -1,8 +1,13 @@ -var X_Audio_WebAudio_context = window.webkitAudioContext || window.AudioContext, +var X_Audio_WebAudio_context = !X_UA.iPhone_4s && !X_UA.iPad_2Mini1 && !X_UA.iPod_4 && + !( X_UA.Gecko && X_UA.Android ) && + ( window.AudioContext || window.webkitAudioContext ), X_Audio_WebAudioWrapper; -if( !X_UA.iPhone_4s && !X_UA.iPod_2Mini1 && !X_UA.iPod_4 && X_Audio_WebAudio_context ){ +/* + * iPhone 4s 以下、iPad2以下、iPad mini 1以下, iPod touch 4G 以下は不可 + */ +if( X_Audio_WebAudio_context ){ X_Audio_WebAudio_context = new X_Audio_WebAudio_context; @@ -246,7 +251,7 @@ if( !X_UA.iPhone_4s && !X_UA.iPod_2Mini1 && !X_UA.iPod_4 && X_Audio_WebAudio_con if( this.loop ){ this.looped = true; - ( this.proxy.dispatch( 'looped' ) | X.Callback.PREVENT_DEFAULT ) || this.play(); + ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play(); } else { this.pause(); this.proxy.dispatch( 'ended' ); diff --git a/0.6.x/js/07_audio/02_XHTMLAudio.js b/0.6.x/js/07_audio/02_XHTMLAudio.js index c18b141..ee712a5 100644 --- a/0.6.x/js/07_audio/02_XHTMLAudio.js +++ b/0.6.x/js/07_audio/02_XHTMLAudio.js @@ -11,7 +11,15 @@ var X_Audio_HTMLAudio_playTrigger = X_Audio_HTMLAudioWrapper, X_Audio_rawAudio, // Opera Mobile 12 android4.4.4 & 2.3.5 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する - X_Audio_HTMLAudioWrapper_currentTimeFix = !!X_UA.OperaMobile || !!X_UA.OperaTablet; + X_Audio_HTMLAudioWrapper_currentTimeFix = !!X_UA.OperaMobile || !!X_UA.OperaTablet, + // 一方 Desktop の Opera12 は、loadeddata 等では duration が infinity で、再生後の durationchange 時に duration が判明する。 + // duration 判明後には currentTime によるシークと、現在時間の取得が可能になる。 + // canplay で play() durationchange で duration が取れたら loadedmetadata->loadeddata -> canplay する + // boombox.js に書いてあった currentTime の効かないブラウザってこいつのことみたい、、、 + X_Audio_HTMLAudioWrapper_currentTimeFix2 = !X_Audio_HTMLAudioWrapper_currentTimeFix && X_UA.Opera, + + X_Audio_HTMLAudioWrapper_shortPlayFix = !!X_UA.AndroidBrowser4; + if( window.HTMLAudioElement ){ @@ -36,19 +44,37 @@ if( window.HTMLAudioElement ){ autoplay : false, volume : 0.5, - _timerID : 0, - _playTime : 0, - _closed : true, - _loaded : false, + _timerID : 0, + _playTime : 0, + _closed : true, + _loaded : false, + _playForDuration : false, + _currentTimeFix : 0, + _shortFix : 0, Constructor : function( proxy, source, option ){ this.proxy = proxy; this._closed = false; X_AudioWrapper_updateStates( this, option ); - - // TODO use video document.createElement('video') - this._rawObject = X_Audio_rawAudio || new Audio( source );// X_Doc_create( 'audio', { src : source } ).appendToRoot();//( X.X_Node_systemNode ); + + if( option[ 'useVideo' ] ){ + this._rawObject = document.createElement( 'video' ); + this._rawObject.preload = 'none'; // auto, metadata, none + //this._rawObject.autoplay = false, // no-auto + this._rawObject.loop = false; + this._rawObject.muted = false; + //this._rawObject.crossorigin = option[ 'crossorigin' ] || ''; //crossorigin: "anonymous", X.URL.isSameDomain() で切り替え + this._rawObject.style.cssText = 'position:absolute;bottom:0;left:-50px;width:100px;height:100px;opacity:0;'; + this._rawObject.controls = false; + this._rawObject.WebKitPlaysInline = true; + this._rawObject.src = source; + //this._rawObject.onclick = "alert('play');this.play();"; + document.body.appendChild( this._rawObject ); + //this._rawObject.load(); + } else { + this._rawObject = X_Audio_rawAudio || new Audio( source );// X_Doc_create( 'audio', { src : source } ).appendToRoot();//( X.X_Node_systemNode ); + }; this.listen( [ 'loadstart', 'load', 'progress', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'play', 'pause', 'loadedmetadata', @@ -79,23 +105,33 @@ if( window.HTMLAudioElement ){ * http://uguisu.skr.jp/html/table3.html */ handleEventProxy : function( e ){ + var loaded; console.log( 'HTMLAudio ' + e.type ); switch( e.type ){ case 'loadstart' : // ブラウザがコンテンツの検索を開始した場合に発生 break; case 'progress' : // ブラウザがコンテンツの取得を実行した場合に発生 - //console.log( e.loaded + ' ' + e.total * 100 + '%' ); - this._rawObject.duration && - console.dir( this._rawObject ); + console.log( e.loaded + ' ' + e.total * 100 + '%' ); + //this._rawObject.duration && + // console.dir( this._rawObject ); //console.log( this._rawObject.buffered.end(0) / this._rawObject.duration * 100 + '%' ); break; + + case 'canplay' : // 今すぐに再生を再開できるが、バッファリングが不十分でコンテンツを最後まで表示できないと予測している場合に発生 + if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){ + console.log( 'play ' + this.duration ); + this._playForDuration = true; + this._rawObject.currentTime = 0; + this._rawObject.play(); + this._rawObject.currentTime = 0; + }; case 'loadedmetadata' : // ブラウザがメディアリソースの長さと寸法を判定した場合に発生 case 'loadeddata' : // コンテンツの表示を現在の再生位置で初めて行えるようになった場合に発生 - case 'canplay' : // 今すぐに再生を再開できるが、バッファリングが不十分でコンテンツを最後まで表示できないと予測している場合に発生 case 'canplaythrough' : // 今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生 + if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ) return; this.duration = this._rawObject.duration * 1000; - //console.log( this.duration ); + console.log( this.duration ); break; case 'suspend' : // ブラウザが意図的にコンテンツの取得を現在行っていない場合に発生(ダウンロードは未完了) @@ -103,24 +139,33 @@ if( window.HTMLAudioElement ){ case 'error' : // コンテンツの取得実行中にエラーが発生した場合に発生 case 'emptied' : // 読み込み中に致命的なエラーが発生したか、実行状態ででload()メソッドが実行された場合に発生 case 'stalled' : // ブラウザがコンテンツの取得を試みたが、データがまだ用意されていない場合に発生 + break; + + case 'play' : // 再生が開始された。play()メソッドからの復帰後に発生する場合に発生 case 'pause' : // 再生が一時停止された。pauseメソッドからの復帰後に発生する場合に発生 - case 'waiting' : // 次のフレームが利用不可のため再生を停止したが、そのフレームがやがて利用可能になると想定している場合に発生 - case 'playing' : // 再生が開始された場合に発生 - + case 'playing' : // 再生が開始された場合に発生 case 'seeking' : // シークがtrueに変化し、イベントを発生させるのに十分な時間がシーク操作にかかっている場合に発生 case 'seeked' : // シークがfalseに変化した場合に発生 + case 'ratechange' : // defaultPlaybackRate属性とplaybackRate属性のどちらかが更新された場合に発生 + case 'volumechange' : // volume属性とmuted属性のどちらかが変化した場合に発生 + if( this._playForDuration ) return; break; case 'timeupdate' : // 通常の再生が行われ現在の再生位置の変化が起こった場合に発生 + // console.log( this._rawObject.currentTime ); + if( this._playForDuration ) 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(); + ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play(); } else { this._timerID && X.Timer.remove( this._timerID ); this.seekTime = 0; @@ -129,15 +174,35 @@ if( window.HTMLAudioElement ){ }; break; - case 'ratechange' : // defaultPlaybackRate属性とplaybackRate属性のどちらかが更新された場合に発生 case 'durationchange' : // duration属性が更新された場合に発生 - case 'volumechange' : // volume属性とmuted属性のどちらかが変化した場合に発生 + 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; + + 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; + }; //console.log( 'html5 ' + e.type + ' ' + ( this.proxy._listeners && this.proxy._listeners[ e.type ] && this.proxy._listeners[ e.type ].length ) ); //e.type === 'canplaythrough' && console.dir( e ); - this.proxy.dispatch( e ); + loaded || this.proxy.dispatch( e ); - if( X_Audio_HTMLAudio_playTrigger === e.type || ( X_UA.AndroidBrowser2 && e.type === 'loadeddata' ) ){ + if( X_Audio_HTMLAudio_playTrigger === e.type || ( X_UA.AndroidBrowser2 && e.type === 'loadeddata' ) || loaded ){ !this._loaded && this.autoplay && X.Timer.once( 16, this, this.play ); this._loaded = true; console.log( 'Loaded! ' + e.type ); @@ -168,8 +233,21 @@ 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++; + this._beginTime = begin; + }; + console.log( '[HTMLAudio] play ' + begin + ' -> ' + end ); if( !this.playing ){ @@ -211,15 +289,20 @@ if( window.HTMLAudioElement ){ 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 ) ); + 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(); + ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play(); } else { this.pause(); this.dispatch( 'ended' ); @@ -232,6 +315,10 @@ if( window.HTMLAudioElement ){ 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; @@ -330,9 +417,11 @@ if( window.HTMLAudioElement ){ case 'mp3' : ok = X_UA.IE || X_UA.Chrome || ( X_UA.Windows && X_UA.Safari ); mineType = 'audio/mpeg'; + //if( X_UA.Android && X_UA.Gecko ) mineType = ''; break; case 'ogg' : ok = 15 <= X_UA.Gecko || X_UA.Chrome || X_UA.Opera; + if( X_UA.AndroidBrowser ) mineType = ''; break; case 'm4a' : ok = X_UA.IE || X_UA.WebKit; diff --git a/0.6.x/js/07_audio/03_XSilverlightAudio.js b/0.6.x/js/07_audio/03_XSilverlightAudio.js index 51433aa..02c1ec1 100644 --- a/0.6.x/js/07_audio/03_XSilverlightAudio.js +++ b/0.6.x/js/07_audio/03_XSilverlightAudio.js @@ -308,7 +308,7 @@ if( X.Pulgin.SilverlightEnabled ){ if( this.loop ){ this.looped = true; - ( this.proxy.dispatch( 'looped' ) | X.Callback.PREVENT_DEFAULT ) || this.play(); + ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play(); } else { this.pause(); 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 74fb1c6..4152fa2 100644 --- a/0.6.x/js/07_audio/10_XAudioSprite.js +++ b/0.6.x/js/07_audio/10_XAudioSprite.js @@ -5,12 +5,12 @@ * iframe 内で生成して、Audio Sprite の preset で再生できないか? */ var X_Audio_Sprite_shouldUse = window.HTMLAudioElement && ( X_UA.iOS || X_UA.AndroidBrowser || X_UA.OperaMobile || X_UA.OperaTablet ), - X_Audio_Sprite_needTouchFirst = !!X_UA.iOS, + X_Audio_Sprite_useVideoForMulti = 4 <= X_UA.AndroidBrowser && 534.3 < X_UA.AndroidBrowserWebkit, // ドスパラパッドはビデオのインライン再生が不可 + X_Audio_Sprite_needTouchFirst = !!X_UA.iOS || X_Audio_Sprite_useVideoForMulti, X_Audio_Sprite_inTouchAction = false, - X_Audio_Sprite_enableMultiTrack = !( X_UA.iOS < 6 ), + 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_useVideoForMulti = 4 <= X_UA.AndroidBrowser, - X_Audio_Sprite_maxTracks = X_UA.iOS < 6 ? 1 : X_Audio_Sprite_useVideoForMulti ? 2 : 9, + X_Audio_Sprite_maxTracks = !X_Audio_Sprite_enableMultiTrack ? 1 : X_Audio_Sprite_useVideoForMulti ? 2 : 9, X_Audio_Sprite_lengthSilence = 10000, // 一番最初の無音部分の長さ X_Audio_Sprite_lengthDistance = 5000, // 音間の無音の長さ X_Audio_Sprite_uid = 0, @@ -19,6 +19,7 @@ var X_Audio_Sprite_shouldUse = window.HTMLAudioElement && ( X_UA.iOS || X presets : {}, BGMs : {}, tracks : [], + pauseTracks : [], // X.Event.DEACTIVATE によって pause した再生中のトラックたち。 volume : 1, bgmTrack : null, bgmPosition : 0, @@ -42,6 +43,7 @@ X.Audio.Sprite = { X_Audio_Sprite_instance.close(); } else { X_Audio_Sprite_instance = X_Class_override( new X.EventDispatcher(), X_Audio_Sprite_members ); + X_ViewPort.listen( [ X.Event.VIEW_ACTIVATE, X.Event.VIEW_DEACTIVATE ], X_Audio_Sprite_instance, X_Audio_Sprite_handleEvent ); }; X_Audio_Sprite_instance.setup( setting ); return X_Audio_Sprite_instance; @@ -50,7 +52,7 @@ X.Audio.Sprite = { }; // 再生が終わっているもの、終わりかけのものを探す -// TODO 終わりかけのもの、と一番古いもの、どちらを再利用するか?または、再利用を待つ。 +// TODO 終わりかけのもの、と一番古いもの、どちらを再利用するか?これ以上に細かい実装を望む場合は X.Audio.Sprite は使わず自力で実装 function X_Audio_Sprite_getTrackEnded(){ var tracks = X_Audio_Sprite_TEMP.tracks, l = tracks.length, @@ -90,8 +92,8 @@ X_Audio_Sprite_members = { bgms = X_Audio_Sprite_TEMP.BGMs, presets = X_Audio_Sprite_TEMP.presets, urls = setting[ 'urls' ], - n = setting[ 'numTracks' ] || 1, video = setting[ 'useVideo' ], + n = video ? 1 : setting[ 'numTracks' ] || 1, option = { volume : setting[ 'volume' ] || 0.5, autoplay : false, @@ -103,8 +105,6 @@ X_Audio_Sprite_members = { n = n <= X_Audio_Sprite_maxTracks ? n : X_Audio_Sprite_maxTracks; - video = video || ( 1 < n && X_Audio_Sprite_useVideoForMulti ); - for( k in setting ){ v = setting[ k ]; if( X.Type.isArray( v ) && v !== urls){ @@ -119,12 +119,10 @@ X_Audio_Sprite_members = { }; for( i = 0; i < n; ++i ){ - if( i === 1 && X_Audio_Sprite_useVideoForMulti ){ - // TODO use