リビジョン | 4e4ab3be10850546063d4a4b93250ed142bb8cd2 (tree) |
---|---|
日時 | 2016-05-13 07:45:05 |
作者 | itozyun <itozyun@user...> |
コミッター | itozyun |
Version 0.6.217, add #switch for X.Audio.
@@ -68,7 +68,11 @@ X[ 'URL' ] = { | ||
68 | 68 | |
69 | 69 | 'cleanup' : X_URL_cleanup, |
70 | 70 | |
71 | - 'getEXT' : X_URL_getEXT | |
71 | + 'getEXT' : X_URL_getEXT, | |
72 | + | |
73 | + 'getSearch' : X_URL_getSearch, | |
74 | + | |
75 | + 'getHash' : X_URL_getHash | |
72 | 76 | }; |
73 | 77 | |
74 | 78 | // ------------------------------------------------------------------------- // |
@@ -152,6 +156,29 @@ function X_URL_getEXT( path ){ | ||
152 | 156 | return path.length ? path.pop() : ''; |
153 | 157 | }; |
154 | 158 | /** |
159 | + * サーチクエリを返します。 | |
160 | + * @alias X.URL.getSearch | |
161 | + * @param {string} | |
162 | + * @return {string} | |
163 | + */ | |
164 | +function X_URL_getSearch( path ){ | |
165 | + path = path.split( '#' )[ 0 ].split( '?' ); | |
166 | + path.splice( 0, 1 ); | |
167 | + return path.join( '?' ); | |
168 | +} | |
169 | +/** | |
170 | + * ハッシュフラグメントを返します。 | |
171 | + * @alias X.URL.getHash | |
172 | + * @param {string} | |
173 | + * @return {string} | |
174 | + */ | |
175 | +function X_URL_getHash( path ){ | |
176 | + path = path.split( '#' ); | |
177 | + path.splice( 0, 1 ); | |
178 | + return path.join( '#' ); | |
179 | +} | |
180 | + | |
181 | +/** | |
155 | 182 | * object を url パラメータにします。値が object の場合、データは失われます。 |
156 | 183 | * @alias X.URL.objToParam |
157 | 184 | * @param {object} |
@@ -112,7 +112,7 @@ var // 内部イベント | ||
112 | 112 | X_EVENT_MEDIA_ENDED = 46, |
113 | 113 | X_EVENT_MEDIA_WAITING = 47, |
114 | 114 | X_EVENT_MEDIA_SEEKING = 48, |
115 | - X_EVENT_MEDIA_TOUCH_FOR_LOAD = 49, | |
115 | + X_EVENT_MEDIA_WAIT_FOR_TOUCH = 49, | |
116 | 116 | |
117 | 117 | X_EVENT_NEED_AUTH = 50, |
118 | 118 |
@@ -228,7 +228,7 @@ X[ 'Event' ] = /** @lends X.Event */ | ||
228 | 228 | 'MEDIA_ENDED' : X_EVENT_MEDIA_ENDED, |
229 | 229 | 'MEDIA_WAITING' : X_EVENT_MEDIA_WAITING, |
230 | 230 | 'MEDIA_SEEKING' : X_EVENT_MEDIA_SEEKING, |
231 | - 'MEDIA_TOUCH_FOR_LOAD' : X_EVENT_MEDIA_TOUCH_FOR_LOAD, | |
231 | + 'MEDIA_WAIT_FOR_TOUCH' : X_EVENT_MEDIA_WAIT_FOR_TOUCH, | |
232 | 232 | |
233 | 233 | 'NEED_AUTH' : X_EVENT_NEED_AUTH, |
234 | 234 |
@@ -131,11 +131,11 @@ function X_TextRange_getRawRange( tr ){ | ||
131 | 131 | range.selectNodeContents( text ); // selectNodeContents は TextNode のみ?? Firefox |
132 | 132 | l = text.data.length; |
133 | 133 | |
134 | - for( j = 0, x = tr.v1, y = tr.v2; j < l; ++j ) { | |
134 | + for( j = 0, x = tr.v1, y = tr.v2; j < l; ++j ){ | |
135 | 135 | if( range ){ |
136 | 136 | range.setStart( text, j ); |
137 | 137 | range.setEnd( text, j + 1 ); |
138 | - rect = range.getBoundingClientRect(); | |
138 | + rect = range.getBoundingClientRect(); | |
139 | 139 | }; |
140 | 140 | if( rect.left <= x && x <= rect.right && rect.top <= y && y <= rect.bottom ){ |
141 | 141 | return { |
@@ -146,7 +146,7 @@ function X_TextRange_getRawRange( tr ){ | ||
146 | 146 | }; |
147 | 147 | }; |
148 | 148 | }; |
149 | - offset += l; | |
149 | + offset += l; | |
150 | 150 | }; |
151 | 151 | range = null; |
152 | 152 | } else { |
@@ -186,7 +186,7 @@ function X_TextRange_getRect(){ | ||
186 | 186 | 'width' : rect.width, |
187 | 187 | 'height' : rect.height |
188 | 188 | }; |
189 | - //range.detach && range.detach(); | |
189 | + //range.detach && range.detach(); | |
190 | 190 | } else { |
191 | 191 | ret = { |
192 | 192 | 'x' : result.boundingLeft, |
@@ -176,7 +176,7 @@ X[ 'Net' ] = X_EventDispatcher[ 'inherits' ]( | ||
176 | 176 | }; |
177 | 177 | |
178 | 178 | opt.netType = type; |
179 | - opt[ 'url' ] = url; | |
179 | + opt[ 'url' ] = url; | |
180 | 180 | |
181 | 181 | X_Pair_create( this, opt ); |
182 | 182 |
@@ -228,8 +228,7 @@ if( X_XHR_w3c || X_XHR_msXML ){ | ||
228 | 228 | |
229 | 229 | // http://www.quirksmode.org/blog/archives/2005/09/xmlhttp_notes_r_1.html |
230 | 230 | if( !X_XHR._isMsXML && raw.overrideMimeType ){ |
231 | - type = X_URL_getEXT( url ) || dataType; | |
232 | - switch( type ){ | |
231 | + switch( type = dataType ){ | |
233 | 232 | case 'html' : |
234 | 233 | case 'htm' : |
235 | 234 | case 'xml' : |
@@ -34,7 +34,7 @@ X_TEMP.onSystemReady.push( | ||
34 | 34 | * <dt>X.Event.BACKEND_READY <dd>音声(src リスト)を再生可能なバックエンドが見つかった。 |
35 | 35 | * <dt>X.Event.BACKEND_NONE <dd>音声を再生可能なバックエンドが見つからなかった。Audio は kill されます。 |
36 | 36 | * <dt>X.Event.MEDIA_CAN_TOUCH <dd>モバイル端末の制約で音声の再生またはロードに、タッチを必要とする場合、タッチイベント内で play を呼び出す準備が出来たことを通知する。 |
37 | - * <dt>X.Event.READY <dd>再生可能、実際の状態は canplay から loadeddata まで様々、、、 | |
37 | + * <dt>X.Event.READY <dd>再生可能、実際の状態は canplay から loadeddata まで様々、、、モバイル端末の場合、タッチして再生が開始された場合に | |
38 | 38 | * <dt>X.Event.ERROR <dd><ul> |
39 | 39 | * <li> 1 : ユーザーによってメディアの取得が中断された |
40 | 40 | * <li> 2 : ネットワークエラー |
@@ -49,6 +49,12 @@ X_TEMP.onSystemReady.push( | ||
49 | 49 | * <dt>X.Event.MEDIA_WAITING <dd>再生中に音声が待機状態に。 |
50 | 50 | * <dt>X.Event.MEDIA_SEEKING <dd>シーク中に音声が待機状態に。 |
51 | 51 | * </dl> |
52 | + * <h4>ソースリストに与える url 文字列</h4> | |
53 | + * <p>ハッシュフラグメント以下にデータを書くことで、各オーディオバックエンドが再生可能性の判断にあたって参考にするデータを渡すことができます。 | |
54 | + * <dl> | |
55 | + * <dt>CBR=1<dd>audio が固定ビットレートであることを示す。Android 用 Opera12- は可変ビットレートの mp3 を正しくシークできない。 | |
56 | + * [ 'snd.mp3', 'snd.mp3#CBR=1' ] と指定すると、Android 用 Opera12- では CBR な mp3 が、他の環境ではよりファイルサイズの小さい VBR な mp3 が使用される。(未実装) | |
57 | + * <dt>ext=mp3<dd>パスに拡張子が含まれない場合、または上書き指定したい場合に指定する | |
52 | 58 | * |
53 | 59 | * @alias X.Audio |
54 | 60 | * @class 各種オーディオ機能をラップしインターフェイスを共通化する。 |
@@ -211,7 +217,7 @@ audio.setState( | ||
211 | 217 | ); |
212 | 218 | |
213 | 219 | function X_Audio_handleEvent( e ){ |
214 | - var backend, pair; | |
220 | + var backend, src, pair; | |
215 | 221 | |
216 | 222 | switch( e.type ){ |
217 | 223 | case X_EVENT_BACKEND_READY : |
@@ -252,8 +258,9 @@ function X_Audio_handleEvent( e ){ | ||
252 | 258 | */ |
253 | 259 | |
254 | 260 | function X_Audio_startDetectionBackend( backend, xaudio, sourceList, option ){ |
255 | - var source = sourceList[ 0 ] || '', | |
256 | - ext = X_URL_getEXT( source ), | |
261 | + var source = sourceList[ 0 ] || '', | |
262 | + hash = X_URL_paramToObj( X_URL_getHash( source ) ), | |
263 | + ext = hash[ 'ext' ] || X_URL_getEXT( source ), | |
257 | 264 | sup; |
258 | 265 | |
259 | 266 | if( source && backend ){ |
@@ -261,29 +268,36 @@ function X_Audio_startDetectionBackend( backend, xaudio, sourceList, option ){ | ||
261 | 268 | sup[ 5 ] = sup; |
262 | 269 | |
263 | 270 | xaudio[ 'listenOnce' ]( X_EVENT_COMPLETE, backend, X_Audio_onEndedDetection, sup ); |
264 | - backend.detect( xaudio, source, ext ); | |
271 | + backend.detect( xaudio, ext, hash ); | |
265 | 272 | } else { |
266 | 273 | xaudio[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE ); |
267 | 274 | }; |
268 | 275 | }; |
269 | 276 | |
270 | 277 | function X_Audio_onEndedDetection( e, xaudio, sourceList, option, source, ext, sup ){ |
271 | - var i = X_Audio_BACKENDS.indexOf( this ), backend; | |
278 | + var i = X_Audio_BACKENDS.indexOf( this ), _e, hash, backend; | |
272 | 279 | |
273 | 280 | if( e.canPlay ){ |
274 | - xaudio[ 'asyncDispatch' ]( { | |
281 | + _e = { | |
275 | 282 | type : X_EVENT_BACKEND_READY, |
276 | 283 | 'option' : option, |
277 | 284 | 'source' : source, |
278 | - 'backendName' : this[ 'backendName' ], | |
285 | + 'backendName' : this.backendName, | |
279 | 286 | 'backendID' : i |
280 | - } ); | |
287 | + }; | |
288 | + // WebAudio | |
289 | + if( this.backendID === 1 ) _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch; | |
290 | + // HTMLAudio | |
291 | + if( this.backendID === 2 ) _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch; | |
292 | + | |
293 | + xaudio[ 'asyncDispatch' ]( _e ); | |
281 | 294 | } else { |
282 | - console.log( 'No ' + source + ' ' + this[ 'backendName' ] ); | |
295 | + console.log( 'No ' + source + ' ' + this.backendName ); | |
283 | 296 | if( sup[ 3 ] = source = sourceList[ sourceList.indexOf( source ) + 1 ] ){ |
284 | - sup[ 4 ] = ext = X_URL_getEXT( source ); | |
297 | + hash = X_URL_paramToObj( X_URL_getHash( source ) ); | |
298 | + sup[ 4 ] = ext = hash[ 'ext' ] || X_URL_getEXT( source ); | |
285 | 299 | xaudio[ 'listenOnce' ]( X_EVENT_COMPLETE, this, X_Audio_onEndedDetection, sup ); |
286 | - this.detect( xaudio, source, ext ); | |
300 | + this.detect( xaudio, ext, hash ); | |
287 | 301 | } else |
288 | 302 | if( backend = X_Audio_BACKENDS[ i + 1 ] ){ |
289 | 303 | X_Audio_startDetectionBackend( backend, xaudio, sourceList, option ); |
@@ -306,7 +306,7 @@ if( X_WebAudio_context ){ | ||
306 | 306 | this.audioBuffer = buffer; |
307 | 307 | this.duration = buffer.duration * 1000; |
308 | 308 | |
309 | - this.disatcher[ 'asyncDispatch' ]( X_WebAudio_touchState ? X_EVENT_MEDIA_TOUCH_FOR_LOAD : X_EVENT_READY ); | |
309 | + this.disatcher[ 'asyncDispatch' ]( X_WebAudio_touchState ? X_EVENT_MEDIA_WAIT_FOR_TOUCH : X_EVENT_READY ); | |
310 | 310 | }, |
311 | 311 | |
312 | 312 | actualPlay : function(){ |
@@ -462,7 +462,7 @@ if( X_WebAudio_context ){ | ||
462 | 462 | |
463 | 463 | canPlay : X_Audio_codecs, |
464 | 464 | |
465 | - detect : function( proxy, source, ext ){ | |
465 | + detect : function( proxy, ext /* hash */ ){ | |
466 | 466 | proxy[ 'asyncDispatch' ]( { type : X_EVENT_COMPLETE, canPlay : X_Audio_codecs[ ext ] } ); |
467 | 467 | }, |
468 | 468 |
@@ -177,11 +177,11 @@ if( X_Audio_constructor ){ | ||
177 | 177 | if( X_HTMLAudio_need1stTouch ){ |
178 | 178 | raw.src = source; |
179 | 179 | } else { |
180 | - // if( this.autoplay ){ | |
180 | + if( this.autoplay ){ | |
181 | 181 | raw.preload = 'auto'; |
182 | 182 | raw.autoplay = true; // Android 4.0-4.1.x で必要 |
183 | 183 | //raw.autobuffer = true; |
184 | - //}; | |
184 | + }; | |
185 | 185 | raw.src = source; |
186 | 186 | raw.load(); // Android4.1.1 HTL21 では必要! |
187 | 187 | }; |
@@ -379,7 +379,7 @@ if( X_Audio_constructor ){ | ||
379 | 379 | if( this._touchState === 1 ){ |
380 | 380 | if( e.type === X_HTMLAudio_playTrigger ){ |
381 | 381 | this._touchState = 2; |
382 | - this.disatcher[ 'asyncDispatch' ]( X_EVENT_MEDIA_TOUCH_FOR_LOAD ); | |
382 | + this.disatcher[ 'asyncDispatch' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH ); | |
383 | 383 | }; |
384 | 384 | } else |
385 | 385 | if( ended ){ |
@@ -407,7 +407,7 @@ if( X_Audio_constructor ){ | ||
407 | 407 | |
408 | 408 | actualPlay : function( forcePlay, forceReload ){ |
409 | 409 | var raw = this[ '_rawObject' ], |
410 | - e, begin, end; | |
410 | + begin, end; | |
411 | 411 | |
412 | 412 | if( !raw ) return; |
413 | 413 |
@@ -425,11 +425,13 @@ if( X_Audio_constructor ){ | ||
425 | 425 | }; |
426 | 426 | |
427 | 427 | if( this._touchState === 2 ){ |
428 | - e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ]; | |
428 | + //@dev{ | |
429 | + var e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ]; | |
429 | 430 | if( !e || !e[ 'pointerType' ] ){ |
430 | 431 | alert( 'タッチイベント以外での play! ' + ( e ? e.type : '' ) ); |
431 | 432 | return; |
432 | 433 | }; |
434 | + //@} | |
433 | 435 | this._touchState = 3; |
434 | 436 | } else |
435 | 437 | if( this._readyState !== 3 && this._durationFixPhase < 2 ){ |
@@ -578,7 +580,9 @@ if( X_Audio_constructor ){ | ||
578 | 580 | * - volume, muted iPhone(iOS4-6)、Android(2.3.6)では動作せず。 |
579 | 581 | * - FireFox3.6, Android 2.3.6については、src変更後、load()を呼び出さないと切り替わらなかった。iPhoneはload()が不要。 |
580 | 582 | */ |
581 | - detect : function( proxy, source, ext ){ | |
583 | + detect : function( proxy, ext, hash ){ | |
584 | + // TODO hash.CBR | |
585 | + // 得意度で返す | |
582 | 586 | proxy[ 'asyncDispatch' ]( { type : X_EVENT_COMPLETE, canPlay : X_Audio_codecs[ ext ] } ); |
583 | 587 | }, |
584 | 588 |
@@ -412,9 +412,7 @@ if( X_Plugin_SILVER_LIGHT_VERSION ){ | ||
412 | 412 | 'wav' : true |
413 | 413 | }, |
414 | 414 | |
415 | - detect : function( proxy, source, ext ){ | |
416 | - // TODO source = .mp3#CBR | |
417 | - // 得意度で返す | |
415 | + detect : function( proxy, ext, hash ){ | |
418 | 416 | proxy[ 'asyncDispatch' ]( { type : X_EVENT_COMPLETE, canPlay : ext === 'mp3' || ext === 'm4a' || ext === 'wma' || ext === 'wav' } ); |
419 | 417 | }, |
420 | 418 |
@@ -223,7 +223,7 @@ if( X_Plugin_WMP_VERSION ){ // IETester で 6.x は不可 | ||
223 | 223 | 'aicf' : true |
224 | 224 | }, |
225 | 225 | |
226 | - detect : function( proxy, source, ext ){ | |
226 | + detect : function( proxy, ext /* hash */ ){ | |
227 | 227 | proxy[ 'asyncDispatch' ]( { type : X_EVENT_COMPLETE, canPlay : 0 <= 'mp3 m4a wma wav midi snd au aiff aicf'.indexOf( ext ) } ); |
228 | 228 | }, |
229 | 229 |
@@ -365,12 +365,12 @@ function X_AudioSprite_backendHandler( e ){ | ||
365 | 365 | // TODO 今は touch 可能で backend ready |
366 | 366 | if( |
367 | 367 | // WebAudio |
368 | - ( backend.backendID === 1 && ( _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch ) ) || | |
368 | + ( e[ 'needTouchForPlay' ] && ( _e[ 'needTouchForPlay' ] = true ) ) || | |
369 | 369 | // HTMLAudio |
370 | - ( backend.backendID === 2 && ( _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch ) ) | |
370 | + ( e[ 'needTouchForLoad' ] && ( _e[ 'needTouchForLoad' ] = true ) ) | |
371 | 371 | ){ |
372 | 372 | X_AudioSprite_TEMP.event = _e; |
373 | - last[ 'listenOnce' ]( X_EVENT_MEDIA_TOUCH_FOR_LOAD, X_AudioSprite_backendHandler ); | |
373 | + last[ 'listenOnce' ]( X_EVENT_MEDIA_WAIT_FOR_TOUCH, X_AudioSprite_backendHandler ); | |
374 | 374 | } else { |
375 | 375 | X_AudioSprite[ 'asyncDispatch' ]( _e ); |
376 | 376 | }; |
@@ -386,8 +386,8 @@ function X_AudioSprite_backendHandler( e ){ | ||
386 | 386 | [ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE ); |
387 | 387 | return X_CALLBACK_STOP_NOW; |
388 | 388 | |
389 | - case X_EVENT_MEDIA_TOUCH_FOR_LOAD : | |
390 | - // TODO 全ての track の MEDIA_TOUCH_FOR_LOAD で! | |
389 | + case X_EVENT_MEDIA_WAIT_FOR_TOUCH : | |
390 | + // TODO 全ての track の MEDIA_WAIT_FOR_TOUCH で! | |
391 | 391 | X_AudioSprite[ 'asyncDispatch' ]( X_AudioSprite_TEMP.event ); |
392 | 392 | delete X_AudioSprite_TEMP.event; |
393 | 393 | break; |