OSDN Git Service

Version 0.6.218, Fix the bug of X.Net & X.Audio.
authoritozyun <itozyun@user.sourceforge.jp>
Fri, 21 Oct 2016 06:10:06 +0000 (15:10 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Fri, 21 Oct 2016 06:10:06 +0000 (15:10 +0900)
0.6.x/js/02_dom/10_XNodeAnime.js
0.6.x/js/06_net/00_XNet.js
0.6.x/js/06_net/01_XNetXHR.js
0.6.x/js/06_net/10_XOAuth2.js
0.6.x/js/07_audio/00_XAudio.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/05_XWMPAudio.js
0.6.x/js/07_audio/10_XAudioSprite.js

index 4320ec1..c851f8e 100644 (file)
@@ -525,7 +525,14 @@ function X_NodeAnime_updatePosition( xnode, obj, ratio, useGPU ){
        \r
        //console.log( 'updatePosition x:' + x + ' gpu:' + !!useGPU );\r
        if( obj.transform ){\r
-               if( ( x === x || y === y ) && ( x !== 0 && y !== 0 ) ) str += ' translate(' + ( x | 0 ) + 'px,' + ( y | 0 ) + 'px)';\r
+               if( ( x === x || y === y ) && ( x !== 0 && y !== 0 ) ){\r
+                       if( X_UA[ 'Safari' ] && X_UA[ 'Windows' ] ){\r
+                               // http://shinimae.hatenablog.com/entry/2016/01/13/151748\r
+                               str = ' -webkit-translate(' + ( x | 0 ) + 'px,' + ( y | 0 ) + 'px)';\r
+                       } else {\r
+                               str = ' translate(' + ( x | 0 ) + 'px,' + ( y | 0 ) + 'px)';\r
+                       };\r
+               };\r
                if( rotate < 0 || 0 < rotate ) str += ' rotate(' + rotate + 'deg)'; // opera は rad?\r
                if( skewX  < 0 || 0 < skewX  ) str += ' skewX('  + skewX  + 'deg)';\r
                if( skewY  < 0 || 0 < skewY  ) str += ' skewY('  + skewY  + 'deg)';\r
index 9069396..3e7b454 100644 (file)
@@ -279,6 +279,8 @@ function X_NET_proxyDispatch( e ){
                        this[ 'listenOnce' ]( X_EVENT_COMPLETE, X_NET_proxyDispatch )\r
                                [ 'asyncDispatch' ]( 32, { type : X_EVENT_COMPLETE, 'lastEventType' : e.type } );\r
 \r
+                       // target を上書き X_NET_currentWrapper -> X_NET_currentQueue\r
+                       e[ 'target' ] = e[ 'currentTarget' ] = this;\r
                        this[ 'asyncDispatch' ]( e );\r
                        break;\r
 \r
index 746f5a3..c03b635 100644 (file)
@@ -171,7 +171,7 @@ if( X_XHR_w3c || X_XHR_msXML ){
                                        postdata = obj[ 'postdata' ] || '',\r
                                        timeout  = obj[ 'timeout' ] || 20000,\r
                                        noCache  = obj[ 'cache' ] !== true,\r
-                                       dataType = X_XHR._dataType = obj[ 'dataType' ],\r
+                                       dataType = X_XHR._dataType = obj[ 'dataType' ], // ext が入っている\r
                                        xDomain  = !X_URL_isSameDomain( url ),\r
                                        isFile   = X_URL_isLocal( url ),\r
                                        init,\r
@@ -204,24 +204,25 @@ if( X_XHR_w3c || X_XHR_msXML ){
                                if( raw.responseType !== undefined ){\r
                                        switch( dataType ){\r
                                                case '' :\r
+                                               case 'txt' :\r
                                                case 'text' :\r
                                                // js, css\r
-                                                       raw.responseType = 'text';\r
+                                                       raw.responseType = X_XHR._dataType = 'text';\r
                                                        break;\r
                                                case 'json' : // firefox9- は moz-json\r
-                                                       raw.responseType = X_UA[ 'Gecko' ] < 10 ? 'moz-json' : X_UA[ 'Gecko' ] ? dataType : ''; // Iron 37 でエラー\r
+                                                       raw.responseType = X_XHR._dataType = X_UA[ 'Gecko' ] < 10 ? 'moz-json' : X_UA[ 'Gecko' ] ? dataType : ''; // Iron 37 でエラー\r
                                                        break;\r
                                                case 'document' :\r
                                                case 'xml' :\r
                                                case 'html' :\r
                                                case 'htm' :\r
                                                // svg\r
-                                                       raw.responseType = 'document';\r
+                                                       raw.responseType = X_XHR._dataType = 'document';\r
                                                        break;\r
                                                case 'blob' :\r
                                                case 'arraybuffer' :\r
                                                // jpeg,jpg,png,gif,mp3,ogg...\r
-                                                       raw.responseType = dataType;\r
+                                                       raw.responseType = X_XHR._dataType = dataType;\r
                                                        break;\r
                                        };\r
                                };\r
@@ -472,7 +473,6 @@ if( X_XHR_w3c || X_XHR_msXML ){
                                                        \r
                                                        // parse json, html, xml, text, script, css\r
                                                        switch( X_XHR._dataType ){\r
-                                                               case '' :\r
                                                                case 'text' :\r
                                                                        data = X_Script_try( X_Object_find, [ raw, 'responseText' ] );\r
                                                                        break;\r
@@ -485,10 +485,6 @@ if( X_XHR_w3c || X_XHR_msXML ){
                                                                        if( X_Type_isString( data ) ) data = X_JSON_parseTrustableString( data );\r
                                                                        break;\r
                                                                case 'document' :\r
-                                                               case 'xml' :\r
-                                                               case 'html' :\r
-                                                               case 'htm' :\r
-                                                               // svg, vml, xaml, xul, mxml ??\r
                                                                        data = raw[ 'responseXML' ] || raw[ 'response' ] || raw[ 'responseText' ]; // とりあえず\r
                                                                        break;\r
                                                                case 'blob' :\r
index e1f923e..5f23c6c 100644 (file)
@@ -414,7 +414,7 @@ function X_OAuth2_updateLocalStorage( cmd, that, name, value ){
        var action = cmd === '+' ? 'setItem' : cmd === '-' ? 'removeItem' : 'getItem',
                pair;
        
-       if( window.localStorage ){
+       if( window.localStorage ){ // TODO http://qiita.com/narikei/items/f55fb9cb398beac52ea9
                return window.localStorage[ action ]( X_Pair_get( that )[ 'clientID' ] + name, value );
        };
        
index 4664aa0..60bc56e 100644 (file)
@@ -89,7 +89,7 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ](
                                X_Type_isArray( sourceList ) ? X_Array_copy( sourceList ) : [ sourceList ],\r
                                opt_option || {} );\r
                        this[ 'listenOnce' ]( [ X_EVENT_BACKEND_READY, X_EVENT_BACKEND_NONE, X_EVENT_KILL_INSTANCE ], X_Audio_handleEvent );\r
-                       X_ViewPort[ 'listenOnce' ]( X_EVENT_UNLOAD, this, X_AudioSprite_handleEvent );\r
+                       X_ViewPort[ 'listenOnce' ]( X_EVENT_UNLOAD, this, X_Audio_handleEvent );\r
                },\r
                \r
                /**\r
@@ -231,7 +231,7 @@ function X_Audio_handleEvent( e ){
                        this[ 'listenOnce' ]( X_EVENT_READY, X_Audio_handleEvent );\r
                        break;\r
                \r
-               case X_EVENT_READY :\r
+               case X_EVENT_READY : // TODO AudioBase 側へ行かない?\r
                        pair = X_Pair_get( this );\r
                        ( pair.autoplay || pair._playReserved ) && pair.actualPlay();\r
                        delete pair._playReserved;\r
@@ -243,7 +243,7 @@ function X_Audio_handleEvent( e ){
                        break;\r
                \r
                case X_EVENT_KILL_INSTANCE :\r
-                       X_ViewPort[ 'unlisten' ]( X_EVENT_UNLOAD, this, X_AudioSprite_handleEvent );\r
+                       X_ViewPort[ 'unlisten' ]( X_EVENT_UNLOAD, this, X_Audio_handleEvent );\r
                        if( backend = X_Pair_get( this ) ){\r
                                backend[ 'kill' ]();\r
                                X_Pair_release( this, backend );\r
@@ -286,7 +286,7 @@ function X_Audio_onEndedDetection( e, xaudio, sourceList, option, source, ext, s
                        'backendID'   : i\r
                };\r
                // WebAudio\r
-               if( this.backendID === 1 ) _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch;\r
+               if( this.backendID === 1 ) _e[ 'needTouchForPlay' ] = /* X_WebAudio_need1stTouch && */ X_WebAudio_isNoTouch;\r
                // HTMLAudio\r
                if( this.backendID === 2 ) _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch;\r
 \r
@@ -313,7 +313,7 @@ var X_AudioBase = X_EventDispatcher[ 'inherits' ](
        'X.AudioBase',\r
        X_Class.ABSTRACT,\r
        {\r
-               disatcher     : null,\r
+               dispatcher    : null,\r
                \r
                startTime     : 0,    // state_startTime\r
                endTime       : -1,   // state_startTime\r
index 1cc3cba..910271f 100644 (file)
@@ -14,6 +14,10 @@ var X_Audio_constructor = 3.1 <= X_UA[ 'Safari' ] && X_UA[ 'Safari' ] < 4 ?
 
        X_Audio_codecs;
 
+// WebAudioAPIを使っているはずなのに、マナーモードで音が出る!?
+// http://qiita.com/gonshi_com/items/e41dbb80f5eb4c176108
+// HTML Audio、もしくはHTML Videoをページ内で1つでも使用していた場合、そのページでは WebAudioAPI の音がマナーモード時にも鳴ってしまう
+
 if( X_Audio_constructor ){
        //http://himaxoff.blog111.fc2.com/blog-entry-97.html
        //引数なしで new Audio() とすると、Operaでエラーになるそうなので注意。
@@ -78,7 +82,7 @@ if( X_Audio_constructor ){
 };
 
 
-var X_WebAudio_context      =  // 4s 以下ではない iPad 2G または iPad mini 1G 以下ではない, iPod touch 4G 以下ではない
+var X_WebAudio_Context      =  // 4s 以下ではない iPad 2G または iPad mini 1G 以下ではない, iPod touch 4G 以下ではない
                                                                !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] &&
                                                                // iOS7 以上で HTML Audio が鳴らない問題を見ていくよ
                                                                // !X_UA[ 'iOS' ] &&
@@ -90,11 +94,13 @@ var X_WebAudio_context      =       // 4s 以下ではない iPad 2G または iPad mi
                                                                //!X_UA[ 'Blink' ] &&
                                                                // Firefox40.0.5 + Windows8 で音声が途中から鳴らなくなる
                                                                // Firefox41.0.1 + Windows8 で音声が途中から鳴らなくなる
-                                                               !( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 46 && X_UA[ 'Windows' ] ) &&
-                                                               ( window[ 'AudioContext' ] || window[ 'webkitAudioContext' ] ),
+                                                               !( 40 <= X_UA[ 'Gecko' ] && /* X_UA[ 'Gecko' ] < 48 && */ X_UA[ 'Windows' ] ) &&
+                                                               ( window[ 'AudioContext' ] || window[ 'webkitAudioContext' ] || window[ 'mozAudioContext' ] ),          
+       X_WebAudio_context,
        X_WebAudio_BUFFER_LIST  = [],
        X_WebAudio_need1stTouch = X_UA[ 'iOS' ],
-       X_WebAudio_touchState   = X_WebAudio_need1stTouch,
+       X_WebAudio_isNoTouch    = X_WebAudio_need1stTouch,
+       X_WebAudio_needRateFix  = X_WebAudio_need1stTouch,
        X_WebAudio,
        X_WebAudio_BufferLoader,
        X_WebAudio_fpsFix;
@@ -102,9 +108,46 @@ var X_WebAudio_context      =      // 4s 以下ではない iPad 2G または iPad mi
 /*
  * iPhone 4s 以下、iPad2以下、iPad mini 1以下, iPod touch 4G 以下は不可
  */
-if( X_WebAudio_context ){
+if( X_WebAudio_Context ){
+       
+       X_WebAudio_context = new X_WebAudio_Context;
        
-       X_WebAudio_context = new X_WebAudio_context;
+       // http://lilting.ch/3323.html
+       // 【間に合わせ】iOS9系でのWebAudioの音割れ対処について
+       /*
+       if( X_WebAudio_needRateFix ){
+               X_WebAudio_context.close();
+               X_WebAudio_context = new X_WebAudio_Context;
+       }; */
+
+       /*
+        * TODO X_TEMP へ
+        * http://qiita.com/simiraaaa/items/79a9ac972cc76fb58d93
+        * [WebAudio API] iOS9で音が歪む、遅い、低い、割れる等の回避方法
+        */
+       if( X_WebAudio_needRateFix ){
+               X_TEMP.webAudioSampleRateFix = function( sampleRate ){
+                   X_TEMP.webAudioDummyPlay( sampleRate );
+
+                       if( true || X_WebAudio_context[ 'sampleRate' ] !== sampleRate ){
+                               // alert( '[debug]iOSで音割れを検知、修復コードを実施 ctxSR:' + X_WebAudio_context[ 'sampleRate' ] + ' abfSR:' + sampleRate );
+                               
+                               X_WebAudio_context.close && X_WebAudio_context.close();
+                               X_WebAudio_context = new X_WebAudio_Context;
+                               
+                               X_TEMP.webAudioDummyPlay( sampleRate );
+                       };
+                       
+                       delete X_TEMP.webAudioSampleRateFix;
+                       delete X_TEMP.webAudioDummyPlay;
+               };
+               X_TEMP.webAudioDummyPlay = function( sampleRate, source ){
+                   source = X_WebAudio_context[ 'createBufferSource' ]();
+                   source.buffer = X_WebAudio_context[ 'createBuffer' ]( 1, 1, sampleRate );
+                   source[ 'connect' ]( X_WebAudio_context[ 'destination' ] );
+                   source.start ? source.start( 0 ) : source[ 'noteOn' ] ? source[ 'noteOn' ]( 0 ) : source[ 'noteGrainOn' ]( 0 );
+               };
+       };
        
        X_WebAudio_BufferLoader = X_EventDispatcher[ 'inherits' ](
                'X.WebAudio.BufferLoader',
@@ -212,8 +255,7 @@ if( X_WebAudio_context ){
                        
                }
        );
-       
-       
+
        X_WebAudio = X_AudioBase[ 'inherits' ](
                'X.WebAudio',
                X_Class.POOL_OBJECT,
@@ -229,9 +271,12 @@ if( X_WebAudio_context ){
                audioBuffer     : null,
                bufferSource    : null,
             gainNode        : null,
+            
+            bufferPlay      : '',
+            bufferStop      : '',
             //_onended        : null,
             
-                       'Constructor' : function( disatcher, url, option ){                             
+                       'Constructor' : function( dispatcher, url, option ){                            
                                var i = 0,
                                        l = X_WebAudio_BUFFER_LIST.length,
                                        loader;
@@ -259,7 +304,7 @@ if( X_WebAudio_context ){
                                        this.loader = loader = X_WebAudio_BufferLoader( this, url );
                                };
                                
-                               this.disatcher = disatcher || this;
+                               this.dispatcher = dispatcher || this;
                                this.setState( option );
                                
                                this[ 'listenOnce' ]( X_EVENT_KILL_INSTANCE, this.onKill );
@@ -269,6 +314,11 @@ if( X_WebAudio_context ){
                                } else {
                                        loader[ 'listenOnce' ]( X_EVENT_COMPLETE, this, this._onLoadBufferComplete );
                                };
+                               
+                               if( X_WebAudio_isNoTouch ){
+                                       X_TEMP.xWebAudioInstances = X_TEMP.xWebAudioInstances || [];
+                                       X_TEMP.xWebAudioInstances.push( this );
+                               };
                        },
                        
                        onKill : function(){
@@ -283,6 +333,10 @@ if( X_WebAudio_context ){
                    //this._onended     && X_Closure_correct( this._onended );  
        
                    this.gainNode     && this.gainNode.disconnect();
+                   
+                               if( X_WebAudio_isNoTouch ){
+                                       X_TEMP.xWebAudioInstances.splice( X_TEMP.xWebAudioInstances.indexOf( this ), 1 );
+                               };
                        },
                                _onLoadBufferComplete : function( e ){
                                        var loader = this.loader,
@@ -292,7 +346,7 @@ if( X_WebAudio_context ){
                                        
                        if ( !buffer ) {
                                this.error = loader.errorState;
-                           this.disatcher[ 'dispatch' ]({
+                           this.dispatcher[ 'dispatch' ]({
                                                                type    : X_EVENT_ERROR,
                                                                error   : loader.errorState,
                                                                message : loader.errorState === 1 ?
@@ -306,11 +360,11 @@ if( X_WebAudio_context ){
                        this.audioBuffer = buffer;
                        this.duration    = buffer.duration * 1000;
 
-                                       this.disatcher[ 'asyncDispatch' ]( X_WebAudio_touchState ? X_EVENT_MEDIA_WAIT_FOR_TOUCH : X_EVENT_READY );
+                                       this.dispatcher[ 'asyncDispatch' ]( X_WebAudio_isNoTouch ? X_EVENT_MEDIA_WAIT_FOR_TOUCH : X_EVENT_READY );
                                },
                        
                        actualPlay : function(){
-                               var e, begin, end;
+                               var xWebAudio, begin, end;
                                
                                console.log( '[WebAudio] play abuf:' + !!this.audioBuffer );
                                
@@ -318,42 +372,48 @@ if( X_WebAudio_context ){
                        this._playReserved = true;
                        return;
                    };
-                               
-                               if( X_WebAudio_touchState ){
-                                       e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ];
+
+                               if( X_WebAudio_isNoTouch ){
+                                       //@dev{
+                                       var e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ];
                                        if( !e || !e[ 'pointerType' ] ){
                                                // alert( 'タッチイベント以外での play! ' + ( e ? e.type : '' ) );
                                                return;
                                        };
+                                       //@}
+                                       
                                        // http://qiita.com/uupaa/items/e5856e3cb2a9fc8c5507
                                        // iOS9 + touchstart で呼んでいた場合、 X_ViewPort['listenOnce']('pointerup',this,this.actualPlay())
-                                       this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );
+                                       this.dispatcher[ 'asyncDispatch' ]( X_EVENT_READY );
+                                       
+                                       // Web Audio インスタンスが複数生成された場合、一つの Web Audio に対してタッチによる play が開始されたら、
+                                       //  1. 同時に生成された他の X.Audio インスタンスに対して READY イベントを発する
+                                       //  2. 以降の X.Audio インスタンス生成時に needTouchForPlay フラグは false
+                                       // ちなみに HTML Audio インスタンスは各々にタッチが必要     
+                                       //X_WebAudio_isNoTouch = false;
+                                       
+                                       while( xWebAudio = X_TEMP.xWebAudioInstances.pop() ){
+                                               xWebAudio !== this && xWebAudio[ 'asyncDispatch' ]( X_EVENT_READY );
+                                       };
+                                       delete X_TEMP.xWebAudioInstances;
+
+                                       X_WebAudio_isNoTouch = false;
+
+                                       X_TEMP.webAudioSampleRateFix && X_TEMP.webAudioSampleRateFix( this.audioBuffer[ 'sampleRate' ] );
                                };
-                               X_WebAudio_touchState = false;
                                
                                end   = X_Audio_getEndTime( this );
                                begin = X_Audio_getStartTime( this, end, true );
                                
                                console.log( '[WebAudio] play ' + begin + ' -> ' + end + ' loop: ' + this.autoLoop + ' :' + this.loopStartTime + ' -> ' + this.loopEndTime );
-                               
-                               if( this.bufferSource ) this._sourceDispose();
-                               if( !this.gainNode ){
-                                       this.gainNode = X_WebAudio_context[ 'createGain' ] ? X_WebAudio_context[ 'createGain' ]() : X_WebAudio_context[ 'createGainNode' ]();
-                                       this.gainNode[ 'connect' ]( X_WebAudio_context[ 'destination' ] );
-                               };
-                               
-                   this.bufferSource        = X_WebAudio_context[ 'createBufferSource' ]();
-                   this.bufferSource.buffer = this.audioBuffer;
+                               this._createTree( begin, end );
                    
                    /* win8.1 Firefox45, win8.1 Chrome48 で動かなくなる...
                    if( this.bufferSource[ 'loop' ] = this.autoLoop ){
                        this.bufferSource[ 'loopStart' ] = 0 <= this.loopStartTime ? this.loopStartTime / 1000 : begin / 1000;
                        this.bufferSource[ 'loopEnd'   ] = 0 <= this.loopEndTime   ? this.loopEndTime   / 1000 : end   / 1000;
                    }; */
-                   
-                   this.bufferSource[ 'connect' ]( this.gainNode );
-                   this.gainNode[ 'gain' ].value = this.gain;
-                   
+
                    // おかしい、stop 前に外していても呼ばれる、、、@Firefox33.1
                    // 破棄された X.Callback が呼ばれて、obj.proxy() でエラーになる。Firefox では、onended は使わない
                    // 多くのブラウザで onended は timer を使ったカウントより遅いので使わない
@@ -364,16 +424,7 @@ if( X_WebAudio_context ){
                        //this._timerID && X_Timer_remove( this._timerID );
                                        //this._timerID = X_Timer_once( end - begin, this, this._onEnded );
                 //};
-       
-                   if( this.bufferSource.start ){
-                       this.bufferSource.start( 0, begin / 1000, ( end - begin ) / 1000 );
-                   } else
-                   if( this.bufferSource[ 'noteOn' ] ){
-                       this.bufferSource[ 'noteOn' ]( 0, begin / 1000, ( end - begin ) / 1000 );
-                   } else {
-                       this.bufferSource[ 'noteGrainOn' ]( 0, begin / 1000, ( end - begin ) / 1000 );
-                   };
-                   
+
                    this.playing      = true;
                    this._startPos    = begin;
                    this._endPosition = end;
@@ -381,20 +432,34 @@ if( X_WebAudio_context ){
                    this._interval    = this._interval || X_Timer_add( 100, 0, this, this._onInterval );
                        },
                        
+                               _createTree : function( begin, end ){
+                                       if( this.bufferSource ) this._sourceDispose();
+                                       
+                                       if( !this.gainNode ){
+                                               this.gainNode = X_WebAudio_context[ 'createGain' ] ? X_WebAudio_context[ 'createGain' ]() : X_WebAudio_context[ 'createGainNode' ]();
+                                               this.gainNode[ 'connect' ]( X_WebAudio_context[ 'destination' ] );
+                                       };
+                                       
+                           this.bufferSource        = X_WebAudio_context[ 'createBufferSource' ]();
+                           this.bufferSource.buffer = this.audioBuffer;
+                           this.bufferSource[ 'connect' ]( this.gainNode );
+                           
+                           this.gainNode[ 'gain' ].value = this.gain;
+                           
+                           if( !this.bufferPlay ){
+                               this.bufferPlay = this.bufferSource.start ? 'start' : this.bufferSource[ 'noteOn'  ] ? 'noteOn'  : 'noteGrainOn';
+                               this.bufferStop = this.bufferSource.stop  ? 'stop'  : 'noteOff';
+                           };
+                                       // https://developer.mozilla.org/ja/docs/Web/API/AudioBufferSourceNode
+                                       // AudioBufferSourceNode.start()の呼び出しは一度しかできません。
+                           this.bufferSource[ this.bufferPlay ]( 0, begin / 1000, ( end - begin ) / 1000 );
+                               },
+                       
                                _sourceDispose : function(){
                            this.bufferSource.disconnect();
                            //delete this.bufferSource.onended;
                            delete this.bufferSource;
                        },
-
-                               /* 
-                               _onInterval : function(){
-                                       if( !this.playing ){
-                                               delete this._interval;
-                                               return X_CALLBACK_UN_LISTEN;
-                                       };
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
-                               }, */
                                        
                                _onInterval : function(){
                                        var time;
@@ -405,14 +470,14 @@ if( X_WebAudio_context ){
                                //console.log( '> onEnd ' + ( this.playing && ( X_WebAudio_context.currentTime * 1000 - this._startTime ) ) + ' < ' + ( this._endPosition - this._startPos ) );
 
                                if( time < 0 ){
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
+                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
                                        return;
                                };
                                
                                if( this.autoLoop ){
-                                       if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
+                                       if( !( this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
                                                this.looped = true;
-                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
+                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
                                                this.actualPlay();
                                        } else {
                                                                delete this._interval;
@@ -420,7 +485,7 @@ if( X_WebAudio_context ){
                                        };
                                } else {
                                        this.actualPause();
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
+                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
                                };
                            };
                                },
@@ -433,8 +498,7 @@ if( X_WebAudio_context ){
                                delete this.playing;
 
                    if( this.bufferSource ){
-                       this.bufferSource.stop ? 
-                               this.bufferSource.stop( 0 ) : this.bufferSource[ 'noteOff' ]( 0 );
+                       this.bufferSource[ this.bufferStop ]( 0 );
                    };
                        },
                        
index 1c88ae5..ab98389 100644 (file)
@@ -54,8 +54,8 @@ var
        \r
        // Opera Mobile 12 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する\r
        X_HTMLAudio_currentTimeFix  = !!X_UA[ 'OperaMobile' ] || !!X_UA[ 'OperaTablet' ],\r
-       // Firefox44.0.2 で音声の再生開始に難あり...\r
-       X_HTMLAudio_playStartFix    = X_UA[ 'Windows' ] && X_UA[ 'Gecko' ] === 44,\r
+       // Firefox44.0.2 で音声の再生開始に難あり... 49 でも確認, あるいはCGIで動的に生成しているmp3自体に問題があるのかも\r
+       X_HTMLAudio_playStartFix    = X_UA[ 'Windows' ] && 44 <= X_UA[ 'Gecko' ],\r
 \r
        X_HTMLAudio_volumeFix       = X_UA[ 'Chrome' ],\r
        /*\r
@@ -118,10 +118,10 @@ if( X_Audio_constructor ){
                        \r
                        _seekingFixON     : false,\r
                        \r
-                       'Constructor' : function( disatcher, source, option ){\r
+                       'Constructor' : function( dispatcher, source, option ){\r
                                var raw;\r
                                \r
-                               this.disatcher = disatcher || this;\r
+                               this.dispatcher = dispatcher || this;\r
                                this._src          = source;\r
                                \r
                                if( X_HTMLAudio_shortPlayFix ){\r
@@ -188,7 +188,7 @@ if( X_Audio_constructor ){
                        },\r
                        \r
                        onDebug : function( e ){\r
-                               this.disatcher[ 'dispatch' ]( {\r
+                               this.dispatcher[ 'dispatch' ]( {\r
                                        type       : X_EVENT_DEBUG,\r
                                        'rawEvent' : e.type,\r
                                        'current'  : this[ '_rawObject' ].currentTime,\r
@@ -232,7 +232,7 @@ if( X_Audio_constructor ){
                                                        for( i = time = 0, l = buf && buf.length; i < l; ++i ){\r
                                                                time += buf[ 'end' ]( i ) - buf[ 'start' ]( i );\r
                                                        };\r
-                                                       this.disatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : time * 1000 / this.duration * 100 } );\r
+                                                       this.dispatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : time * 1000 / this.duration * 100 } );\r
                                                };\r
                                                break;\r
                                        \r
@@ -379,29 +379,36 @@ if( X_Audio_constructor ){
                                if( this._touchState === 1 ){\r
                                        if( e.type === X_HTMLAudio_playTrigger ){\r
                                                this._touchState = 2;\r
-                                               this.disatcher[ 'asyncDispatch' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH );\r
+                                               this.dispatcher[ 'asyncDispatch' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH );\r
                                        };\r
                                } else\r
                                if( ended ){\r
                                        if( this.autoLoop ){\r
-                                               if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){\r
+                                               if( !( this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){\r
                                                        this.looped = true;\r
-                                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );\r
+                                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );\r
                                                        this.actualPlay( X_HTMLAudio_endedFixCWV && actualEnded, X_HTMLAudio_endedFixAOSP3 && actualEnded );\r
                                                };\r
                                        } else {\r
                                                this.seekTime = 0;\r
                                                delete this.playing;\r
-                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );\r
+                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );\r
                                        };\r
                                } else\r
                                if( this._readyState === 1 && this.duration ){\r
                                        this._readyState |= 2;\r
-                                       this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );\r
+                                       this.dispatcher[ 'asyncDispatch' ]( X_EVENT_READY );\r
+                                       \r
+                                       // TODO 勝手に play する環境があるので pause() を実施\r
+                                       /*\r
+                                       if( !this.playing && !this.autoplay && !this._playReserved && !X_HTMLAudio_pauseFix ){\r
+                                               this.actualPause();\r
+                                       }; */\r
+                                       \r
                                        console.log( '> Audio Loaded!! ' + e.type + ' d:' + ( this.duration | 0 ) );\r
                                } else\r
                                if( eventType ){\r
-                                       this.disatcher[ 'dispatch' ]( eventType );\r
+                                       this.dispatcher[ 'dispatch' ]( eventType );\r
                                };\r
                        },\r
 \r
@@ -488,7 +495,7 @@ if( X_Audio_constructor ){
                                                this._endedFixON = true;\r
                                                raw.src = this._src;\r
                                                console.log( '△ onEndedFix の開始' );\r
-                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
+                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
                                        };\r
                                };\r
 \r
index ea3dad7..09fa4cd 100644 (file)
@@ -53,7 +53,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                        _lastState      : '',\r
                        _interval       : 0, // setInterval timer id\r
                        \r
-                       'Constructor' : function( disatcher, source, option ){\r
+                       'Constructor' : function( dispatcher, source, option ){\r
                                !X_SLAudio_uid && X_TEMP.slaudioInit();\r
                                \r
                                /*\r
@@ -61,7 +61,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                 * http://www.atmarkit.co.jp/fdotnet/dotnettips/902slobjcallfromjs/slobjcallfromjs.html\r
                                 * このページのサンプルは sl5+firefox32 環境で動いている。xaml を js から利用する形ではなく、.xap を sl4 以下で作るのがよさそう.\r
                                 */\r
-                               this.disatcher   = disatcher || this;\r
+                               this.dispatcher   = dispatcher || this;\r
                                this._source     = source;\r
                                // X.Audio._slOnload_ は不可\r
                        this._onload     = 'XAudioSilverlightOnLoad' + ( ++X_SLAudio_uid );\r
@@ -122,7 +122,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                                if( this.playing ){\r
                                                        //X_Timer_once( 16, this, this.actualPlay );\r
                                                } else {\r
-                                                       this.disatcher[ 'dispatch' ]( X_EVENT_ERROR ); // open failed\r
+                                                       this.dispatcher[ 'dispatch' ]( X_EVENT_ERROR ); // open failed\r
                                                        this[ 'kill' ]();                                                       \r
                                                };\r
                                                break;\r
@@ -130,7 +130,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                        case 'MediaOpened' :\r
                                                // http://msdn.microsoft.com/ja-jp/library/bb979710(VS.95).aspx\r
                                                this.duration = this[ '_rawObject' ][ 'NaturalDuration' ][ 'Seconds' ] * 1000;\r
-                               this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );\r
+                               this.dispatcher[ 'asyncDispatch' ]( X_EVENT_READY );\r
                                                break;\r
 \r
                                        case 'MediaEnded' :\r
@@ -157,10 +157,10 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                                        case 'Opening' :\r
                                                                switch( this._lastUserAction ){\r
                                                                        case 'play' :\r
-                                                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
+                                                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
                                                                                break;\r
                                                                        case 'seek' :\r
-                                                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );\r
+                                                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );\r
                                                                                break;\r
                                                                        case 'pause' :\r
                                                                                break;\r
@@ -177,7 +177,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                                                this.playing = false;\r
                                                                this._ended  = true;\r
                                                                this._paused = false;\r
-                                                               this.disatcher[ 'dispatch' ]( X_EVENT_ERROR );\r
+                                                               this.dispatcher[ 'dispatch' ]( X_EVENT_ERROR );\r
                                                                this[ 'kill' ]();\r
                                                                break;\r
 \r
@@ -195,7 +195,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                                                                //this.seekTime = 0;\r
                                                                                this._ended  = true;\r
                                                                                this._paused = false;\r
-                                                                               //this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );\r
+                                                                               //this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );\r
                                                                                //this.setCurrentTime( this.startTime );\r
                                                                                break;\r
                                                                        case 'pause':\r
@@ -214,7 +214,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                                                //this.playing = true;\r
                                                                this._ended  = false;\r
                                                                this._paused = false;\r
-                                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );\r
+                                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );\r
                                                                break;\r
 \r
                                                        // stop()\r
@@ -230,7 +230,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                                break;\r
 \r
                                        case X_EVENT_KILL_INSTANCE :\r
-                                               this.playing && this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );\r
+                                               this.playing && this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );\r
                                                this.playing && this.actualPause();\r
                                        \r
                                                if( this._onload ){\r
@@ -297,7 +297,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                                delete this._interval;\r
                                                return X_CALLBACK_UN_LISTEN;\r
                                        };\r
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );\r
+                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );\r
                                },\r
                                \r
                                _onEnded : function(){\r
@@ -315,7 +315,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                        console.log( '    > ' + time );\r
                                        this._ended && this[ '_rawObject' ].play();\r
                                        this._ended = false;\r
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
+                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
                                        this._timerID = X_Timer_once( X_Audio_getEndTime( this ) - time, this, this._onEnded );\r
                                        return;\r
                                };\r
@@ -331,16 +331,16 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
                                \r
                                if( this.autoLoop ){\r
                                        console.log( '========= loop?' );\r
-                                       if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){\r
+                                       if( !( this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){\r
                                                console.log( '========== loopした' );\r
                                                this.looped = true;\r
-                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );\r
+                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );\r
                                                this.actualPlay();\r
                                        };\r
                                } else {\r
                                        console.log( '========= pause' );\r
                                        this.actualPause();\r
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );\r
+                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );\r
                                };\r
                            };\r
                                },\r
index 5ee0c80..cb750fb 100644 (file)
@@ -22,8 +22,8 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
                _seekDirection  : 0,
                        _timerID        : 0,
                        
-                       'Constructor' : function( disatcher, source, option ){
-                               this.disatcher   = disatcher || this;
+                       'Constructor' : function( dispatcher, source, option ){
+                               this.dispatcher   = dispatcher || this;
                                this._source     = source;
                                
                                if( 7 <= X_Plugin_WMP_VERSION ){
@@ -71,7 +71,7 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
                                                break;
 
                                        case X_EVENT_KILL_INSTANCE :
-                                               this.playing && this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
+                                               this.playing && this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
                                                this.playing && this.actualPause();
                                            this.wmp.stop();
                                                this.xnodeObject[ 'kill' ]();
@@ -120,7 +120,7 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
                                                progress = this.wmp[ 'BufferingProgress' ];
                                                };
                                                if( progress < 100 ){
-                                                       this.disatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : progress } );
+                                                       this.dispatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : progress } );
                                                } else {
                                                        this._readyState = 2;
                                                        if( 7 <= X_Plugin_WMP_VERSION ){
@@ -128,7 +128,7 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
                                                        } else {
                                                        this.duration = this.wmp[ 'Duration' ] * 1000 | 0;
                                                        };
-                                                       this.disatcher[ 'dispatch' ]( X_EVENT_READY );
+                                                       this.dispatcher[ 'dispatch' ]( X_EVENT_READY );
                                                };
                                        } else
                                        // ended の判定
@@ -138,33 +138,33 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
                                // waiting
                                if( this._seekDirection ){
                                        if( this._seekDirection === 1 ? ( time < this._beginTime ) : ( this._lastCurrentTime <= time ) ){
-                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );
+                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );
                                                return;
                                        };
                                        delete this._seekDirection;
                                };
                                if( time === this._lastCurrentTime ){
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
+                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
                                        return;
                                };              
                                this._lastCurrentTime = time;
                                
                                // ended ではない
                                if( time - X_Audio_getEndTime( this ) < -50 ){
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
+                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
                                        return;
                                };
                                
                                // ended
                                if( this.autoLoop ){
-                                       if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
+                                       if( !( this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
                                                this.looped = true;
-                                               this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
+                                               this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
                                                this.actualPlay();
                                        };
                                } else {
                                        this.actualPause();
-                                       this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
+                                       this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
                                        delete this._timerID;
                                                        return X_CALLBACK_UN_LISTEN;
                                };
index f0183bc..dc4ec65 100644 (file)
@@ -28,7 +28,7 @@ var X_AudioSprite_shouldUse         = X_HTMLAudio && ( X_UA[ 'iOS' ] || X_UA[ 'A
                bgmName     : '',\r
                bgmLooped   : false,\r
                bgmPlaying  : false,\r
-               event       : null\r
+               tmpEvent    : null\r
        },\r
        X_AudioSprite,\r
        X_AudioSprite_numTracks,\r
@@ -93,7 +93,7 @@ X[ 'AudioSprite' ] = function( setting ){
        \r
        X_Audio_startDetectionBackend(\r
                X_Audio_BACKENDS[ 0 ],\r
-               X_AudioSprite,\r
+               X_AudioSprite, // dispatcher として\r
                X_Array_copy( urls ),\r
                {\r
                        'volume'    : 0 <= volume && volume <= 1 ? volume : 1,\r
@@ -369,7 +369,7 @@ function X_AudioSprite_backendHandler( e ){
                                // HTMLAudio\r
                                ( e[ 'needTouchForLoad' ] && ( _e[ 'needTouchForLoad' ] = true ) )\r
                        ){\r
-                               X_AudioSprite_TEMP.event = _e;\r
+                               X_AudioSprite_TEMP.tmpEvent = _e;\r
                                last[ 'listenOnce' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH, X_AudioSprite_backendHandler );\r
                        } else {\r
                                X_AudioSprite[ 'asyncDispatch' ]( _e );\r
@@ -388,8 +388,8 @@ function X_AudioSprite_backendHandler( e ){
                \r
                case X_EVENT_MEDIA_WAIT_FOR_TOUCH :\r
                        // TODO 全ての track の MEDIA_WAIT_FOR_TOUCH で!\r
-                       X_AudioSprite[ 'asyncDispatch' ]( X_AudioSprite_TEMP.event );\r
-                       delete X_AudioSprite_TEMP.event;\r
+                       X_AudioSprite[ 'asyncDispatch' ]( X_AudioSprite_TEMP.tmpEvent );\r
+                       delete X_AudioSprite_TEMP.tmpEvent;\r
                        break;\r
                \r
                case X_EVENT_PROGRESS :\r
@@ -398,6 +398,21 @@ function X_AudioSprite_backendHandler( e ){
                \r
                case X_EVENT_READY :\r
                        console.log( 'X.AudioSprite - Ready!' );\r
+                       \r
+                       if( X_AudioSprite_TEMP.tmpEvent ){\r
+                               // このタイミングで tmpEvent が存在する場合は、タッチをスキップして Web Audio が再生可能になった\r
+                               // つまり他の Web Audio インスタンスでタッチによる再生が開始され、自身も再生可能になった\r
+                               \r
+                               _e = X_AudioSprite_TEMP.tmpEvent;\r
+                               _e[ 'needTouchForPlay' ] = false;\r
+                               \r
+                               X_AudioSprite\r
+                                       [ 'unlisten' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH, X_AudioSprite_backendHandler )\r
+                                       [ 'asyncDispatch' ]( _e );\r
+                               \r
+                               delete X_AudioSprite_TEMP.tmpEvent;\r
+                       };                      \r
+                       \r
                        for( i = 0; i < X_AudioSprite_numTracks; ++i ){\r
                                track = X_AudioSprite_TEMP.tracks[ i ];\r
                                ( track.autoplay || track._playReserved ) && track.actualPlay();\r