OSDN Git Service

Version 0.6.119, add ended event to X.Audio.Sprite & GPU layer off.
authoritozyun <itozyun@user.sourceforge.jp>
Sun, 14 Dec 2014 22:14:02 +0000 (07:14 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Sun, 14 Dec 2014 22:14:02 +0000 (07:14 +0900)
0.6.x/js/02_dom/02_XNode.js
0.6.x/js/02_dom/10_XNodeAnime.js
0.6.x/js/05_util/01_XNinjaIframe.js
0.6.x/js/06_net/01_XNetXHR.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/10_XAudioSprite.js

index 01588f9..9c44e1d 100644 (file)
@@ -1377,6 +1377,8 @@ var X_Node__afterActualCreate =
 \r
 var X_Node__actualRemove =\r
        X_UA_DOM.W3C ?\r
+               // GPUレイヤーにいるうちは remove しない。-> GPU解除してから remove する\r
+               // Firefox34 では遭遇せず、Safari で何度かアニメーションしているうちに発生\r
                ( function( that, isChild ){\r
                        var xnodes = that._xnodes,\r
                                elm    = that._rawObject,\r
index 2adfebb..0343ec8 100644 (file)
@@ -64,7 +64,8 @@ var X_Node_ANIMATIONS            = [],
        X_Node_Anime_needsDetection  = false,\r
        X_Node_Anime_hasTransform    = !!X_Node_CSS_VENDER_PREFIX[ 'transform' ],\r
        /* Opera mobile で  translateZ(0) が有効だと XY が 0 0 になる */\r
-       X_Node_Anime_translateZ      = X_Node_CSS_VENDER_PREFIX[ 'perspective' ] && !X.UA.OperaMobile && !X.UA.OperaTablet ? ' translateZ(0)' : '',\r
+       /* GPUレイヤーにいる間に要素のコンテンツを変更をすると transitionend が動かなくなるっぽい Mac safari と firefox, 手当てが済むまでここは常に false */\r
+       X_Node_Anime_translateZ      = '', //X_Node_CSS_VENDER_PREFIX[ 'perspective' ] && !X.UA.OperaMobile && !X.UA.OperaTablet ? ' translateZ(0)' : '',\r
        X_Node_Anime_hasTransition   = !!X_Node_CSS_VENDER_PREFIX[ 'transitionDelay' ] && !X.UA.Opera, // Opera12(XP,8.1) 切った方がスムース\r
        X_Node_Anime_transitionProps = X_Node_Anime_hasTransform ? X_Node_CSS_VENDER_PREFIX[ 'transform' ] : 'left,top';\r
 \r
@@ -134,10 +135,10 @@ function X_Node_Anime_reserveUpdate( before ){
                X_Node_Anime_reserved = true;\r
                \r
                if( X_Node_updateTimerID ){\r
-                       console.log( before ? '> BEFORE_UPDATE' : '> UPDATED' );\r
+                       //console.log( before ? '> BEFORE_UPDATE' : '> UPDATED' );\r
                        X_System.listenOnce( before ? X.Event.BEFORE_UPDATE : X.Event.UPDATED, X_Node_Anime_updateAnimations );\r
                } else {\r
-                       console.log( '> Timer' );\r
+                       //console.log( '> Timer' );\r
                        // Opera12 requestAnimationFrame では transition が動かない、、、\r
                        X_Node_Anime_updateTimerID =\r
                                X_UA.Opera ?\r
@@ -150,7 +151,7 @@ function X_Node_Anime_reserveUpdate( before ){
 function X_Node_Anime_updateAnimations( v ){\r
        var i = X_Node_ANIMATIONS.length, ret, c = false;\r
        \r
-       console.log( v.type || v );\r
+       //console.log( v.type || v );\r
        \r
        //console.log( 'updateAnimations ' + i + ' ' + X_Node_Anime_needsDetection );\r
        \r
@@ -311,14 +312,14 @@ function X_Node_Anime_updateAnimation( xnode ){
                \r
                case 15 :\r
                        // GPU有効で停止(待機)している xnode の解除\r
-                       console.log( 'GPU有効で停止(待機)している xnode の解除' + xnode._tag + xnode.getOrder() );\r
+                       //console.log( 'GPU有効で停止(待機)している xnode の解除' + xnode._tag + xnode.getOrder() );\r
                        X_Node_Anime_clearTransition( xnode );\r
                        X_Node_Anime_updatePosition( xnode, obj.destX, obj.destY, obj.destA, false );\r
                        obj.gpuTimerID && X.Timer.remove( obj.gpuTimerID );\r
                        return true;\r
                \r
                case 100 : // stop() : アニメーションの中断して削除\r
-                       console.log( 'stop() gpu:' + obj.gpuParent );\r
+                       //console.log( 'stop() gpu:' + obj.gpuParent );\r
                        current = X_Node_Anime_getComputedPosition( xnode );\r
                                                \r
                        X_Node_Anime_clearTransition( xnode );\r
@@ -350,7 +351,7 @@ function X_Node_Anime_onTransitionEnd(){
        this._anime.phase = 3;\r
        X_Node_Anime_needsDetection = true;\r
        X_Node_Anime_reserveUpdate();\r
-       console.log( 'トランジション終了' );\r
+       //console.log( 'トランジション終了' );\r
        return X.Callback.UN_LISTEN | X.Callback.PREVENT_DEFAULT | X.Callback.STOP_PROPAGATION;\r
 };\r
 \r
index 8a026f0..a72e64d 100644 (file)
@@ -13,7 +13,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits(
                \r
                _iwin        : null,\r
                \r
-               _html        : '',\r
+               _contentHTML : '',\r
                _name        : '',\r
                _ready       : false,\r
                \r
@@ -47,7 +47,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits(
                                this.xnodeIframe.css( { position : 'absolute' } );\r
                        };\r
                        \r
-                       if( html ) this._html = html;\r
+                       if( html ) this._contentHTML = html;\r
                },\r
                \r
                handleEvent : function( e ){\r
@@ -64,7 +64,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits(
                                        this.xnodeIframe.listen( [ X_UA.IE < 9 ? 'readystatechange' : 'load', 'error' ], this );\r
                                        \r
                                        if( !( X_UA.IE < 9 ) ){\r
-                                               this._html && X_Util_NinjaIframe_writeToIframe( this );\r
+                                               this._contentHTML && X_Util_NinjaIframe_writeToIframe( this );\r
                                                this._ready = true;\r
                                                return;\r
                                        };\r
@@ -73,7 +73,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits(
                                        if( ( raw.readyState !== 'complete' && raw.readyState !== 'loaded' ) ) return X.Callback.STOP_PROPAGATION;\r
                                        // ie9-\r
                                        if( !this._ready ){\r
-                                               this._html && X_Util_NinjaIframe_writeToIframe( this );\r
+                                               this._contentHTML && X_Util_NinjaIframe_writeToIframe( this );\r
                                                this._ready = true;\r
                                                return;\r
                                        };\r
@@ -90,14 +90,14 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits(
                        return X.Callback.STOP_PROPAGATION;                     \r
                },\r
                \r
-               refresh : function( opt_html ){\r
+               refresh : function( opt_contentHTML ){\r
                        var raw = this.xnodeIframe._rawObject,\r
                                idoc;\r
                                \r
                        this._ready = false;\r
                        \r
                        if( !this._iwin ){\r
-                               this._html = opt_html;\r
+                               this._contentHTML = opt_html;\r
                                return this;\r
                        };\r
                        \r
@@ -109,7 +109,7 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits(
                        \r
                        if( !opt_html ) return this;\r
                        \r
-                       this._html = opt_html;\r
+                       this._contentHTML = opt_html;\r
                        X_UA.IE < 9 || X_Util_NinjaIframe_writeToIframe( this );\r
                        \r
                        return this;\r
@@ -127,9 +127,9 @@ X.Util.NinjaIframe = X.EventDispatcher.inherits(
 function X_Util_NinjaIframe_writeToIframe( that ){\r
        var raw  = that.xnodeIframe._rawObject,\r
                idoc = raw.contentDocument || that._iwin.document,\r
-               html = that._html;\r
+               html = that._contentHTML;\r
                \r
-       delete that._html;\r
+       delete that._contentHTML;\r
        that._ready = true;\r
 \r
        idoc.open();\r
index 1ea396c..2ecd889 100644 (file)
@@ -94,6 +94,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
                        _type      : '',\r
                        _busy      : false,\r
                        _canceled  : false,\r
+                       _error     : false,\r
                        _percent   : 0,\r
                        _timerID   : 0,\r
                        \r
@@ -175,17 +176,17 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
                                if( raw.timeout !== undefined ){\r
                                        raw.timeout = timeout;\r
                                } else {\r
-                                       //this._timerID = X.Timer.once( timeout, this, this.onTimeout );\r
+                                       this._timerID = X.Timer.once( timeout, this, this.onTimeout );\r
                                };      \r
                                \r
                                // send 前にフラグを立てる,回線が早いと raw.send() 内で onload -> _busy = false ののち、 _busy = true するため。\r
                                this._busy = true;\r
                                \r
 \r
-                               //raw.send( postbody || '' );\r
-                               this._timerID = X.Timer.once( 16, this, this._lazySend, [ postbody || '', timeout ] );\r
+                               raw.send( postbody || '' );\r
+                               //this._timerID = X.Timer.once( 16, this, this._lazySend, [ postbody || '', timeout ] );\r
                        },\r
-                       \r
+                       /*\r
                        // send() 内で onload するケースがあり、そのときはイベントリスナが間に合わないので、タイマーをかませる。\r
                        _lazySend : function( postbody, timeout ){\r
                                if( this._rawObject.timeout === undefined ){\r
@@ -198,7 +199,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
                                // sendをonreadystatechangeの前に記述すると、ieでは動作しなくなります、、、。\r
                                // konquerorでエラーが発生するのでここでは、とりあえず、send('') としました。\r
                                this._rawObject.send( postbody );                               \r
-                       },\r
+                       }, */\r
                        \r
                        cancel : function(){\r
                                /* X.Net.XHR.CANCELABLE && */ this._rawObject.abort && this._rawObject.abort();\r
@@ -215,8 +216,14 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
                                // domes.lingua.heliohost.org/dom-intro/load-save2.html\r
                                // 規定上は open() を呼び出すと XMLHttpRequest オブジェクトが未送信状態に戻りますが、\r
                                // Opera 10.10、Safari 4.1 では、同一オリジン制限に違反した XMLHttpRequest オブジェクトは再度 open() しても未送信状態に戻りません。\r
-                               if( X_UA.Opera || X_UA.Webkit ){\r
-                                       \r
+                               \r
+                               // Timeout した Gecko の xhr.response に触るとエラー??\r
+                               if( X_UA.Opera || X_UA.Webkit || X_UA.Gecko ){\r
+                                       if( this._error ){\r
+                                               X_EventDispatcher_toggleAllEvents( this, false );\r
+                                               this._rawObject = new XMLHttpRequest();\r
+                                               X_EventDispatcher_toggleAllEvents( this, true );\r
+                                       };\r
                                };\r
 \r
                                // XMLHttpRequest の使い方\r
@@ -225,7 +232,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
                                this._rawObject.abort && this._rawObject.abort();\r
 \r
                                this._method   = this._type = '';\r
-                               this._canceled = this._busy = false;\r
+                               this._canceled = this._busy = this._error = false;\r
                                this._timerID && X.Timer.remove( this._timerID );\r
                                this._percent  = this._timerID = 0;\r
                        },\r
@@ -276,7 +283,7 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
                                        case 'load' :\r
                                                \r
                                                if( !live ) return this.reset();\r
-                                               if( this._percent === 100 ) return;\r
+                                               if( !this._busy ) return;\r
                                                \r
                                                \r
                                                this._percent = 100;\r
@@ -325,9 +332,9 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
                                                                        break;\r
                                                        };\r
 \r
-                                                       this.asyncDispatch( { type : X.Event.SUCCESS, status : status || 200, data : data } );                                                  \r
+                                                       this.asyncDispatch( 32, { type : X.Event.SUCCESS, status : status || 200, data : data } );                                                      \r
                                                } else {\r
-                                                       live && this.asyncDispatch( { type : X.Event.ERROR, status : raw.status || 0, percent : 100 } );\r
+                                                       live && this.asyncDispatch( 32, { type : X.Event.ERROR, status : raw.status || 0, percent : 100 } );\r
                                                };\r
                                                break;\r
                                        \r
@@ -340,12 +347,14 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
                                        \r
                                        case 'error' :\r
                                        //console.dir( e );\r
-                                               this._busy = false;\r
-                                               live && this.asyncDispatch( { type : X.Event.ERROR, status : raw.status } );\r
+                                               this._busy  = false;\r
+                                               this._error = X_UA.Opera || X_UA.Webkit;\r
+                                               live && this.asyncDispatch( 32, { type : X.Event.ERROR, status : raw.status } );\r
                                                break;\r
 \r
                                        case 'timeout' : // Gecko 12.0 https://developer.mozilla.org/ja/docs/XMLHttpRequest/Synchronous_and_Asynchronous_Requests\r
-                                               this._busy = false;\r
+                                               this._busy  = false;\r
+                                               this._error = !!X_UA.Gecko;\r
                                                this.asyncDispatch( X.Event.TIMEOUT );\r
                                                break;\r
                                };\r
index 8a44956..5572486 100644 (file)
@@ -47,7 +47,12 @@ function X_Audio_detectComplete( e, proxy, option, sourceList, source, ext, sup
        switch( e.type ){\r
                case 'support' :\r
                        proxy._backend = i;\r
-                       proxy.asyncDispatch( { type : 'backendfound', option : option, source : source, backendName : this.backendName } );\r
+                       proxy.asyncDispatch( {\r
+                               type        : 'backendfound',\r
+                               option      : option,\r
+                               source      : source,\r
+                               backendName : this.backendName\r
+                       } );\r
                        break;\r
                case 'nosupport' :\r
                        if( backend = X_Audio_BACKENDS[ i + 1 ] ){\r
index bb64a98..abd163b 100644 (file)
@@ -85,9 +85,16 @@ if( X_Audio_WebAudio_context ){
                                                return;
                                        
                                        case X.Event.SUCCESS :
-                                               console.log( 'WebAudio xhr success! ' + !!X_Audio_WebAudio_context.decodeAudioData );
+                                               console.log( 'WebAudio xhr success! ' + !!X_Audio_WebAudio_context.decodeAudioData + ' t:' + typeof e.data );
                                        // TODO 旧api
                                        // https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext
+                                       
+                                       // http://qiita.com/sou/items/5688d4e7d3a37b4e2ff1
+                                       // iOS 7.1 で decodeAudioData に処理が入った瞬間にスクリーンを長押しする(スクロールを繰り返す)と
+                                       // decoeAudioData の処理がキャンセルされることがある(エラーやコールバックの発火もなく、ただ処理が消滅する)。
+                                               if( X_Audio_WebAudio_context.createBuffer && X_UA.iOS ){
+                                                       this._onDecodeSuccess( X_Audio_WebAudio_context.createBuffer( e.data, false ) );
+                                               } else
                                                if( X_Audio_WebAudio_context.decodeAudioData ){
                                                        X_Audio_WebAudio_context.decodeAudioData( e.data,
                                                                this.onDecodeSuccess = X_Callback_create( this, this._onDecodeSuccess ),
@@ -250,8 +257,10 @@ if( X_Audio_WebAudio_context ){
                                };
                                
                                if( this.loop ){
-                                       this.looped = true;
-                                       ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play();
+                                       if( !( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) ){
+                                               this.looped = true;
+                                               this.play();
+                                       };
                                } else {
                                        this.pause();
                                        this.proxy.dispatch( 'ended' );
@@ -315,10 +324,9 @@ if( X_Audio_WebAudio_context ){
                {
                        backendName : 'Web Audio',
 
+                       // 
                        detect : function( proxy, source, ext ){
-                               var ok = ext === 'mp3' || ext === 'ogg';
-                               
-                               proxy.asyncDispatch( ok ? 'support' : 'nosupport' );
+                               proxy.asyncDispatch( X_Audio_codecs[ ext ] ? 'support' : 'nosupport' );
                        },
                        
                        klass : X_Audio_WebAudioWrapper
index ee712a5..e2cdca3 100644 (file)
@@ -13,16 +13,43 @@ var X_Audio_HTMLAudio_playTrigger =
        // Opera Mobile 12 android4.4.4 & 2.3.5 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する\r
        X_Audio_HTMLAudioWrapper_currentTimeFix  = !!X_UA.OperaMobile || !!X_UA.OperaTablet,\r
        // 一方 Desktop の Opera12 は、loadeddata 等では duration が infinity で、再生後の durationchange 時に duration が判明する。\r
+       // opera12 volume, mute の変更が2度目以降できない\r
        // duration 判明後には currentTime によるシークと、現在時間の取得が可能になる。\r
        // canplay で play() durationchange で duration が取れたら loadedmetadata->loadeddata -> canplay する\r
        // boombox.js に書いてあった currentTime の効かないブラウザってこいつのことみたい、、、\r
-       X_Audio_HTMLAudioWrapper_currentTimeFix2 = !X_Audio_HTMLAudioWrapper_currentTimeFix && X_UA.Opera,\r
+       // Opera12.17 Win32(XP) portable apps は勝手に再生が始まる、、、その際には timeupdate が発行されない、、、 iframe+image+audio で使わないときは破棄する、とか。\r
+       // opera11、10.54 WinXP はまとも、、、\r
+       // X_Audio_Sprite_handleEvent でも使用\r
+       X_Audio_HTMLAudioWrapper_durationFix     = !X_Audio_HTMLAudioWrapper_currentTimeFix && 12 < X_UA.Opera,\r
        \r
-       X_Audio_HTMLAudioWrapper_shortPlayFix    = !!X_UA.AndroidBrowser4;\r
+       X_Audio_HTMLAudioWrapper_shortPlayFix    = !!X_UA.AndroidBrowser4,\r
+       \r
+       X_Audio_codecs;\r
        \r
 \r
 if( window.HTMLAudioElement ){\r
        \r
+       X_Audio_rawAudio = new Audio;\r
+       \r
+       X_Audio_codecs = {\r
+      mp3  : X_Audio_rawAudio.canPlayType('audio/mpeg;'),\r
+      opus : X_Audio_rawAudio.canPlayType('audio/ogg; codecs="opus"'),\r
+      ogg  : X_Audio_rawAudio.canPlayType('audio/ogg; codecs="vorbis"'),\r
+      wav  : X_Audio_rawAudio.canPlayType('audio/wav; codecs="1"'),\r
+      aac  : X_Audio_rawAudio.canPlayType('audio/aac;'),\r
+      m4a  : (X_Audio_rawAudio.canPlayType('audio/x-m4a;') || X_Audio_rawAudio.canPlayType('audio/m4a;') || X_Audio_rawAudio.canPlayType('audio/aac;')),\r
+      mp4  : (X_Audio_rawAudio.canPlayType('audio/x-mp4;') || X_Audio_rawAudio.canPlayType('audio/mp4;') || X_Audio_rawAudio.canPlayType('audio/aac;')),\r
+      weba : X_Audio_rawAudio.canPlayType('audio/webm; codecs="vorbis"')\r
+       };\r
+       \r
+       (function( k, v ){\r
+               for( k in X_Audio_codecs ){\r
+                       v = X_Audio_codecs[ k ];\r
+                       X_Audio_codecs[ k ] = v && v !== 'no';\r
+               };\r
+       })();\r
+       \r
+       \r
        X_Audio_HTMLAudioWrapper = X.EventDispatcher.inherits(\r
                'X.AV.HTML5AudioWrapper',\r
                X.Class.POOL_OBJECT,\r
@@ -44,13 +71,12 @@ if( window.HTMLAudioElement ){
                        autoplay        : false,\r
                        volume          : 0.5,\r
 \r
-            _timerID         : 0,\r
                        _playTime        : 0,\r
                        _closed          : true,\r
                        _loaded          : false,\r
-                       _playForDuration : false,\r
-                       _currentTimeFix  : 0,\r
-                       _shortFix        : 0,\r
+                       _beginTime       : 0,\r
+                       _playForDuration : 0,\r
+                       _src             : '',\r
                        \r
                        Constructor : function( proxy, source, option ){\r
                                this.proxy   = proxy;\r
@@ -74,6 +100,8 @@ if( window.HTMLAudioElement ){
                                        //this._rawObject.load();\r
                                } else {\r
                                        this._rawObject = X_Audio_rawAudio || new Audio( source );// X_Doc_create( 'audio', { src : source } ).appendToRoot();//( X.X_Node_systemNode );\r
+                                       this._rawObject.autobuffer = false;\r
+                                       this._src = source;\r
                                };\r
                                \r
                                this.listen( [\r
@@ -106,7 +134,7 @@ if( window.HTMLAudioElement ){
                         */\r
                        handleEventProxy : function( e ){\r
                                var loaded;\r
-                               console.log( 'HTMLAudio ' + e.type );\r
+                               console.log( 'HTMLAudio ' + e.type + ' ' + this._rawObject.currentTime );\r
                                \r
                                switch( e.type ){\r
                                        case 'loadstart' :      //      ブラウザがコンテンツの検索を開始した場合に発生\r
@@ -119,17 +147,18 @@ if( window.HTMLAudioElement ){
                                                break;\r
                                        \r
                                        case 'canplay' :        //      今すぐに再生を再開できるが、バッファリングが不十分でコンテンツを最後まで表示できないと予測している場合に発生\r
-                                               if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){\r
-                                                       console.log( 'play ' + this.duration );\r
-                                                       this._playForDuration = true;\r
-                                                       this._rawObject.currentTime = 0;\r
+                                               if( X_Audio_HTMLAudioWrapper_durationFix && this._playForDuration === 0 ){\r
+                                                       console.log( 'start DurationFix for Desktop Opera12 - ' + this._rawObject.duration );\r
+                                                       this._playForDuration = 1;\r
+                                                       //this._rawObject.currentTime = 0;\r
                                                        this._rawObject.play();\r
-                                                       this._rawObject.currentTime = 0;\r
+                                                       this._rawObject.currentTime = this._beginTime / 1000; // 必要!\r
+                                                       return;\r
                                                };\r
                                        case 'loadedmetadata' : //      ブラウザがメディアリソースの長さと寸法を判定した場合に発生\r
                                        case 'loadeddata' :     //      コンテンツの表示を現在の再生位置で初めて行えるようになった場合に発生\r
                                        case 'canplaythrough' : //      今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生\r
-                                               if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ) return;\r
+                                               if( X_Audio_HTMLAudioWrapper_durationFix && this._playForDuration !== 2 ) return;\r
                                                this.duration = this._rawObject.duration * 1000;\r
                                                console.log( this.duration );\r
                                                break;\r
@@ -150,50 +179,70 @@ if( window.HTMLAudioElement ){
                                        case 'seeked' :         //      シークがfalseに変化した場合に発生\r
                                        case 'ratechange' :     // defaultPlaybackRate属性とplaybackRate属性のどちらかが更新された場合に発生\r
                                        case 'volumechange' :   // volume属性とmuted属性のどちらかが変化した場合に発生\r
-                                               if( this._playForDuration ) return;\r
+                                               if( this._playForDuration === 1 ) return;\r
                                                break;\r
                                                \r
                                        case 'timeupdate' :     //      通常の再生が行われ現在の再生位置の変化が起こった場合に発生\r
-                                               // console.log( this._rawObject.currentTime );\r
-                                               if( this._playForDuration ) return;                     \r
+                                               console.log( this._rawObject.currentTime );\r
+                                               if( this._playForDuration === 1 ){\r
+                                                       this._rawObject.currentTime = this._beginTime / 1000; // 必要!\r
+                                                       return;\r
+                                               };      \r
                                                this._onEnded();\r
                                                break;\r
                                        \r
                                        case 'ended' :\r
-                                               if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){\r
-                                                       delete this._currentTimeFix;\r
-                                               };\r
                                                if( !this._closed && this.loop ){\r
                                                        this.looped = true;\r
                                                        ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play();\r
                                                } else {\r
-                                                       this._timerID && X.Timer.remove( this._timerID );\r
                                                        this.seekTime = 0;\r
-                                                       delete this._timerID;\r
                                                        delete this.playing;\r
                                                };\r
                                                break;\r
        \r
                                        case 'durationchange' : // duration属性が更新された場合に発生\r
-                                               this.duration = this._rawObject.duration * 1000;\r
-                                               // console.log( this._rawObject.duration );\r
                                                \r
-                                               if( this._playForDuration ){\r
-                                                       this._rawObject.pause();\r
-                                                       this._rawObject.currentTime = 0.001;\r
-                                                       delete this._playForDuration;\r
+                                               if( !X_Audio_HTMLAudioWrapper_durationFix ){\r
+                                                       this.duration = this._rawObject.duration * 1000;\r
+                                               } else\r
+                                               // Desktop Opera\r
+                                               if( this._rawObject.duration !== 1 / 0 ){\r
+                                                       \r
+                                                       console.log( this._rawObject.duration );\r
+                                                       \r
+                                                       this.duration = this._rawObject.duration * 1000;\r
+                                                       \r
+                                                       if( this._playForDuration === 0 ) this._playForDuration = 2;\r
+                                                       \r
+                                                       if( this._playForDuration === 1 ){\r
+                                                               this._playForDuration = 2;\r
+                                                               \r
+                                                               console.log( 'Loaded ' + this._loaded );\r
+                                                               \r
+                                                               if( this._loaded ){\r
+                                                                       this._rawObject.currentTime = this._beginTime / 1000;\r
+                                                                       console.log( '設定 ' + this._beginTime );\r
+                                                                       return;\r
+                                                               };\r
+                                                       \r
+                                               this.proxy.asyncDispatch( 'loadedmetadata' );\r
+                                               this.proxy.asyncDispatch( 'loadeddata' );\r
+                                               this.proxy.asyncDispatch( 'canplay' );\r
+                                               this.proxy.asyncDispatch( 'canplaythrough' );\r
+                                               loaded = true;\r
+                                               console.log( 'Desktop Opera のための currentTime と duration の fix が完了' + this.duration );\r
+                                               \r
+                                               if( this.autoplay ){\r
+                                                                       this._rawObject.currentTime = this._beginTime / 1000;   \r
+                                               } else {\r
+                                                       // Opera12.17 WinXP で勝手に再生される不具合\r
+                                                       // これで一応再生は止まる、、、\r
+                                                                       this._rawObject.src = '';\r
+                                                                       //this._rawObject.load();                                               \r
+                                               };\r
+                                                       };\r
                                                        \r
-                                       this.proxy.asyncDispatch( 'loadedmetadata' );\r
-                                       this.proxy.asyncDispatch( 'loadeddata' );\r
-                                       this.proxy.asyncDispatch( 'canplay' );\r
-                                       this.proxy.asyncDispatch( 'canplaythrough' );\r
-                                       loaded = true;\r
-                                       console.log( 'DEsktop Opera のための currentTime と duration の fix が完了' + this.duration );\r
-                                               };\r
-                                               if( this._currentTimeFix === 1 ){\r
-                                                       this._currentTimeFix++;\r
-                                                       this._rawObject.currentTime = this._beginTime / 1000;\r
-                                                       return;\r
                                                };\r
                                                break;\r
                                        \r
@@ -233,21 +282,20 @@ 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
+                               if( !this._rawObject.src ){\r
                                        this._beginTime = begin;\r
+                                       this._rawObject.src = this._src;\r
+                                       delete this._playForDuration;\r
                                };\r
 \r
+                               this._rawObject.currentTime = begin / 1000;\r
+\r
                            console.log( '[HTMLAudio] play ' + begin + ' -> ' + end );\r
                            \r
                            if( !this.playing ){\r
@@ -263,15 +311,8 @@ if( window.HTMLAudioElement ){
                            };\r
                    \r
                    if( X_Audio_HTMLAudioWrapper_currentTimeFix ){\r
-                       //this._timerID && X.Timer.remove( this._timerID );\r
                        this._beginTime = begin;\r
-                       this._playTime  = X_Timer_now();\r
-                                               \r
-                       if( end < this.duration ){\r
-                                               //this._timerID   = X.Timer.once( end - begin, this, this._onEnded );\r
-                       } else {\r
-                               delete this._timerID;\r
-                       };                      \r
+                       this._playTime  = X_Timer_now();                        \r
                    };\r
 \r
                        },\r
@@ -284,28 +325,23 @@ if( window.HTMLAudioElement ){
                                _onEnded : function(){\r
                                        var currentTime, time;\r
                                        \r
-                                       delete this._timerID;\r
-                                       \r
                            if( this.playing ){\r
                                currentTime = X_Audio_HTMLAudioWrapper_currentTimeFix ? X_Timer_now() - this._playTime + this._beginTime : this._rawObject.currentTime * 1000 | 0;\r
                                time        = currentTime - X_AudioWrapper_getEndTime( this );\r
 \r
-                                   if( X_Audio_HTMLAudioWrapper_shortPlayFix ){\r
-                                       //time -= this._shortFix;\r
-                                   };\r
-\r
                                if( time < 0 ){\r
                                        console.log( '> onEnd ' + (-time) + ' ' + currentTime + '/' + ( X_AudioWrapper_getEndTime( this ) ) );\r
-                                       //if( X_Audio_HTMLAudioWrapper_currentTimeFix ) this._timerID = X.Timer.once( -time, this, this._onEnded );\r
                                        return;\r
                                };\r
                                \r
                                if( this.loop ){\r
-                                       this.looped = true;\r
-                                       ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play();\r
+                                       if( !( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) ){\r
+                                               this.looped = true;\r
+                                               this.play();\r
+                                       };\r
                                } else {\r
                                        this.pause();\r
-                                       this.dispatch( 'ended' );\r
+                                       this.proxy.dispatch( 'ended' );\r
                                };\r
                            };\r
                                },\r
@@ -314,13 +350,7 @@ if( window.HTMLAudioElement ){
                                if( !this.playing ) return;\r
                                \r
                                this.seekTime = this.state().currentTime;\r
-                               \r
-                               if( X_Audio_HTMLAudioWrapper_currentTimeFix2 ){\r
-                                       delete this._currentTimeFix;\r
-                               };\r
-                               \r
-                               //this._timerID && X.Timer.remove( this._timerID );\r
-                               //delete this._timerID;\r
+\r
                                delete this._playTime;\r
 \r
                        !this._rawObject.error && this._rawObject.pause();\r
@@ -412,6 +442,7 @@ if( window.HTMLAudioElement ){
                 *  - FireFox3.6, Android 2.3.6については、src変更後、load()を呼び出さないと切り替わらなかった。iPhoneはload()が不要。\r
                 */     \r
                        detect : function( proxy, source, ext ){\r
+                               /*\r
                                var ok, mineType = 'audio/' + ext;\r
                                switch( ext ){\r
                                        case 'mp3' :\r
@@ -443,7 +474,9 @@ if( window.HTMLAudioElement ){
                                        ok = X_Audio_rawAudio.canPlayType( mineType );\r
                                };\r
                                \r
-                               proxy.asyncDispatch( ok ? 'support' : 'nosupport' );\r
+                               proxy.asyncDispatch( ok ? 'support' : 'nosupport' ); */\r
+                               \r
+                               proxy.asyncDispatch( X_Audio_codecs[ ext ] ? 'support' : 'nosupport' );\r
                        },\r
                        \r
                        klass : X_Audio_HTMLAudioWrapper\r
index 02c1ec1..5ef3c25 100644 (file)
@@ -307,11 +307,13 @@ if( X.Pulgin.SilverlightEnabled ){
                                };\r
                                \r
                                if( this.loop ){\r
-                                       this.looped = true;\r
-                                       ( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) || this.play();\r
+                                       if( !( this.proxy.dispatch( 'looped' ) & X.Callback.PREVENT_DEFAULT ) ){\r
+                                               this.looped = true;\r
+                                               this.play();\r
+                                       };\r
                                } else {\r
                                        this.pause();\r
-                                       this.proxy.dispatch( 'ended' );                         \r
+                                       this.proxy.dispatch( 'ended' );\r
                                };\r
                            };\r
                                },\r
index 4152fa2..39751ae 100644 (file)
@@ -6,8 +6,8 @@
  */\r
 var X_Audio_Sprite_shouldUse        = window.HTMLAudioElement && ( X_UA.iOS || X_UA.AndroidBrowser || X_UA.OperaMobile || X_UA.OperaTablet ),\r
        X_Audio_Sprite_useVideoForMulti = 4 <= X_UA.AndroidBrowser && 534.3 < X_UA.AndroidBrowserWebkit, // ドスパラパッドはビデオのインライン再生が不可 \r
+       X_Audio_Sprite_needTouchAndroid = X_Audio_Sprite_useVideoForMulti,      \r
        X_Audio_Sprite_needTouchFirst   = !!X_UA.iOS || X_Audio_Sprite_useVideoForMulti,\r
-       X_Audio_Sprite_inTouchAction    = false,\r
        X_Audio_Sprite_enableMultiTrack = !( X_UA.iOS && !X_Audio_WebAudio_context ) && !( X_UA.AndroidBrowser4 && X_UA.AndroidBrowserWebkit <= 534.3 ),\r
        X_Audio_Sprite_enableVolume     = window.HTMLAudioElement && ( !X_UA.iOS && !X_UA.AndroidBrowser && !X_UA.OperaMobile && !X_UA.OperaTablet ),\r
        X_Audio_Sprite_maxTracks        = !X_Audio_Sprite_enableMultiTrack ? 1 : X_Audio_Sprite_useVideoForMulti ? 2 : 9,\r
@@ -301,17 +301,39 @@ X_Audio_Sprite_members = {
 };\r
 \r
 function X_Audio_Sprite_handleEvent( e ){\r
-       var i, tracks, track;\r
+       var i, tracks, track, _e;\r
        switch( e.type ){\r
                case 'backendfound' :\r
-                       this.asyncDispatch( e );\r
+                       _e = {\r
+                               type        : e.type,\r
+                               source      : e.source,\r
+                               backendName : e.backendName\r
+                       };\r
+                       \r
+                       if( X_Audio_Sprite_needTouchFirst ){\r
+                               if( e.backendName === 'Web Audio' ){\r
+                                       _e[ 'needTouchForPlay' ] = true;\r
+                               } else {\r
+                                       _e[ 'needTouchForLoad' ] = true;\r
+                               };\r
+                       };\r
+                       this.asyncDispatch( _e );\r
+                       \r
                        e.target.unlisten( 'nobackend', this, X_Audio_Sprite_handleEvent );\r
                        \r
                        if( e.backendName === 'HTML Audio' ){\r
-                               e.target.listenOnce( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata' ], this, X_Audio_Sprite_handleEvent );\r
+                               // Android 4.4.4 Y!Browser でたまにロードを検出できていない?問題を解決できないかな? -> , 'canplaythrough'\r
+                               // タッチイベント内でloadを開始。ロード完了したら無音の再生を実施。timeupdate が返ったらいつでも再生が出来る状態になる。\r
+                               e.target.listenOnce( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata', 'canplaythrough' ], this, X_Audio_Sprite_handleEvent );\r
                        } else {\r
                                e.target.listenOnce( 'canplaythrough', this, X_Audio_Sprite_handleEvent );\r
                        };\r
+                       // READY, needTouchForPlay, needTouchForLoad\r
+                       if( X_Audio_HTMLAudioWrapper_durationFix ){\r
+                               for( i = 0; i < X_Audio_Sprite_TEMP.tracks.length; ++i ){\r
+                                       X_Audio_Sprite_instance.pause( i );\r
+                               };\r
+                       };\r
                        break;\r
 \r
                case 'nobackend' :\r
@@ -324,7 +346,7 @@ function X_Audio_Sprite_handleEvent( e ){
                case 'loadeddata' :\r
                        e.target.unlisten( [ X_Audio_HTMLAudio_playTrigger, 'loadeddata', 'canplaythrough' ], this, X_Audio_Sprite_handleEvent );\r
                        \r
-                       if( X_Audio_Sprite_useVideoForMulti ){\r
+                       if( X_Audio_Sprite_needTouchAndroid ){\r
                                for( i = 0; i < X_Audio_Sprite_TEMP.tracks.length; ++i ){\r
                                        X_Audio_Sprite_instance.pause( i );\r
                                };\r
@@ -339,6 +361,8 @@ function X_Audio_Sprite_handleEvent( e ){
                        if( e.target === X_Audio_Sprite_TEMP.bgmTrack ){\r
                                X_Audio_Sprite_TEMP.bgmLooped = true;\r
                        } else {\r
+                               e.target.state().looped || this.asyncDispatch( 'ended' ); // uid\r
+                               \r
                                // single track | iOS\r
                                if( X_Audio_Sprite_TEMP.bgmPlaying && !X_Audio_Sprite_TEMP.bgmTrack ){\r
                                        X_Audio_Sprite_TEMP.bgmTrack = e.target;\r