OSDN Git Service

Version 0.6.118, fix X.Audio.Sprite & etc.
authoritozyun <itozyun@user.sourceforge.jp>
Fri, 5 Dec 2014 15:02:49 +0000 (00:02 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Fri, 5 Dec 2014 15:02:49 +0000 (00:02 +0900)
12 files changed:
0.6.x/js/01_core/02_XUA.js
0.6.x/js/01_core/03_XType.js
0.6.x/js/01_core/04_XObject.js
0.6.x/js/01_core/13_XEventDispatcher.js
0.6.x/js/01_core/16_XViewPort.js
0.6.x/js/02_dom/02_XNode.js
0.6.x/js/02_dom/05_XNodeAttr.js
0.6.x/js/06_net/01_XNetXHR.js
0.6.x/js/07_audio/01_XWebAudio.js
0.6.x/js/07_audio/02_XHTMLAudio.js
0.6.x/js/07_audio/03_XSilverlightAudio.js
0.6.x/js/07_audio/10_XAudioSprite.js

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