function X_Closure_correct( f ){\r
var i = X_CLOSURE_LIVE_LIST.indexOf( f ),\r
obj;\r
+\r
if( i !== -1 ){\r
X_CLOSURE_LIVE_LIST.splice( i, 1 );\r
X_CLOSURE_POOL_LIST[ X_CLOSURE_POOL_LIST.length ] = f;\r
obj = f( X_Closure_COMMAND_BACK );\r
- /*\r
- delete obj.cbKind;\r
- if( obj.funcName ) delete obj.funcName;\r
- if( obj.func ) delete obj.func;\r
- if( obj.context ) delete obj.context;\r
- if( obj.supplement ) delete obj.supplement;\r
- delete obj.proxy; */\r
X_Object_clear( obj );\r
return true;\r
};\r
- return false;\r
};\r
\r
function X_Closure_monitor(){\r
case 'beforeunload' :
// ie では a href='javascript' な要素でも beforeunload が起こる
href = e.target && e.target[ 'attr' ] && e.target[ 'attr' ]( 'href' );
- if( href && href.indexOf && href.indexOf( 'javascript:' ) === 0 ) return X_CALLBACK_PREVENT_DEFAULT | X_CALLBACK_STOP_PROPAGATION;
+ if( X_Type_isString( href ) && !href.toLowerCase().indexOf( 'javascript:' ) ) return X_CALLBACK_PREVENT_DEFAULT | X_CALLBACK_STOP_PROPAGATION;
return X_ViewPort[ 'dispatch' ]( X_EVENT_BEFORE_UNLOAD );
};
+// TODO EventDispatcherProxy
/**
* window に相当する ViewPort 情報を提供するオブジェクト。
* @namespace X.ViewPort
var ey = 0;\r
//\r
var el = target;\r
- var bd = document.body;\r
+ var bd = X_elmBody;\r
\r
do\r
{ \r
// 親の xnodes から v を消す
v.parent && v[ 'remove' ]();
// IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知
- if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
+ if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
break;
default :
return this;
v[ 'remove' ]();
};
// IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知
- if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
+ if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
break;
default :
return this;
X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this;
X_Node_reserveUpdate();
} else
- if( !this[ '_tag' ] && ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ){
+ if( !this[ '_tag' ] && ( ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ){
parent[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
};
} else {
X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = elm;
X_Node_reserveUpdate();
} else
- if( !that[ '_tag' ] && ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ){
+ if( !that[ '_tag' ] && ( ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ){
parent[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
};
} else {
accumulatedFlags |= that[ '_flags' ];
if( that[ '_flags' ] & X_NodeFlags_IE5_DISPLAY_NONE_FIX ){
- if( accumulatedFlags & ( X_NodeFlags_DIRTY_POSITION | X_NodeFlags_DIRTY_ID | X_NodeFlags_DIRTY_CLASSNAME ) === 0 ){
+ if( ( accumulatedFlags & ( X_NodeFlags_DIRTY_POSITION | X_NodeFlags_DIRTY_ID | X_NodeFlags_DIRTY_CLASSNAME ) ) === 0 ){
return nextElement;
};
};
} else
if( that[ '_flags' ] & X_NodeFlags_IS_SVG ){
elm = document.createElementNS( 'http://www.w3.org/2000/svg', that[ '_tag' ].toLowerCase() );
+
+ // math http://www.w3.org/1998/Math/MathML
} else {
elm = document.createElement( that[ '_tag' ] );
};
parentElement.appendChild( elm );
};
- if( that[ '_listeners' ] && ( that[ '_flags' ] & X_NodeFlags_ACTUAL_LISTENING ) === 0 ){
+ if( that[ '_listeners' ] && ( ( that[ '_flags' ] & X_NodeFlags_ACTUAL_LISTENING ) === 0 ) ){
X_EventDispatcher_toggleAllEvents( that, true );// イベントの退避
that[ '_flags' ] |= X_NodeFlags_ACTUAL_LISTENING;
};
return X_Script_createActiveXObjectSafty( 'Gears.Factory' );
})() :
X_Object_find( navigator, 'mimeTypes>application/x-googlegears>enabledPlugin' )
- );
-
+ ),
+
+// https://support.microsoft.com/ja-jp/kb/279022
+// Windows Media Player 7 がクライアントにインストールされている場合に、自動的に Web ページに埋め込む方法
+// TODO GeckoActiveXObject
+ X_Pulgin_WMP_VERSION =
+ !X_UA[ 'IE' ] || !X_UA[ 'ActiveX' ] ? parseFloat( X_Object_find( navigator, 'plugins>Windows Media Player Plug-in Dynamic Link Library>version' ) || 0 ) :
+ (function(){
+ var obj = X_Script_createActiveXObjectSafty( 'WMPlayer.OCX.7' );
+
+ return obj ? parseFloat( obj[ 'versionInfo' ] ) :
+ X_Script_createActiveXObjectSafty( '{22D6F312-B0F6-11D0-94AB-0080C74C7E95}' ) ? 6.4 : 0;
+ })();
+
// QuickTime Plug-in 7.7.6
/*
X_Pulgin_QUICKTIME_VERSION =
})() :
0, */
-
/**
* @namespace X.Pulgin
*/
//'QuickTime' : X_Pulgin_QUICKTIME_VERSION,
- 'Gears' : !!X_Pulgin_GEARS_ENABLED
+ 'Gears' : !!X_Pulgin_GEARS_ENABLED,
+
+ 'WMP' : X_Pulgin_WMP_VERSION
};
for( ; xnode = xmlList[i]; ++i ){\r
tmp = true;\r
for( node = xnode.firstChild; node; node = node.nextSibling ){\r
- if( node.nodeType === 1 || ( node.nodeType === 3 && node._text ) ){\r
+ if( node.nodeType === 1 || ( node.nodeType === 3 && node.nodeValue ) ){\r
tmp = false;\r
break;\r
}; \r
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
},\r
\r
/**\r
);\r
\r
function X_Audio_handleEvent( e ){\r
- var backend;\r
+ var backend, pair;\r
\r
switch( e.type ){\r
case X_EVENT_BACKEND_READY :\r
this[ 'unlisten' ]( X_EVENT_BACKEND_NONE, X_Audio_handleEvent );\r
this[ 'source' ] = e[ 'source' ];\r
this[ 'backendName' ] = backend.backendName;\r
+ \r
X_Pair_create( this, backend.klass( this, e[ 'source' ], e[ 'option' ] ) );\r
+ this[ 'listenOnce' ]( X_EVENT_READY, X_Audio_handleEvent );\r
+ break;\r
+ \r
+ case X_EVENT_READY :\r
+ pair = X_Pair_get( this );\r
+ ( pair.autoplay || pair._playReserved ) && pair.actualPlay();\r
+ delete pair._playReserved;\r
break;\r
\r
case X_EVENT_BACKEND_NONE :\r
+ case X_EVENT_UNLOAD :\r
this[ 'kill' ]();\r
break;\r
\r
case X_EVENT_KILL_INSTANCE :\r
- backend = X_Pair_get( this );\r
- backend && backend[ 'kill' ]();\r
- X_Pair_release( this, backend );\r
+ X_ViewPort[ 'unlisten' ]( X_EVENT_UNLOAD, this, X_AudioSprite_handleEvent );\r
+ if( backend = X_Pair_get( this ) ){\r
+ backend[ 'kill' ]();\r
+ X_Pair_release( this, backend );\r
+ };\r
break;\r
};\r
};\r
{\r
disatcher : null,\r
\r
- startTime : 0, //\r
- endTime : -1, //\r
+ startTime : 0, // state_startTime\r
+ endTime : -1, // state_startTime\r
loopStartTime : -1,\r
loopEndTime : -1,\r
seekTime : -1,\r
autoplay : false,//\r
gain : 0.5,\r
\r
+ _playReserved : false,\r
+ \r
play : function( startTime, endTime, loop, loopStartTime, loopEndTime ){\r
if( 0 <= startTime ){\r
this.setState( {\r
},\r
\r
pause : function(){\r
+ this.seekTime = this.getActualCurrentTime();\r
this.playing && this.actualPause();\r
// delete this.autoplay\r
// delete this.playing\r
for( k in obj ){\r
v = obj[ k ];\r
switch( k ){\r
- case 'currentTime' :\r
+ case 'currentTime' :\r
v = X_Audio_timeStringToNumber( v );\r
if( X_Type_isNumber( v ) ){\r
if( playing ){\r
case 'useVideo' :\r
break;\r
default :\r
- throw ( 'bad arg! ' + k );\r
+ alert( 'bad arg! ' + k );\r
};\r
};\r
\r
\r
function X_Audio_timeStringToNumber( time ){\r
var ary, ms, s = 0, m = 0, h = 0;\r
+\r
if( X_Type_isNumber( time ) ) return time;\r
if( !X_Type_isString( time ) || !time.length ) return;\r
\r
return ms < 0 ? 0 : ms;\r
};\r
\r
-function X_Audio_getStartTime( audioWrapper, endTime, delSeekTime ){\r
- var seek = audioWrapper.seekTime;\r
+function X_Audio_getStartTime( audioBase, endTime, delSeekTime ){\r
+ var seek = audioBase.seekTime;\r
\r
- if( delSeekTime ) delete audioWrapper.seekTime;\r
+ if( delSeekTime ) delete audioBase.seekTime;\r
\r
if( 0 <= seek ){\r
- if( audioWrapper.duration <= seek || endTime < seek ) return 0;\r
+ if( audioBase.duration <= seek || endTime < seek ) return 0;\r
return seek;\r
};\r
\r
- if( audioWrapper.looped && 0 <= audioWrapper.loopStartTime ){\r
- if( audioWrapper.duration <= audioWrapper.loopStartTime || endTime < audioWrapper.loopStartTime ) return 0;\r
- return audioWrapper.loopStartTime;\r
+ if( audioBase.looped && 0 <= audioBase.loopStartTime ){\r
+ if( audioBase.duration <= audioBase.loopStartTime || endTime < audioBase.loopStartTime ) return 0;\r
+ return audioBase.loopStartTime;\r
};\r
\r
- if( audioWrapper.startTime < 0 || audioWrapper.duration <= audioWrapper.startTime ) return 0;\r
- return audioWrapper.startTime;\r
+ if( audioBase.startTime < 0 || audioBase.duration <= audioBase.startTime ) return 0;\r
+ return audioBase.startTime;\r
};\r
\r
-function X_Audio_getEndTime( audioWrapper ){\r
- var duration = audioWrapper.duration;\r
+function X_Audio_getEndTime( audioBase ){\r
+ var duration = audioBase.duration;\r
\r
- if( audioWrapper.looped && 0 <= audioWrapper.loopEndTime ){\r
- if( duration <= audioWrapper.loopEndTime ) return duration;\r
- return audioWrapper.loopEndTime;\r
+ if( audioBase.looped && 0 <= audioBase.loopEndTime ){\r
+ if( duration <= audioBase.loopEndTime ) return duration;\r
+ return audioBase.loopEndTime;\r
};\r
\r
- if( audioWrapper.endTime < 0 || duration <= audioWrapper.endTime ) return duration;\r
- return audioWrapper.endTime;\r
+ if( audioBase.endTime < 0 || duration <= audioBase.endTime ) return duration;\r
+ return audioBase.endTime;\r
};\r
\r
( window[ 'AudioContext' ] || window[ 'webkitAudioContext' ] ),
X_WebAudio_BUFFER_LIST = [],
X_WebAudio_need1stTouch = X_UA[ 'iOS' ],
+ X_WebAudio_touchState = X_WebAudio_need1stTouch,
X_WebAudio,
X_WebAudio_BufferLoader,
X_WebAudio_fpsFix;
},
handleEvent : function( e ){
+ var i, l;
+
switch( e.type ){
case X_EVENT_PROGRESS :
- this[ 'dispatch' ]( { type : 'progress', 'percent' : e[ 'percent' ] } );
+ for( i = 0, l = this.webAudioList.length; i < l; ++i ){
+ this.webAudioList[ i ][ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : e[ 'percent' ] } );
+ };
return;
case X_EVENT_SUCCESS :
this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );
console.log( 'WebAudio buffer ready' );
-
- this.autoplay && !X_WebAudio_need1stTouch && X_Timer_once( 16, this, this.actualPlay );
-
},
actualPlay : function(){
console.log( '[WebAudio] play abuf:' + !!this.audioBuffer );
if( !this.audioBuffer ){
- this.autoplay = true;
+ this._playReserved = true;
return;
};
- if( X_WebAudio_need1stTouch ){
+ if( X_WebAudio_touchState ){
e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ];
if( !e || !e[ 'pointerType' ] ){
- alert( 'タッチイベント以外での play! ' + ( e ? e.type : '' ) );
+ // alert( 'タッチイベント以外での play! ' + ( e ? e.type : '' ) );
return;
};
};
+ X_WebAudio_touchState = false;
end = X_Audio_getEndTime( this );
begin = X_Audio_getStartTime( this, end, true );
},
actualPause : function(){
- //if( !this.playing ) return this;
-
console.log( '[WebAudio] pause' );
- this.seekTime = this.getActualCurrentTime();
-
this._timerID && X_Timer_remove( this._timerID );
delete this._timerID;
delete this.playing;
*/\r
X_HTMLAudio_volumeEnabled = !( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) && !X_UA[ 'Opera' ],\r
// Gecko PC + Android でseek時に再生がしばしば止まる問題の修正\r
- X_HTMLAudio_needPlayForSeek = X_UA[ 'Gecko' ],\r
+ X_HTMLAudio_needPlayForSeek = X_UA[ 'iOS' ] || X_UA[ 'Gecko' ],\r
// \r
X_HTMLAudio_pauseFix = 12 <= X_UA[ 'Opera' ] && 0 < ' XP XPSP2 2003|XP64'.indexOf( X_UA[ 'Windows' ] ), // XP + Opera12 のみ?\r
\r
X_elmBody.appendChild( raw );\r
} else {\r
raw = X_TEMP.rawAudio || new X_Audio_constructor( '' );\r
- // raw.loop = false; // loop を使えば ended で止まること回避できるかも 但し ended イベントが起きなくなる\r
\r
if( X_TEMP.rawAudio ) delete X_TEMP.rawAudio;\r
};\r
'playing', 'waiting', 'seeking',\r
'durationchange', 'timeupdate', 'ended' ], this.onDebug );\r
\r
+ if( X_HTMLAudio_endedFixAOSP2 || X_HTMLAudio_endedFixAOSP4 ){\r
+ raw.loop = true; // loop を使えば ended で止まること回避できるかも 但し ended イベントが起きなくなる\r
+ };\r
+\r
if( X_HTMLAudio_need1stTouch ){\r
raw.src = source;\r
} else {\r
// if( this.autoplay ){\r
raw.preload = 'auto';\r
raw.autoplay = true; // Android 4.0-4.1.x で必要\r
+ //raw.autobuffer = true;\r
//};\r
- //raw.autobuffer = true;\r
raw.src = source;\r
raw.load(); // Android4.1.1 HTL21 では必要!\r
};\r
this.disatcher[ 'dispatch' ]( {\r
type : X_EVENT_DEBUG,\r
'rawEvent' : e.type,\r
- current : this[ '_rawObject' ].currentTime,\r
+ 'current' : this[ '_rawObject' ].currentTime,\r
duration : this[ '_rawObject' ].duration } );\r
},\r
\r
handleEvent : function( e ){\r
- if( !e || !e.type ) alert( 888 );\r
- \r
var raw = this[ '_rawObject' ],\r
actualEnded = e.type === 'ended',\r
ended = actualEnded,\r
+ i, l, buf, time,\r
ready,\r
eventType, duration, end, now;\r
\r
if( this._closed ) return;\r
- \r
- // global に公開\r
- //window[ '__rawAudio' ] = this[ '_rawObject' ];\r
- \r
- e.type !== 'timeupdate' && console.log( ' > ' + e.type );\r
+\r
+ //e.type !== 'timeupdate' && console.log( ' > ' + e.type );\r
\r
switch( e.type ){\r
\r
\r
// 【javascript】モバイル向けブラウザでも音を鳴らしたい【WebAudio】\r
// http://ingaouhou.com/archives/3633\r
- // ・使い終わったインスタンスはload()しておくとやや安定 \r
+ // ・使い終わったインスタンスはload()しておくとやや安定\r
raw.src = '';\r
raw.load();\r
\r
// console.log( e.loaded + ' ' + e.total * 100 + '%' );\r
// iem9 で常に0 raw.networkState;\r
// opera Android 12 で buffered.end() へのアクセスはエラー try catch も無効、iem9 は常に end(0) = 0\r
- //console.log( 'buffered.end ' + raw.buffered && raw.buffered.end(0) ); \r
+ if( !( X_UA[ 'Opera' ] && X_UA[ 'Android' ] ) && !( X_UA[ 'WinPhones' ] && X_UA[ 'IE9' ] ) && this.duration ){\r
+ buf = raw.buffered;\r
+ time = 0;\r
+ for( i = 0, l = 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 } );\r
+ };\r
break;\r
\r
case 'loadeddata' : // コンテンツの表示を現在の再生位置で初めて行えるようになった場合に発生\r
duration = raw.duration;\r
eventType = X_EVENT_MEDIA_WAITING;\r
} else\r
- if( !X_HTMLAudio_durationFix && X_HTMLAudio_need1stTouch && this._touchState === 3 ){\r
+ if( this._touchState === 3 && !X_HTMLAudio_durationFix ){\r
this._touchState = 0;\r
this._readyState |= 1;\r
} else\r
if( this.playing ){\r
end = X_Audio_getEndTime( this ) + this._shortPlayFixTime;\r
//console.log( now + ' / ' + end );\r
- // || now < this._lastCurrentTime // loop した場合\r
- if( 0 + end <= 0 + now ){ // 0+ なぜか iem9 で必要,,,\r
+ if( ( 0 + end <= 0 + now ) || // 0+ なぜか iem9 で必要,,,\r
+ ( now < this._lastCurrentTime ) ){ // loop した場合\r
if( this.autoLoop ){\r
console.log( '☆★☆ 曲の最後に到達 @timeupdate now-end:' + ( now - end ) );\r
ended = true;\r
- if( X_HTMLAudio_endedFixIOS ) actualEnded = true;\r
+ //if( X_HTMLAudio_endedFixIOS ) actualEnded = true;\r
} else {\r
this.actualPause();\r
eventType = X_EVENT_MEDIA_ENDED;\r
console.log( '▼ DurationFix の終了 @' + e.type );\r
this._durationFixPhase = 8;\r
\r
- if( this.autoplay ){\r
+ if( this.autoplay || this._playReserved ){\r
console.log( '☆ 再生 <- DurationFix の終了' );\r
+ delete this._playReserved;\r
this.actualPlay();\r
} else\r
if( X_HTMLAudio_pauseFix ){\r
console.log( '☆ PAUSE <- DurationFix の終了' );\r
- //raw.src = '';\r
- //raw.load();\r
- this.actualPause(); \r
+ this.actualPause();\r
};\r
} else\r
if( this._durationFixPhase & 3 ){ // === 1 | 2\r
if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){\r
this.looped = true;\r
this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );\r
- ( X_HTMLAudio_endedFixAOSP3 || X_HTMLAudio_endedFixAOSP4 || X_HTMLAudio_endedFixCWV || X_HTMLAudio_endedFixIOS ) && actualEnded && console.log( '☆★☆ 音声の継続用の play() @ended' );\r
- this.actualPlay(\r
- ( X_HTMLAudio_endedFixAOSP4 || X_HTMLAudio_endedFixCWV || X_HTMLAudio_endedFixIOS ) && actualEnded,\r
- ( X_HTMLAudio_endedFixAOSP3 || X_HTMLAudio_endedFixAOSP2 ) && actualEnded );\r
+ this.actualPlay( X_HTMLAudio_endedFixCWV && actualEnded, X_HTMLAudio_endedFixAOSP3 && actualEnded );\r
};\r
} else {\r
this.seekTime = 0;\r
if( this._readyState === 1 && this.duration ){\r
this._readyState = 3;\r
this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );\r
- this.autoplay && X_Timer_once( 16, this, this.actualPlay );\r
console.log( '> Audio Loaded!! ' + e.type + ' d:' + ( this.duration | 0 ) );\r
} else\r
if( eventType ){\r
this._touchState = 3;\r
} else\r
if( this._readyState !== 3 && this._durationFixPhase < 2 ){\r
- this.autoplay = true;\r
+ this._playReserved = true;\r
return;\r
};\r
\r
} else\r
if( X_HTMLAudio_needPlayForSeek || forcePlay ){\r
raw.play();\r
- console.log( '[HTMLAudio] currentTime より先.' );\r
+ //console.log( '[HTMLAudio] currentTime より先.' );\r
};\r
\r
//http://himaxoff.blog111.fc2.com/blog-entry-97.html\r
\r
console.log( '[HTMLAudio] play ' + begin + ' -> ' + end + ' crt:' + ( raw.currentTime | 0 ) + ' last:' + this._lastCurrentTime );\r
\r
- if( forceReload || ( X_HTMLAudio_endedFixAOSP4 && raw.duration && raw.currentTime === raw.duration ) ){\r
- raw.src = '';\r
- raw.src = this._src;\r
+ if( forceReload ){\r
this.playing = false;\r
this._endedFixON = true;\r
+ raw.src = this._src;\r
console.log( '△ onEndedFix の開始' );\r
- raw.currentTime = this._lastCurrentTime;\r
this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
- X_HTMLAudio_endedFixAOSP2 && raw.load();\r
};\r
};\r
\r
var raw = this[ '_rawObject' ];\r
\r
console.log( '[HTMLAudio] pause' );\r
- \r
- this.seekTime = this.getActualCurrentTime();\r
\r
delete this._currentFixStart;\r
\r
var X_SLAudio,\r
X_SLAudio_uid = 0;\r
\r
-if( X[ 'Pulgin' ][ 'Silverlight' ] ){\r
+if( X_Pulgin_SILVER_LIGHT_VERSION ){\r
\r
X_TEMP.slaudioInit = function(){\r
//\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
- \r
- this.autoplay && X_Timer_once( 16, this, this.actualPlay );\r
break;\r
\r
case 'MediaEnded' :\r
// もし kill 後に autoplayTimer で呼ばれても、_closed==true なので平気\r
if( this.error ) return;\r
if( !this.duration ){\r
- this.autoplay = true;\r
+ this._playReserved = true;\r
return;\r
};\r
\r
\r
// SilverlightAudio.pause\r
actualPause : function(){\r
- if( this.error /* || !this.playing */ ) return;\r
+ if( this.error ) return;\r
\r
this._lastUserAction = 'pause';\r
- this.seekTime = this.getActualCurrentTime();\r
this.playing = false;\r
this._paused = true;\r
this._ended = false;\r
\r
this[ '_rawObject' ].pause();\r
- //this.disatcher[ 'dispatch' ]( 'pause' );\r
},\r
\r
getActualCurrentTime : function(){\r
},\r
\r
afterUpdateState : function( result ){\r
+ var end, halfway;\r
+ \r
if( result & 3 ){ // seek\r
this.actualPlay();\r
} else\r
--- /dev/null
+// https://msdn.microsoft.com/ja-jp/library/cc410695.aspx
+// Windows Media Player コントロール Version 6.4
+
+// http://www.tohoho-web.com/wwwmmd2.htm
+
+// http://devedge.primedirective.net/viewsource/2003/windows-media-in-netscape/index.html
+
+var X_WMPAudio;
+
+if( X_Pulgin_WMP_VERSION ){ // IETester で 6.x は不可
+ X_WMPAudio = X_AudioBase[ 'inherits' ](
+ 'X.WMPAudio',
+ X_Class.POOL_OBJECT,
+ {
+ xnodeObject : null,
+ wmp : null,
+ _wmp : null,
+ // 0 : no <object>
+ // 1 : loading
+ // 2 : loaded
+ _readyState : 0,
+ _seekDirection : 0,
+ _timerID : 0,
+
+ 'Constructor' : function( disatcher, source, option ){
+ this.disatcher = disatcher || this;
+ this._source = source;
+
+ if( 7 <= X_Pulgin_WMP_VERSION ){
+ this.xnodeObject = X_Node_systemNode[ 'create' ]( 'object', {
+ 'classID' : 'CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6',
+ width : 1,
+ height : 1
+ })[ 'html' ](
+ X_UA[ 'IE55' ] ? '' : '<param name="uiMode" value="none">'
+ //+ '<param name="URL" value="' + source + '">'
+ //+ '<param name="AutoStart" value="' + option.autoplay + '">'
+ );
+ } else {
+ this.xnodeObject = X_Node_systemNode[ 'create' ]( 'object', {
+ classID : 'CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95',
+ width : 0,
+ height : 0
+ })[ 'html' ](
+ X_UA[ 'IE55' ] ? '' : '<param name="ShowControls" value="false">'
+ //+ '<param name="FileName" value="' + source + '">'
+ //+ '<param name="AutoStart" value="' + option.autoplay + '">'
+ );
+ };
+ // TODO embed
+
+ this.setState( option );
+
+ X_ViewPort[ 'listenOnce' ]( X_EVENT_AFTER_UPDATE, this );
+ this[ 'listenOnce' ]( X_EVENT_KILL_INSTANCE );
+ },
+
+ handleEvent : function( e ){
+ switch( e.type ){
+ case X_EVENT_AFTER_UPDATE :
+ this._readyState = 1;
+ if( 7 <= X_Pulgin_WMP_VERSION ){
+ this._wmp = this.xnodeObject[ '_rawObject' ];
+ this._wmp[ 'URL' ] = this._source;
+ this.wmp = this._wmp[ 'controls' ];
+ } else {
+ this.wmp = this.xnodeObject[ '_rawObject' ];
+ this.wmp[ 'FileName' ] = this._source;
+ };
+ this._timerID = X_Timer_add( 100, 0, this, this._onTimer );
+ break;
+
+ case X_EVENT_KILL_INSTANCE :
+ this.playing && this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
+ this.playing && this.actualPause();
+ this.wmp.stop();
+ this.xnodeObject[ 'kill' ]();
+ break;
+ };
+ },
+
+ // WMPAudio.play
+ actualPlay : function(){
+ var begin, offset, end;
+
+ if( this._readyState < 2 ){
+ this._playReserved = true;
+ return;
+ };
+
+ end = X_Audio_getEndTime( this );
+ begin = this._beginTime = X_Audio_getStartTime( this, end, true ) | 0;
+
+ console.log( '[play] ' + begin + ' -> ' + end );
+
+ if( !this.playing ){
+ this.setVolume();
+ this.wmp.play();
+
+ this.playing = true;
+ } else {
+ this._seekDirection = this.getActualCurrentTime() < begin ? 1 : -1;
+ };
+
+ // 1 秒以下は指定できないため四捨五入
+ //begin = ( begin / 1000 | 0 ) * 1000 + ( 500 < begin % 1000 ? 1000 : 0 );
+ this.wmp[ 'CurrentPosition' ] = begin / 1000;
+
+ if( !this._timerID ) this._timerID = X_Timer_add( 100, 0, this, this._onTimer );
+ },
+
+ _onTimer : function(){
+ var progress, time;
+
+ // road 中の場合
+ if( this._readyState === 1 ){
+ if( 7 <= X_Pulgin_WMP_VERSION ){
+ progress = this._wmp[ 'network' ][ 'downloadProgress' ];
+ } else {
+ progress = this.wmp[ 'BufferingProgress' ];
+ };
+ if( progress < 100 ){
+ this.disatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : progress } );
+ } else {
+ this._readyState = 2;
+ if( 7 <= X_Pulgin_WMP_VERSION ){
+ this.duration = this._wmp[ 'currentMedia' ].duration * 1000 | 0;
+ } else {
+ this.duration = this.wmp[ 'Duration' ] * 1000 | 0;
+ };
+ this.disatcher[ 'dispatch' ]( X_EVENT_READY );
+ };
+ } else
+ // ended の判定
+ if( this.playing ){
+ time = this.getActualCurrentTime();
+
+ // waiting
+ if( this._seekDirection ){
+ if( this._seekDirection === 1 ? ( time < this._beginTime ) : ( this._lastCurrentTime <= time ) ){
+ this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );
+ return;
+ };
+ delete this._seekDirection;
+ };
+ if( time === this._lastCurrentTime ){
+ this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
+ return;
+ };
+ this._lastCurrentTime = time;
+
+ // ended ではない
+ if( time - X_Audio_getEndTime( this ) < -50 ){
+ this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
+ return;
+ };
+
+ // ended
+ if( this.autoLoop ){
+ if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
+ this.looped = true;
+ this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
+ this.actualPlay();
+ };
+ } else {
+ this.actualPause();
+ this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
+ delete this._timerID;
+ return X_CALLBACK_UN_LISTEN;
+ };
+ };
+ },
+
+ // WMPAudio.pause
+ actualPause : function(){
+ this.playing = false;
+ this._timerID && X_Timer_remove( this._timerID );
+ delete this._timerID;
+
+ this.wmp.pause();
+ },
+
+ setVolume : function(){
+ if( 7 <= X_Pulgin_WMP_VERSION ){
+ this._wmp[ 'settings' ][ 'Volume' ] = this.gain * 100;
+ } else {
+ this.wmp[ 'Volume' ] = ( 1 - this.gain ) * 10000;
+ };
+ },
+
+ getActualCurrentTime : function(){
+ return this.wmp[ 'CurrentPosition' ] * 1000 | 0;
+ },
+
+ afterUpdateState : function( result ){
+ if( result & 3 ){ // seek
+ this.actualPlay();
+ } else
+ if( result & 4 ){
+ this.setVolume();
+ };
+ }
+
+ }
+ );
+
+ X_Audio_BACKENDS.push( {
+ backendID : 16,
+
+ backendName : 'WMP' + X_Pulgin_WMP_VERSION,
+
+ canPlay : {
+ 'mp3' : true,
+ 'wma' : true,
+ 'wav' : true,
+ 'mid' : true,
+ 'midi' : true,
+ 'snd' : true,
+ 'au' : true,
+ 'aif' : true,
+ 'aicf' : true,
+ 'aiff' : true
+ },
+
+ detect : function( proxy, source, ext ){
+ proxy[ 'asyncDispatch' ]( { type : X_EVENT_COMPLETE, canPlay : ext === 'mp3' || ext === 'wma' || ext === 'wav' } );
+ },
+
+ klass : X_WMPAudio
+
+ } );
+
+};
\ No newline at end of file
X_AudioSprite_lengthSilence = 10000, // 一番最初の無音部分の長さ\r
X_AudioSprite_lengthDistance = 5000, // 音間の無音の長さ\r
X_AudioSprite_uid = 0,\r
- X_AudioSprite_members = {},\r
X_AudioSprite_TEMP = {\r
presets : {},\r
BGMs : {},\r
bgmLooped : false,\r
bgmPlaying : false\r
},\r
- X_AudioSprite_instance,\r
+ X_AudioSprite,\r
X_AudioSprite_numTracks,\r
X_AudioSprite_useVideo;\r
\r
urls = setting[ 'urls' ],\r
video = setting[ 'useVideo' ],\r
n = video ? 1 : setting[ 'numTracks' ] || 1,\r
- option = {\r
- volume : setting[ 'volume' ] || 0.5,\r
- autoplay : true,\r
- startTime : 0,\r
- endTime : X_AudioSprite_lengthSilence,\r
- loop : true\r
- },\r
- k, i, v, track; \r
+ volume = setting[ 'volume' ],\r
+ k, i, v, track;\r
\r
- if( !X_AudioSprite_instance ){\r
- X_AudioSprite_instance = X_Class_override( X_EventDispatcher(), X_AudioSprite_members );\r
- X_ViewPort[ 'listen' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE ], X_AudioSprite_instance, X_AudioSprite_handleEvent );\r
+ if( !X_AudioSprite ){\r
+ X_AudioSprite = X_Class_override( X_EventDispatcher(), X_AudioSprite_members );\r
+ X_ViewPort[ 'listen' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE, X_EVENT_UNLOAD ], X_AudioSprite, X_AudioSprite_handleEvent );\r
};\r
\r
n = n <= X_AudioSprite_maxTracks ? n : X_AudioSprite_maxTracks;\r
};\r
};\r
\r
- X_Audio_startDetectionBackend( X_Audio_BACKENDS[ 0 ], X_AudioSprite_instance, X_Array_copy( urls ), option );\r
+ X_Audio_startDetectionBackend(\r
+ X_Audio_BACKENDS[ 0 ],\r
+ X_AudioSprite,\r
+ X_Array_copy( urls ),\r
+ {\r
+ 'volume' : 0 <= volume && volume <= 1 ? volume : 1,\r
+ 'autoplay' : true,\r
+ 'startTime' : 0,\r
+ 'endTime' : X_AudioSprite_lengthSilence,\r
+ 'loop' : true\r
+ });\r
\r
- X_AudioSprite_instance[ 'listenOnce' ]( [ X_EVENT_BACKEND_READY, X_EVENT_BACKEND_NONE ], X_AudioSprite_backendHandler );\r
- X_AudioSprite_instance[ 'listenOnce' ]( X_EVENT_KILL_INSTANCE, X_AudioSprite_handleEvent );\r
+ X_AudioSprite[ 'listenOnce' ]( [ X_EVENT_BACKEND_READY, X_EVENT_BACKEND_NONE ], X_AudioSprite_backendHandler );\r
+ X_AudioSprite[ 'listenOnce' ]( X_EVENT_KILL_INSTANCE, X_AudioSprite_handleEvent );\r
\r
X_AudioSprite_useVideo = video;\r
- X_AudioSprite_numTracks = X_AudioSprite_instance[ 'numTracks' ] = n;\r
+ X_AudioSprite_numTracks = X_AudioSprite[ 'numTracks' ] = n;\r
\r
- return X_AudioSprite_instance;\r
+ return X_AudioSprite;\r
};\r
\r
X[ 'AudioSprite' ][ 'shouldUse' ] = X_AudioSprite_shouldUse;\r
// TODO 終わりかけのもの、と一番古いもの、どちらを再利用するか?これ以上に細かい実装を望む場合は X.AudioSprite は使わず自力で実装\r
function X_AudioSprite_getTrackEnded(){\r
var tracks = X_AudioSprite_TEMP.tracks,\r
- l = tracks.length,\r
+ l = X_AudioSprite_numTracks,\r
i = 0, track, state, last = 1 / 0, _last, index;\r
\r
for( ; i < l; ++i ){\r
return tracks[ index ];\r
};\r
\r
-X_AudioSprite_members =\r
+var X_AudioSprite_members =\r
/** @lends X.AudioSprite.prototype */\r
{\r
/**\r
'numTracks' : 0,\r
\r
/**\r
- * モバイル用タッチイベント中に呼び出す\r
- */\r
- 'on1stTouch' : function(){\r
- var i = 0, l = X_AudioSprite_TEMP.tracks.length;\r
-\r
- for( ; i < l; ++i ){\r
- //if( X_UA[ 'iOS' ] ){\r
- // X_AudioSprite_TEMP.tracks[ i ][ '_rawObject' ].load();\r
- //} else {\r
- X_AudioSprite_instance[ 'pause' ]( i );\r
- //};\r
- };\r
- },\r
- \r
- /**\r
* 再生\r
* @param {string} name トラック名\r
* @return {number} uid\r
if( bgm ){\r
track = bgm;\r
} else\r
- if( 1 < tracks.length ){\r
+ if( 1 < X_AudioSprite_numTracks ){\r
track = X_AudioSprite_TEMP.bgmTrack = X_AudioSprite_getTrackEnded();\r
} else {\r
track = X_AudioSprite_TEMP.bgmTrack = tracks[ 0 ];\r
};\r
\r
- if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_instance, X_AudioSprite_handleEvent ).playing ){\r
+ if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite, X_AudioSprite_handleEvent ).playing ){\r
track.setState({\r
'loop' : true,\r
'looped' : X_AudioSprite_TEMP.bgmLooped,\r
};\r
\r
} else {\r
- if( 1 < tracks.length ){\r
+ if( 1 < X_AudioSprite_numTracks ){\r
track = X_AudioSprite_getTrackEnded( X_AudioSprite_TEMP.bgmPlaying );\r
track\r
- [ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_instance, X_AudioSprite_handleEvent )\r
+ [ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite, X_AudioSprite_handleEvent )\r
.setState( { 'looped' : false } );\r
track.play( preset[ 0 ], preset[ 1 ], true, 0, X_AudioSprite_lengthSilence );\r
} else {\r
};\r
track = tracks[ 0 ];\r
\r
- if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_instance, X_AudioSprite_handleEvent ).playing ){\r
+ if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite, X_AudioSprite_handleEvent ).playing ){\r
track.setState({\r
'loop' : true,\r
'looped' : false,\r
- //'currentTime' : preset[ 0 ],\r
+ 'currentTime' : preset[ 0 ],\r
'startTime' : preset[ 0 ],\r
'endTime' : preset[ 1 ],\r
'loopStartTime' : 0,\r
},\r
\r
/**\r
- * ポーズ\r
- * @param {number} uid トラックID\r
- * @return {number} uid\r
+ * ポーズ, uid を指定しない、または '*' で呼び出した場合、全てのトラックを pause する。\r
+ * @param {number} uid=undefined トラックID, '*'\r
+ * @return {AudioSprite}\r
*/\r
'pause' : function( uid ){\r
- var track = X_AudioSprite_TEMP.tracks[ uid ];\r
+ var tracks = X_AudioSprite_TEMP.tracks,\r
+ i, l, track;\r
\r
- if( X_AudioSprite_TEMP.bgmTrack === track ){\r
- X_AudioSprite_TEMP.bgmPosition = track.currentTime();\r
- X_AudioSprite_TEMP.bgmPlaying = false;\r
- X_AudioSprite_TEMP.bgmTrack = null;\r
+ if( uid === '*' || uid === undefined ){\r
+ for( i = 0, l = X_AudioSprite_numTracks; i < l; ++i ){\r
+ X_AudioSprite[ 'pause' ]( i );\r
+ };\r
+ } else\r
+ if( track = tracks[ uid ] ){\r
+ if( X_AudioSprite_TEMP.bgmTrack === track ){\r
+ X_AudioSprite_TEMP.bgmPosition = track.currentTime();\r
+ X_AudioSprite_TEMP.bgmPlaying = false;\r
+ X_AudioSprite_TEMP.bgmTrack = null;\r
+ };\r
+ track.play( 0, X_AudioSprite_lengthSilence, true, 0, X_AudioSprite_lengthSilence );\r
+ track.seek( 0 );\r
+ X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_PAUSED ); \r
};\r
- track && track.play( 0, X_AudioSprite_lengthSilence, true, 0, X_AudioSprite_lengthSilence );\r
- track && track.seek( 0 );\r
- X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_PAUSED );\r
- return X_AudioSprite_instance;\r
+ return X_AudioSprite;\r
},\r
\r
/**\r
- * シーク\r
+ * シーク, 現在のトラックの長さ内で相対指定する\r
* @param {number} uid トラックID\r
* @param {number} position ms\r
* @return {AudioSprite}\r
start = X_Audio_getStartTime( track, end );\r
0 <= position && position <= ( end - start ) && track.seek( start + position );\r
};\r
- return X_AudioSprite_instance;\r
+ return X_AudioSprite;\r
},\r
\r
/**\r
if( opt_volume === undefined ){\r
return X_AudioSprite_TEMP.volume;\r
};\r
- for( i = X_AudioSprite_TEMP.tracks.length; i; ){\r
+ for( i = X_AudioSprite_numTracks; i; ){\r
X_AudioSprite_TEMP.tracks[ --i ].volume( opt_volume );\r
};\r
- return X_AudioSprite_instance;\r
+ return X_AudioSprite;\r
};\r
track = X_AudioSprite_TEMP.tracks[ uid ];\r
if( opt_volume === undefined ){\r
return track ? track.gain : -1;\r
};\r
track && track.volume( opt_volume );\r
- return X_AudioSprite_instance;\r
+ return X_AudioSprite;\r
},\r
\r
/**\r
return { 'volume' : X_AudioSprite_TEMP.volume, 'playing' : false };\r
};\r
track && track.setState( opt_obj );\r
- return X_AudioSprite_instance;\r
+ return X_AudioSprite;\r
}\r
};\r
\r
function X_AudioSprite_backendHandler( e ){\r
- var i, backend, option, src, name, last, _e;\r
+ var i, backend, option, src, name, last, _e, track;\r
\r
switch( e.type ){\r
case X_EVENT_BACKEND_READY :\r
backend = X_Audio_BACKENDS[ e[ 'backendID' ] ];\r
option = e[ 'option' ];\r
\r
- X_AudioSprite_instance[ 'unlisten' ]( X_EVENT_BACKEND_NONE, X_AudioSprite_backendHandler );\r
- X_AudioSprite_instance[ 'source' ] = src = e[ 'source' ];\r
- X_AudioSprite_instance[ 'backendName' ] = name = backend.backendName;\r
+ X_AudioSprite[ 'unlisten' ]( X_EVENT_BACKEND_NONE, X_AudioSprite_backendHandler );\r
+ X_AudioSprite[ 'source' ] = src = e[ 'source' ];\r
+ X_AudioSprite[ 'backendName' ] = name = backend.backendName;\r
\r
//console.log( i + ' / ' + X_AudioSprite_numTracks );\r
\r
for( i = 0; i < X_AudioSprite_numTracks; ++i ){\r
if( X_AudioSprite_useVideo || ( i === 1 && X_AudioSprite_useVideoForMulti ) ){\r
+ option = X_Object_deepCopy( option );\r
option[ 'useVideo' ] = true;\r
console.log( 'use video' );\r
};\r
// Audiobackend の owner として null を渡すとAudioBackend 自身へ dispatch する\r
- X_AudioSprite_TEMP.tracks.push( last = backend.klass( null, e[ 'source' ], option )[ 'listen' ]( X_EVENT_DEBUG, X_AudioSprite_instance, X_AudioSprite_handleEvent ) );\r
+ X_AudioSprite_TEMP.tracks.push(\r
+ last = backend.klass( null, e[ 'source' ], option )[ 'listen' ]( X_EVENT_DEBUG, X_AudioSprite, X_AudioSprite_handleEvent ) );\r
};\r
\r
_e = {\r
'backendName' : name\r
};\r
// touch 可能で backend ready\r
- \r
- if( name === 'WebAudio' ){\r
- if( _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch ){\r
- last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_instance[ 'asyncDispatch' ], [ _e ] );\r
- } else {\r
- X_AudioSprite_instance[ 'asyncDispatch' ]( _e );\r
- };\r
- last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
+ // WebAudio\r
+ if( backend.backendID === 1 && ( _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch ) ){\r
+ last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite, X_AudioSprite[ 'asyncDispatch' ], [ _e ] );\r
} else\r
- if( name === 'HTMLAudio' ){\r
- if( _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch ){\r
- last[ 'listenOnce' ]( X_EVENT_MEDIA_TOUCH_FOR_LOAD, X_AudioSprite_instance, X_AudioSprite_instance[ 'asyncDispatch' ], [ _e ] );\r
- last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
- } else {\r
- X_AudioSprite_instance[ 'asyncDispatch' ]( _e );\r
- last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
- \r
- // READY, needTouchForPlay, needTouchForLoad\r
- if( X_HTMLAudio_durationFix ){\r
- for( i = 0; i < X_AudioSprite_TEMP.tracks.length; ++i ){\r
- X_AudioSprite_instance[ 'pause' ]( i );\r
- };\r
- };\r
- };\r
- \r
+ // HTMLAudio\r
+ if( backend.backendID === 2 && ( _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch ) ){\r
+ last[ 'listenOnce' ]( X_EVENT_MEDIA_TOUCH_FOR_LOAD, X_AudioSprite, X_AudioSprite[ 'asyncDispatch' ], [ _e ] );\r
} else {\r
- X_AudioSprite_instance[ 'asyncDispatch' ]( _e );\r
- \r
- console.log( 'AudioSprite - X_EVENT_BACKEND_READY' );\r
- \r
- last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
+ X_AudioSprite[ 'asyncDispatch' ]( _e );\r
};\r
+ \r
+ last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite, X_AudioSprite_backendHandler );\r
return X_CALLBACK_STOP_NOW;\r
\r
case X_EVENT_BACKEND_NONE :\r
- X_AudioSprite_instance[ 'unlisten' ]( X_EVENT_BACKEND_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler )\r
+ X_AudioSprite[ 'unlisten' ]( X_EVENT_BACKEND_READY, X_AudioSprite, X_AudioSprite_backendHandler )\r
[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE );\r
return X_CALLBACK_STOP_NOW;\r
\r
case X_EVENT_READY :\r
console.log( 'X.AudioSprite - Ready!' );\r
- for( i = 0; i < X_AudioSprite_TEMP.tracks.length; ++i ){\r
- X_AudioSprite_instance[ 'pause' ]( i );\r
+ for( i = 0; i < X_AudioSprite_numTracks; ++i ){\r
+ track = X_AudioSprite_TEMP.tracks[ i ];\r
+ ( track.autoplay || track._playReserved ) && track.actualPlay();\r
+ delete track._playReserved;\r
};\r
- X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_READY );\r
+ X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_READY );\r
break;\r
};\r
};\r
\r
switch( e.type ){\r
case X_EVENT_MEDIA_PLAYING :\r
- ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) && X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_PLAYING );\r
+ ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) && X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_PLAYING );\r
break;\r
case X_EVENT_MEDIA_WAITING :\r
case X_EVENT_MEDIA_SEEKING :\r
- ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) && X_AudioSprite_instance[ 'asyncDispatch' ]( e.type );\r
+ ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) && X_AudioSprite[ 'asyncDispatch' ]( e.type );\r
break;\r
\r
case X_EVENT_MEDIA_BEFORE_LOOP :\r
if( e.target === X_AudioSprite_TEMP.bgmTrack ){\r
X_AudioSprite_TEMP.bgmLooped = true;\r
- X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
+ X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
} else {\r
if( e.target.looped ){\r
- // X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
+ // X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
} else {\r
- X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_ENDED ); // TODO uid\r
+ X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_ENDED ); // TODO uid\r
};\r
\r
//console.log( '[AudioSprite] bgmPlaying:' + X_AudioSprite_TEMP.bgmPlaying + ' ' + !X_AudioSprite_TEMP.bgmTrack );\r
// single track | iOS\r
if( X_AudioSprite_TEMP.bgmPlaying && !X_AudioSprite_TEMP.bgmTrack ){\r
X_AudioSprite_TEMP.bgmTrack = e.target;\r
- X_AudioSprite_instance.play( X_AudioSprite_TEMP.bgmName );\r
+ X_AudioSprite.play( X_AudioSprite_TEMP.bgmName );\r
return X_CALLBACK_PREVENT_DEFAULT;\r
};\r
};\r
i = X_AudioSprite_TEMP.tracks.indexOf( e.target );\r
if( 0 <= i ){\r
e[ 'trackID' ] = i;\r
- X_AudioSprite_instance[ 'dispatch' ]( e );\r
+ X_AudioSprite[ 'dispatch' ]( e );\r
};\r
break;\r
\r
console.log( '■ デアクティブ' );\r
// track.pause();\r
tracks = X_AudioSprite_TEMP.tracks;\r
- i = tracks.length;\r
+ i = X_AudioSprite_numTracks;\r
for( ; i; ){\r
track = tracks[ --i ];\r
track.playing && X_AudioSprite_TEMP.pauseTracks.push( track ) && track.pause();\r
};\r
break;\r
\r
+ case X_EVENT_UNLOAD :\r
+ console.log( '■ unload' );\r
+ \r
case X_EVENT_KILL_INSTANCE :\r
- \r
while( X_AudioSprite_TEMP.tracks.length ){\r
X_AudioSprite_TEMP.tracks.pop()[ 'kill' ]();\r
};\r
X_AudioSprite_TEMP.bgmLooped = false;\r
X_AudioSprite_TEMP.bgmPlaying = false;\r
\r
- X_ViewPort[ 'unlisten' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE ], X_AudioSprite_instance, X_AudioSprite_handleEvent );\r
+ X_ViewPort[ 'unlisten' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE, X_EVENT_UNLOAD ], X_AudioSprite, X_AudioSprite_handleEvent );\r
break;\r
};\r
};\r