• R/O
  • HTTP
  • SSH
  • HTTPS

clientJs: コミット

クライアント側 js 開発用


コミットメタ情報

リビジョン66ccef8a1fdd3994dd3c75dcfede668ea55f1d2e (tree)
日時2016-10-21 15:10:06
作者itozyun <itozyun@user...>
コミッターitozyun

ログメッセージ

Version 0.6.218, Fix the bug of X.Net & X.Audio.

変更サマリ

差分

--- a/0.6.x/js/02_dom/10_XNodeAnime.js
+++ b/0.6.x/js/02_dom/10_XNodeAnime.js
@@ -525,7 +525,14 @@ function X_NodeAnime_updatePosition( xnode, obj, ratio, useGPU ){
525525
526526 //console.log( 'updatePosition x:' + x + ' gpu:' + !!useGPU );
527527 if( obj.transform ){
528- if( ( x === x || y === y ) && ( x !== 0 && y !== 0 ) ) str += ' translate(' + ( x | 0 ) + 'px,' + ( y | 0 ) + 'px)';
528+ if( ( x === x || y === y ) && ( x !== 0 && y !== 0 ) ){
529+ if( X_UA[ 'Safari' ] && X_UA[ 'Windows' ] ){
530+ // http://shinimae.hatenablog.com/entry/2016/01/13/151748
531+ str = ' -webkit-translate(' + ( x | 0 ) + 'px,' + ( y | 0 ) + 'px)';
532+ } else {
533+ str = ' translate(' + ( x | 0 ) + 'px,' + ( y | 0 ) + 'px)';
534+ };
535+ };
529536 if( rotate < 0 || 0 < rotate ) str += ' rotate(' + rotate + 'deg)'; // opera は rad?
530537 if( skewX < 0 || 0 < skewX ) str += ' skewX(' + skewX + 'deg)';
531538 if( skewY < 0 || 0 < skewY ) str += ' skewY(' + skewY + 'deg)';
--- a/0.6.x/js/06_net/00_XNet.js
+++ b/0.6.x/js/06_net/00_XNet.js
@@ -279,6 +279,8 @@ function X_NET_proxyDispatch( e ){
279279 this[ 'listenOnce' ]( X_EVENT_COMPLETE, X_NET_proxyDispatch )
280280 [ 'asyncDispatch' ]( 32, { type : X_EVENT_COMPLETE, 'lastEventType' : e.type } );
281281
282+ // target を上書き X_NET_currentWrapper -> X_NET_currentQueue
283+ e[ 'target' ] = e[ 'currentTarget' ] = this;
282284 this[ 'asyncDispatch' ]( e );
283285 break;
284286
--- a/0.6.x/js/06_net/01_XNetXHR.js
+++ b/0.6.x/js/06_net/01_XNetXHR.js
@@ -171,7 +171,7 @@ if( X_XHR_w3c || X_XHR_msXML ){
171171 postdata = obj[ 'postdata' ] || '',
172172 timeout = obj[ 'timeout' ] || 20000,
173173 noCache = obj[ 'cache' ] !== true,
174- dataType = X_XHR._dataType = obj[ 'dataType' ],
174+ dataType = X_XHR._dataType = obj[ 'dataType' ], // ext が入っている
175175 xDomain = !X_URL_isSameDomain( url ),
176176 isFile = X_URL_isLocal( url ),
177177 init,
@@ -204,24 +204,25 @@ if( X_XHR_w3c || X_XHR_msXML ){
204204 if( raw.responseType !== undefined ){
205205 switch( dataType ){
206206 case '' :
207+ case 'txt' :
207208 case 'text' :
208209 // js, css
209- raw.responseType = 'text';
210+ raw.responseType = X_XHR._dataType = 'text';
210211 break;
211212 case 'json' : // firefox9- は moz-json
212- raw.responseType = X_UA[ 'Gecko' ] < 10 ? 'moz-json' : X_UA[ 'Gecko' ] ? dataType : ''; // Iron 37 でエラー
213+ raw.responseType = X_XHR._dataType = X_UA[ 'Gecko' ] < 10 ? 'moz-json' : X_UA[ 'Gecko' ] ? dataType : ''; // Iron 37 でエラー
213214 break;
214215 case 'document' :
215216 case 'xml' :
216217 case 'html' :
217218 case 'htm' :
218219 // svg
219- raw.responseType = 'document';
220+ raw.responseType = X_XHR._dataType = 'document';
220221 break;
221222 case 'blob' :
222223 case 'arraybuffer' :
223224 // jpeg,jpg,png,gif,mp3,ogg...
224- raw.responseType = dataType;
225+ raw.responseType = X_XHR._dataType = dataType;
225226 break;
226227 };
227228 };
@@ -472,7 +473,6 @@ if( X_XHR_w3c || X_XHR_msXML ){
472473
473474 // parse json, html, xml, text, script, css
474475 switch( X_XHR._dataType ){
475- case '' :
476476 case 'text' :
477477 data = X_Script_try( X_Object_find, [ raw, 'responseText' ] );
478478 break;
@@ -485,10 +485,6 @@ if( X_XHR_w3c || X_XHR_msXML ){
485485 if( X_Type_isString( data ) ) data = X_JSON_parseTrustableString( data );
486486 break;
487487 case 'document' :
488- case 'xml' :
489- case 'html' :
490- case 'htm' :
491- // svg, vml, xaml, xul, mxml ??
492488 data = raw[ 'responseXML' ] || raw[ 'response' ] || raw[ 'responseText' ]; // とりあえず
493489 break;
494490 case 'blob' :
--- a/0.6.x/js/06_net/10_XOAuth2.js
+++ b/0.6.x/js/06_net/10_XOAuth2.js
@@ -414,7 +414,7 @@ function X_OAuth2_updateLocalStorage( cmd, that, name, value ){
414414 var action = cmd === '+' ? 'setItem' : cmd === '-' ? 'removeItem' : 'getItem',
415415 pair;
416416
417- if( window.localStorage ){
417+ if( window.localStorage ){ // TODO http://qiita.com/narikei/items/f55fb9cb398beac52ea9
418418 return window.localStorage[ action ]( X_Pair_get( that )[ 'clientID' ] + name, value );
419419 };
420420
--- a/0.6.x/js/07_audio/00_XAudio.js
+++ b/0.6.x/js/07_audio/00_XAudio.js
@@ -89,7 +89,7 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ](
8989 X_Type_isArray( sourceList ) ? X_Array_copy( sourceList ) : [ sourceList ],
9090 opt_option || {} );
9191 this[ 'listenOnce' ]( [ X_EVENT_BACKEND_READY, X_EVENT_BACKEND_NONE, X_EVENT_KILL_INSTANCE ], X_Audio_handleEvent );
92- X_ViewPort[ 'listenOnce' ]( X_EVENT_UNLOAD, this, X_AudioSprite_handleEvent );
92+ X_ViewPort[ 'listenOnce' ]( X_EVENT_UNLOAD, this, X_Audio_handleEvent );
9393 },
9494
9595 /**
@@ -231,7 +231,7 @@ function X_Audio_handleEvent( e ){
231231 this[ 'listenOnce' ]( X_EVENT_READY, X_Audio_handleEvent );
232232 break;
233233
234- case X_EVENT_READY :
234+ case X_EVENT_READY : // TODO AudioBase 側へ行かない?
235235 pair = X_Pair_get( this );
236236 ( pair.autoplay || pair._playReserved ) && pair.actualPlay();
237237 delete pair._playReserved;
@@ -243,7 +243,7 @@ function X_Audio_handleEvent( e ){
243243 break;
244244
245245 case X_EVENT_KILL_INSTANCE :
246- X_ViewPort[ 'unlisten' ]( X_EVENT_UNLOAD, this, X_AudioSprite_handleEvent );
246+ X_ViewPort[ 'unlisten' ]( X_EVENT_UNLOAD, this, X_Audio_handleEvent );
247247 if( backend = X_Pair_get( this ) ){
248248 backend[ 'kill' ]();
249249 X_Pair_release( this, backend );
@@ -286,7 +286,7 @@ function X_Audio_onEndedDetection( e, xaudio, sourceList, option, source, ext, s
286286 'backendID' : i
287287 };
288288 // WebAudio
289- if( this.backendID === 1 ) _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch;
289+ if( this.backendID === 1 ) _e[ 'needTouchForPlay' ] = /* X_WebAudio_need1stTouch && */ X_WebAudio_isNoTouch;
290290 // HTMLAudio
291291 if( this.backendID === 2 ) _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch;
292292
@@ -313,7 +313,7 @@ var X_AudioBase = X_EventDispatcher[ 'inherits' ](
313313 'X.AudioBase',
314314 X_Class.ABSTRACT,
315315 {
316- disatcher : null,
316+ dispatcher : null,
317317
318318 startTime : 0, // state_startTime
319319 endTime : -1, // state_startTime
--- a/0.6.x/js/07_audio/01_XWebAudio.js
+++ b/0.6.x/js/07_audio/01_XWebAudio.js
@@ -14,6 +14,10 @@ var X_Audio_constructor = 3.1 <= X_UA[ 'Safari' ] && X_UA[ 'Safari' ] < 4 ?
1414
1515 X_Audio_codecs;
1616
17+// WebAudioAPIを使っているはずなのに、マナーモードで音が出る!?
18+// http://qiita.com/gonshi_com/items/e41dbb80f5eb4c176108
19+// HTML Audio、もしくはHTML Videoをページ内で1つでも使用していた場合、そのページでは WebAudioAPI の音がマナーモード時にも鳴ってしまう
20+
1721 if( X_Audio_constructor ){
1822 //http://himaxoff.blog111.fc2.com/blog-entry-97.html
1923 //引数なしで new Audio() とすると、Operaでエラーになるそうなので注意。
@@ -78,7 +82,7 @@ if( X_Audio_constructor ){
7882 };
7983
8084
81-var X_WebAudio_context = // 4s 以下ではない iPad 2G または iPad mini 1G 以下ではない, iPod touch 4G 以下ではない
85+var X_WebAudio_Context = // 4s 以下ではない iPad 2G または iPad mini 1G 以下ではない, iPod touch 4G 以下ではない
8286 !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] &&
8387 // iOS7 以上で HTML Audio が鳴らない問題を見ていくよ
8488 // !X_UA[ 'iOS' ] &&
@@ -90,11 +94,13 @@ var X_WebAudio_context = // 4s 以下ではない iPad 2G または iPad mi
9094 //!X_UA[ 'Blink' ] &&
9195 // Firefox40.0.5 + Windows8 で音声が途中から鳴らなくなる
9296 // Firefox41.0.1 + Windows8 で音声が途中から鳴らなくなる
93- !( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 46 && X_UA[ 'Windows' ] ) &&
94- ( window[ 'AudioContext' ] || window[ 'webkitAudioContext' ] ),
97+ !( 40 <= X_UA[ 'Gecko' ] && /* X_UA[ 'Gecko' ] < 48 && */ X_UA[ 'Windows' ] ) &&
98+ ( window[ 'AudioContext' ] || window[ 'webkitAudioContext' ] || window[ 'mozAudioContext' ] ),
99+ X_WebAudio_context,
95100 X_WebAudio_BUFFER_LIST = [],
96101 X_WebAudio_need1stTouch = X_UA[ 'iOS' ],
97- X_WebAudio_touchState = X_WebAudio_need1stTouch,
102+ X_WebAudio_isNoTouch = X_WebAudio_need1stTouch,
103+ X_WebAudio_needRateFix = X_WebAudio_need1stTouch,
98104 X_WebAudio,
99105 X_WebAudio_BufferLoader,
100106 X_WebAudio_fpsFix;
@@ -102,9 +108,46 @@ var X_WebAudio_context = // 4s 以下ではない iPad 2G または iPad mi
102108 /*
103109 * iPhone 4s 以下、iPad2以下、iPad mini 1以下, iPod touch 4G 以下は不可
104110 */
105-if( X_WebAudio_context ){
111+if( X_WebAudio_Context ){
112+
113+ X_WebAudio_context = new X_WebAudio_Context;
106114
107- X_WebAudio_context = new X_WebAudio_context;
115+ // http://lilting.ch/3323.html
116+ // 【間に合わせ】iOS9系でのWebAudioの音割れ対処について
117+ /*
118+ if( X_WebAudio_needRateFix ){
119+ X_WebAudio_context.close();
120+ X_WebAudio_context = new X_WebAudio_Context;
121+ }; */
122+
123+ /*
124+ * TODO X_TEMP へ
125+ * http://qiita.com/simiraaaa/items/79a9ac972cc76fb58d93
126+ * [WebAudio API] iOS9で音が歪む、遅い、低い、割れる等の回避方法
127+ */
128+ if( X_WebAudio_needRateFix ){
129+ X_TEMP.webAudioSampleRateFix = function( sampleRate ){
130+ X_TEMP.webAudioDummyPlay( sampleRate );
131+
132+ if( true || X_WebAudio_context[ 'sampleRate' ] !== sampleRate ){
133+ // alert( '[debug]iOSで音割れを検知、修復コードを実施 ctxSR:' + X_WebAudio_context[ 'sampleRate' ] + ' abfSR:' + sampleRate );
134+
135+ X_WebAudio_context.close && X_WebAudio_context.close();
136+ X_WebAudio_context = new X_WebAudio_Context;
137+
138+ X_TEMP.webAudioDummyPlay( sampleRate );
139+ };
140+
141+ delete X_TEMP.webAudioSampleRateFix;
142+ delete X_TEMP.webAudioDummyPlay;
143+ };
144+ X_TEMP.webAudioDummyPlay = function( sampleRate, source ){
145+ source = X_WebAudio_context[ 'createBufferSource' ]();
146+ source.buffer = X_WebAudio_context[ 'createBuffer' ]( 1, 1, sampleRate );
147+ source[ 'connect' ]( X_WebAudio_context[ 'destination' ] );
148+ source.start ? source.start( 0 ) : source[ 'noteOn' ] ? source[ 'noteOn' ]( 0 ) : source[ 'noteGrainOn' ]( 0 );
149+ };
150+ };
108151
109152 X_WebAudio_BufferLoader = X_EventDispatcher[ 'inherits' ](
110153 'X.WebAudio.BufferLoader',
@@ -212,8 +255,7 @@ if( X_WebAudio_context ){
212255
213256 }
214257 );
215-
216-
258+
217259 X_WebAudio = X_AudioBase[ 'inherits' ](
218260 'X.WebAudio',
219261 X_Class.POOL_OBJECT,
@@ -229,9 +271,12 @@ if( X_WebAudio_context ){
229271 audioBuffer : null,
230272 bufferSource : null,
231273 gainNode : null,
274+
275+ bufferPlay : '',
276+ bufferStop : '',
232277 //_onended : null,
233278
234- 'Constructor' : function( disatcher, url, option ){
279+ 'Constructor' : function( dispatcher, url, option ){
235280 var i = 0,
236281 l = X_WebAudio_BUFFER_LIST.length,
237282 loader;
@@ -259,7 +304,7 @@ if( X_WebAudio_context ){
259304 this.loader = loader = X_WebAudio_BufferLoader( this, url );
260305 };
261306
262- this.disatcher = disatcher || this;
307+ this.dispatcher = dispatcher || this;
263308 this.setState( option );
264309
265310 this[ 'listenOnce' ]( X_EVENT_KILL_INSTANCE, this.onKill );
@@ -269,6 +314,11 @@ if( X_WebAudio_context ){
269314 } else {
270315 loader[ 'listenOnce' ]( X_EVENT_COMPLETE, this, this._onLoadBufferComplete );
271316 };
317+
318+ if( X_WebAudio_isNoTouch ){
319+ X_TEMP.xWebAudioInstances = X_TEMP.xWebAudioInstances || [];
320+ X_TEMP.xWebAudioInstances.push( this );
321+ };
272322 },
273323
274324 onKill : function(){
@@ -283,6 +333,10 @@ if( X_WebAudio_context ){
283333 //this._onended && X_Closure_correct( this._onended );
284334
285335 this.gainNode && this.gainNode.disconnect();
336+
337+ if( X_WebAudio_isNoTouch ){
338+ X_TEMP.xWebAudioInstances.splice( X_TEMP.xWebAudioInstances.indexOf( this ), 1 );
339+ };
286340 },
287341 _onLoadBufferComplete : function( e ){
288342 var loader = this.loader,
@@ -292,7 +346,7 @@ if( X_WebAudio_context ){
292346
293347 if ( !buffer ) {
294348 this.error = loader.errorState;
295- this.disatcher[ 'dispatch' ]({
349+ this.dispatcher[ 'dispatch' ]({
296350 type : X_EVENT_ERROR,
297351 error : loader.errorState,
298352 message : loader.errorState === 1 ?
@@ -306,11 +360,11 @@ if( X_WebAudio_context ){
306360 this.audioBuffer = buffer;
307361 this.duration = buffer.duration * 1000;
308362
309- this.disatcher[ 'asyncDispatch' ]( X_WebAudio_touchState ? X_EVENT_MEDIA_WAIT_FOR_TOUCH : X_EVENT_READY );
363+ this.dispatcher[ 'asyncDispatch' ]( X_WebAudio_isNoTouch ? X_EVENT_MEDIA_WAIT_FOR_TOUCH : X_EVENT_READY );
310364 },
311365
312366 actualPlay : function(){
313- var e, begin, end;
367+ var xWebAudio, begin, end;
314368
315369 console.log( '[WebAudio] play abuf:' + !!this.audioBuffer );
316370
@@ -318,42 +372,48 @@ if( X_WebAudio_context ){
318372 this._playReserved = true;
319373 return;
320374 };
321-
322- if( X_WebAudio_touchState ){
323- e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ];
375+
376+ if( X_WebAudio_isNoTouch ){
377+ //@dev{
378+ var e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ];
324379 if( !e || !e[ 'pointerType' ] ){
325380 // alert( 'タッチイベント以外での play! ' + ( e ? e.type : '' ) );
326381 return;
327382 };
383+ //@}
384+
328385 // http://qiita.com/uupaa/items/e5856e3cb2a9fc8c5507
329386 // iOS9 + touchstart で呼んでいた場合、 X_ViewPort['listenOnce']('pointerup',this,this.actualPlay())
330- this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );
387+ this.dispatcher[ 'asyncDispatch' ]( X_EVENT_READY );
388+
389+ // Web Audio インスタンスが複数生成された場合、一つの Web Audio に対してタッチによる play が開始されたら、
390+ // 1. 同時に生成された他の X.Audio インスタンスに対して READY イベントを発する
391+ // 2. 以降の X.Audio インスタンス生成時に needTouchForPlay フラグは false
392+ // ちなみに HTML Audio インスタンスは各々にタッチが必要
393+ //X_WebAudio_isNoTouch = false;
394+
395+ while( xWebAudio = X_TEMP.xWebAudioInstances.pop() ){
396+ xWebAudio !== this && xWebAudio[ 'asyncDispatch' ]( X_EVENT_READY );
397+ };
398+ delete X_TEMP.xWebAudioInstances;
399+
400+ X_WebAudio_isNoTouch = false;
401+
402+ X_TEMP.webAudioSampleRateFix && X_TEMP.webAudioSampleRateFix( this.audioBuffer[ 'sampleRate' ] );
331403 };
332- X_WebAudio_touchState = false;
333404
334405 end = X_Audio_getEndTime( this );
335406 begin = X_Audio_getStartTime( this, end, true );
336407
337408 console.log( '[WebAudio] play ' + begin + ' -> ' + end + ' loop: ' + this.autoLoop + ' :' + this.loopStartTime + ' -> ' + this.loopEndTime );
338-
339- if( this.bufferSource ) this._sourceDispose();
340- if( !this.gainNode ){
341- this.gainNode = X_WebAudio_context[ 'createGain' ] ? X_WebAudio_context[ 'createGain' ]() : X_WebAudio_context[ 'createGainNode' ]();
342- this.gainNode[ 'connect' ]( X_WebAudio_context[ 'destination' ] );
343- };
344-
345- this.bufferSource = X_WebAudio_context[ 'createBufferSource' ]();
346- this.bufferSource.buffer = this.audioBuffer;
409+ this._createTree( begin, end );
347410
348411 /* win8.1 Firefox45, win8.1 Chrome48 で動かなくなる...
349412 if( this.bufferSource[ 'loop' ] = this.autoLoop ){
350413 this.bufferSource[ 'loopStart' ] = 0 <= this.loopStartTime ? this.loopStartTime / 1000 : begin / 1000;
351414 this.bufferSource[ 'loopEnd' ] = 0 <= this.loopEndTime ? this.loopEndTime / 1000 : end / 1000;
352415 }; */
353-
354- this.bufferSource[ 'connect' ]( this.gainNode );
355- this.gainNode[ 'gain' ].value = this.gain;
356-
416+
357417 // おかしい、stop 前に外していても呼ばれる、、、@Firefox33.1
358418 // 破棄された X.Callback が呼ばれて、obj.proxy() でエラーになる。Firefox では、onended は使わない
359419 // 多くのブラウザで onended は timer を使ったカウントより遅いので使わない
@@ -364,16 +424,7 @@ if( X_WebAudio_context ){
364424 //this._timerID && X_Timer_remove( this._timerID );
365425 //this._timerID = X_Timer_once( end - begin, this, this._onEnded );
366426 //};
367-
368- if( this.bufferSource.start ){
369- this.bufferSource.start( 0, begin / 1000, ( end - begin ) / 1000 );
370- } else
371- if( this.bufferSource[ 'noteOn' ] ){
372- this.bufferSource[ 'noteOn' ]( 0, begin / 1000, ( end - begin ) / 1000 );
373- } else {
374- this.bufferSource[ 'noteGrainOn' ]( 0, begin / 1000, ( end - begin ) / 1000 );
375- };
376-
427+
377428 this.playing = true;
378429 this._startPos = begin;
379430 this._endPosition = end;
@@ -381,20 +432,34 @@ if( X_WebAudio_context ){
381432 this._interval = this._interval || X_Timer_add( 100, 0, this, this._onInterval );
382433 },
383434
435+ _createTree : function( begin, end ){
436+ if( this.bufferSource ) this._sourceDispose();
437+
438+ if( !this.gainNode ){
439+ this.gainNode = X_WebAudio_context[ 'createGain' ] ? X_WebAudio_context[ 'createGain' ]() : X_WebAudio_context[ 'createGainNode' ]();
440+ this.gainNode[ 'connect' ]( X_WebAudio_context[ 'destination' ] );
441+ };
442+
443+ this.bufferSource = X_WebAudio_context[ 'createBufferSource' ]();
444+ this.bufferSource.buffer = this.audioBuffer;
445+ this.bufferSource[ 'connect' ]( this.gainNode );
446+
447+ this.gainNode[ 'gain' ].value = this.gain;
448+
449+ if( !this.bufferPlay ){
450+ this.bufferPlay = this.bufferSource.start ? 'start' : this.bufferSource[ 'noteOn' ] ? 'noteOn' : 'noteGrainOn';
451+ this.bufferStop = this.bufferSource.stop ? 'stop' : 'noteOff';
452+ };
453+ // https://developer.mozilla.org/ja/docs/Web/API/AudioBufferSourceNode
454+ // AudioBufferSourceNode.start()の呼び出しは一度しかできません。
455+ this.bufferSource[ this.bufferPlay ]( 0, begin / 1000, ( end - begin ) / 1000 );
456+ },
457+
384458 _sourceDispose : function(){
385459 this.bufferSource.disconnect();
386460 //delete this.bufferSource.onended;
387461 delete this.bufferSource;
388462 },
389-
390- /*
391- _onInterval : function(){
392- if( !this.playing ){
393- delete this._interval;
394- return X_CALLBACK_UN_LISTEN;
395- };
396- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
397- }, */
398463
399464 _onInterval : function(){
400465 var time;
@@ -405,14 +470,14 @@ if( X_WebAudio_context ){
405470 //console.log( '> onEnd ' + ( this.playing && ( X_WebAudio_context.currentTime * 1000 - this._startTime ) ) + ' < ' + ( this._endPosition - this._startPos ) );
406471
407472 if( time < 0 ){
408- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
473+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
409474 return;
410475 };
411476
412477 if( this.autoLoop ){
413- if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
478+ if( !( this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
414479 this.looped = true;
415- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
480+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
416481 this.actualPlay();
417482 } else {
418483 delete this._interval;
@@ -420,7 +485,7 @@ if( X_WebAudio_context ){
420485 };
421486 } else {
422487 this.actualPause();
423- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
488+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
424489 };
425490 };
426491 },
@@ -433,8 +498,7 @@ if( X_WebAudio_context ){
433498 delete this.playing;
434499
435500 if( this.bufferSource ){
436- this.bufferSource.stop ?
437- this.bufferSource.stop( 0 ) : this.bufferSource[ 'noteOff' ]( 0 );
501+ this.bufferSource[ this.bufferStop ]( 0 );
438502 };
439503 },
440504
--- a/0.6.x/js/07_audio/02_XHTMLAudio.js
+++ b/0.6.x/js/07_audio/02_XHTMLAudio.js
@@ -54,8 +54,8 @@ var
5454
5555 // Opera Mobile 12 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する
5656 X_HTMLAudio_currentTimeFix = !!X_UA[ 'OperaMobile' ] || !!X_UA[ 'OperaTablet' ],
57- // Firefox44.0.2 で音声の再生開始に難あり...
58- X_HTMLAudio_playStartFix = X_UA[ 'Windows' ] && X_UA[ 'Gecko' ] === 44,
57+ // Firefox44.0.2 で音声の再生開始に難あり... 49 でも確認, あるいはCGIで動的に生成しているmp3自体に問題があるのかも
58+ X_HTMLAudio_playStartFix = X_UA[ 'Windows' ] && 44 <= X_UA[ 'Gecko' ],
5959
6060 X_HTMLAudio_volumeFix = X_UA[ 'Chrome' ],
6161 /*
@@ -118,10 +118,10 @@ if( X_Audio_constructor ){
118118
119119 _seekingFixON : false,
120120
121- 'Constructor' : function( disatcher, source, option ){
121+ 'Constructor' : function( dispatcher, source, option ){
122122 var raw;
123123
124- this.disatcher = disatcher || this;
124+ this.dispatcher = dispatcher || this;
125125 this._src = source;
126126
127127 if( X_HTMLAudio_shortPlayFix ){
@@ -188,7 +188,7 @@ if( X_Audio_constructor ){
188188 },
189189
190190 onDebug : function( e ){
191- this.disatcher[ 'dispatch' ]( {
191+ this.dispatcher[ 'dispatch' ]( {
192192 type : X_EVENT_DEBUG,
193193 'rawEvent' : e.type,
194194 'current' : this[ '_rawObject' ].currentTime,
@@ -232,7 +232,7 @@ if( X_Audio_constructor ){
232232 for( i = time = 0, l = buf && buf.length; i < l; ++i ){
233233 time += buf[ 'end' ]( i ) - buf[ 'start' ]( i );
234234 };
235- this.disatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : time * 1000 / this.duration * 100 } );
235+ this.dispatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : time * 1000 / this.duration * 100 } );
236236 };
237237 break;
238238
@@ -379,29 +379,36 @@ if( X_Audio_constructor ){
379379 if( this._touchState === 1 ){
380380 if( e.type === X_HTMLAudio_playTrigger ){
381381 this._touchState = 2;
382- this.disatcher[ 'asyncDispatch' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH );
382+ this.dispatcher[ 'asyncDispatch' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH );
383383 };
384384 } else
385385 if( ended ){
386386 if( this.autoLoop ){
387- if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
387+ if( !( this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
388388 this.looped = true;
389- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
389+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
390390 this.actualPlay( X_HTMLAudio_endedFixCWV && actualEnded, X_HTMLAudio_endedFixAOSP3 && actualEnded );
391391 };
392392 } else {
393393 this.seekTime = 0;
394394 delete this.playing;
395- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
395+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
396396 };
397397 } else
398398 if( this._readyState === 1 && this.duration ){
399399 this._readyState |= 2;
400- this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );
400+ this.dispatcher[ 'asyncDispatch' ]( X_EVENT_READY );
401+
402+ // TODO 勝手に play する環境があるので pause() を実施
403+ /*
404+ if( !this.playing && !this.autoplay && !this._playReserved && !X_HTMLAudio_pauseFix ){
405+ this.actualPause();
406+ }; */
407+
401408 console.log( '> Audio Loaded!! ' + e.type + ' d:' + ( this.duration | 0 ) );
402409 } else
403410 if( eventType ){
404- this.disatcher[ 'dispatch' ]( eventType );
411+ this.dispatcher[ 'dispatch' ]( eventType );
405412 };
406413 },
407414
@@ -488,7 +495,7 @@ if( X_Audio_constructor ){
488495 this._endedFixON = true;
489496 raw.src = this._src;
490497 console.log( '△ onEndedFix の開始' );
491- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
498+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
492499 };
493500 };
494501
--- a/0.6.x/js/07_audio/03_XSilverlightAudio.js
+++ b/0.6.x/js/07_audio/03_XSilverlightAudio.js
@@ -53,7 +53,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
5353 _lastState : '',
5454 _interval : 0, // setInterval timer id
5555
56- 'Constructor' : function( disatcher, source, option ){
56+ 'Constructor' : function( dispatcher, source, option ){
5757 !X_SLAudio_uid && X_TEMP.slaudioInit();
5858
5959 /*
@@ -61,7 +61,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
6161 * http://www.atmarkit.co.jp/fdotnet/dotnettips/902slobjcallfromjs/slobjcallfromjs.html
6262 * このページのサンプルは sl5+firefox32 環境で動いている。xaml を js から利用する形ではなく、.xap を sl4 以下で作るのがよさそう.
6363 */
64- this.disatcher = disatcher || this;
64+ this.dispatcher = dispatcher || this;
6565 this._source = source;
6666 // X.Audio._slOnload_ は不可
6767 this._onload = 'XAudioSilverlightOnLoad' + ( ++X_SLAudio_uid );
@@ -122,7 +122,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
122122 if( this.playing ){
123123 //X_Timer_once( 16, this, this.actualPlay );
124124 } else {
125- this.disatcher[ 'dispatch' ]( X_EVENT_ERROR ); // open failed
125+ this.dispatcher[ 'dispatch' ]( X_EVENT_ERROR ); // open failed
126126 this[ 'kill' ]();
127127 };
128128 break;
@@ -130,7 +130,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
130130 case 'MediaOpened' :
131131 // http://msdn.microsoft.com/ja-jp/library/bb979710(VS.95).aspx
132132 this.duration = this[ '_rawObject' ][ 'NaturalDuration' ][ 'Seconds' ] * 1000;
133- this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );
133+ this.dispatcher[ 'asyncDispatch' ]( X_EVENT_READY );
134134 break;
135135
136136 case 'MediaEnded' :
@@ -157,10 +157,10 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
157157 case 'Opening' :
158158 switch( this._lastUserAction ){
159159 case 'play' :
160- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
160+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
161161 break;
162162 case 'seek' :
163- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );
163+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );
164164 break;
165165 case 'pause' :
166166 break;
@@ -177,7 +177,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
177177 this.playing = false;
178178 this._ended = true;
179179 this._paused = false;
180- this.disatcher[ 'dispatch' ]( X_EVENT_ERROR );
180+ this.dispatcher[ 'dispatch' ]( X_EVENT_ERROR );
181181 this[ 'kill' ]();
182182 break;
183183
@@ -195,7 +195,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
195195 //this.seekTime = 0;
196196 this._ended = true;
197197 this._paused = false;
198- //this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
198+ //this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
199199 //this.setCurrentTime( this.startTime );
200200 break;
201201 case 'pause':
@@ -214,7 +214,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
214214 //this.playing = true;
215215 this._ended = false;
216216 this._paused = false;
217- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
217+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
218218 break;
219219
220220 // stop()
@@ -230,7 +230,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
230230 break;
231231
232232 case X_EVENT_KILL_INSTANCE :
233- this.playing && this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
233+ this.playing && this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
234234 this.playing && this.actualPause();
235235
236236 if( this._onload ){
@@ -297,7 +297,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
297297 delete this._interval;
298298 return X_CALLBACK_UN_LISTEN;
299299 };
300- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
300+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
301301 },
302302
303303 _onEnded : function(){
@@ -315,7 +315,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
315315 console.log( ' > ' + time );
316316 this._ended && this[ '_rawObject' ].play();
317317 this._ended = false;
318- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
318+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
319319 this._timerID = X_Timer_once( X_Audio_getEndTime( this ) - time, this, this._onEnded );
320320 return;
321321 };
@@ -331,16 +331,16 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){
331331
332332 if( this.autoLoop ){
333333 console.log( '========= loop?' );
334- if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
334+ if( !( this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
335335 console.log( '========== loopした' );
336336 this.looped = true;
337- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
337+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
338338 this.actualPlay();
339339 };
340340 } else {
341341 console.log( '========= pause' );
342342 this.actualPause();
343- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
343+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
344344 };
345345 };
346346 },
--- a/0.6.x/js/07_audio/05_XWMPAudio.js
+++ b/0.6.x/js/07_audio/05_XWMPAudio.js
@@ -22,8 +22,8 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
2222 _seekDirection : 0,
2323 _timerID : 0,
2424
25- 'Constructor' : function( disatcher, source, option ){
26- this.disatcher = disatcher || this;
25+ 'Constructor' : function( dispatcher, source, option ){
26+ this.dispatcher = dispatcher || this;
2727 this._source = source;
2828
2929 if( 7 <= X_Plugin_WMP_VERSION ){
@@ -71,7 +71,7 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
7171 break;
7272
7373 case X_EVENT_KILL_INSTANCE :
74- this.playing && this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
74+ this.playing && this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
7575 this.playing && this.actualPause();
7676 this.wmp.stop();
7777 this.xnodeObject[ 'kill' ]();
@@ -120,7 +120,7 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
120120 progress = this.wmp[ 'BufferingProgress' ];
121121 };
122122 if( progress < 100 ){
123- this.disatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : progress } );
123+ this.dispatcher[ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : progress } );
124124 } else {
125125 this._readyState = 2;
126126 if( 7 <= X_Plugin_WMP_VERSION ){
@@ -128,7 +128,7 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
128128 } else {
129129 this.duration = this.wmp[ 'Duration' ] * 1000 | 0;
130130 };
131- this.disatcher[ 'dispatch' ]( X_EVENT_READY );
131+ this.dispatcher[ 'dispatch' ]( X_EVENT_READY );
132132 };
133133 } else
134134 // ended の判定
@@ -138,33 +138,33 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可
138138 // waiting
139139 if( this._seekDirection ){
140140 if( this._seekDirection === 1 ? ( time < this._beginTime ) : ( this._lastCurrentTime <= time ) ){
141- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );
141+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_SEEKING );
142142 return;
143143 };
144144 delete this._seekDirection;
145145 };
146146 if( time === this._lastCurrentTime ){
147- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
147+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );
148148 return;
149149 };
150150 this._lastCurrentTime = time;
151151
152152 // ended ではない
153153 if( time - X_Audio_getEndTime( this ) < -50 ){
154- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
154+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
155155 return;
156156 };
157157
158158 // ended
159159 if( this.autoLoop ){
160- if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
160+ if( !( this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
161161 this.looped = true;
162- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
162+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
163163 this.actualPlay();
164164 };
165165 } else {
166166 this.actualPause();
167- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
167+ this.dispatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
168168 delete this._timerID;
169169 return X_CALLBACK_UN_LISTEN;
170170 };
--- a/0.6.x/js/07_audio/10_XAudioSprite.js
+++ b/0.6.x/js/07_audio/10_XAudioSprite.js
@@ -28,7 +28,7 @@ var X_AudioSprite_shouldUse = X_HTMLAudio && ( X_UA[ 'iOS' ] || X_UA[ 'A
2828 bgmName : '',
2929 bgmLooped : false,
3030 bgmPlaying : false,
31- event : null
31+ tmpEvent : null
3232 },
3333 X_AudioSprite,
3434 X_AudioSprite_numTracks,
@@ -93,7 +93,7 @@ X[ 'AudioSprite' ] = function( setting ){
9393
9494 X_Audio_startDetectionBackend(
9595 X_Audio_BACKENDS[ 0 ],
96- X_AudioSprite,
96+ X_AudioSprite, // dispatcher として
9797 X_Array_copy( urls ),
9898 {
9999 'volume' : 0 <= volume && volume <= 1 ? volume : 1,
@@ -369,7 +369,7 @@ function X_AudioSprite_backendHandler( e ){
369369 // HTMLAudio
370370 ( e[ 'needTouchForLoad' ] && ( _e[ 'needTouchForLoad' ] = true ) )
371371 ){
372- X_AudioSprite_TEMP.event = _e;
372+ X_AudioSprite_TEMP.tmpEvent = _e;
373373 last[ 'listenOnce' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH, X_AudioSprite_backendHandler );
374374 } else {
375375 X_AudioSprite[ 'asyncDispatch' ]( _e );
@@ -388,8 +388,8 @@ function X_AudioSprite_backendHandler( e ){
388388
389389 case X_EVENT_MEDIA_WAIT_FOR_TOUCH :
390390 // TODO 全ての track の MEDIA_WAIT_FOR_TOUCH で!
391- X_AudioSprite[ 'asyncDispatch' ]( X_AudioSprite_TEMP.event );
392- delete X_AudioSprite_TEMP.event;
391+ X_AudioSprite[ 'asyncDispatch' ]( X_AudioSprite_TEMP.tmpEvent );
392+ delete X_AudioSprite_TEMP.tmpEvent;
393393 break;
394394
395395 case X_EVENT_PROGRESS :
@@ -398,6 +398,21 @@ function X_AudioSprite_backendHandler( e ){
398398
399399 case X_EVENT_READY :
400400 console.log( 'X.AudioSprite - Ready!' );
401+
402+ if( X_AudioSprite_TEMP.tmpEvent ){
403+ // このタイミングで tmpEvent が存在する場合は、タッチをスキップして Web Audio が再生可能になった
404+ // つまり他の Web Audio インスタンスでタッチによる再生が開始され、自身も再生可能になった
405+
406+ _e = X_AudioSprite_TEMP.tmpEvent;
407+ _e[ 'needTouchForPlay' ] = false;
408+
409+ X_AudioSprite
410+ [ 'unlisten' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH, X_AudioSprite_backendHandler )
411+ [ 'asyncDispatch' ]( _e );
412+
413+ delete X_AudioSprite_TEMP.tmpEvent;
414+ };
415+
401416 for( i = 0; i < X_AudioSprite_numTracks; ++i ){
402417 track = X_AudioSprite_TEMP.tracks[ i ];
403418 ( track.autoplay || track._playReserved ) && track.actualPlay();
旧リポジトリブラウザで表示