2 * original : uupaa-js SilverlightAudio.js
\r
3 * https://code.google.com/p/uupaa-js/source/browse/trunk/0.8/src/Audio/SilverlightAudio.js?r=568
\r
5 * Silverlight 4 → 5における不具合の状況
\r
6 * http://www.slideshare.net/wakabayashiy/silverlight-4-5
\r
8 * SilverlLight5 ie6&7(ietester,winxp), ie8(winxp) で動作確認。firefox32 では動作しない。(4以下の方がよい?)
\r
11 var X_Audio_SLAudio, X_Audio_SLAudioWrapper,
\r
12 X_Audio_SLAudio_uid = 0,
\r
13 X_Audio_SLAudio_LIVE_LIST = [],
\r
14 X_Audio_SLAudio_POOL_LIST = [];
\r
16 if( X.Pulgin.SilverlightEnabled ){
\r
18 function getSLAudioWrapper( proxy ){
\r
19 var i = X_Audio_SLAudio_LIVE_LIST.length;
\r
21 if( X_Audio_SLAudio_LIVE_LIST[ --i ].proxy === proxy ) return X_Audio_SLAudio_LIVE_LIST[ i ];
\r
25 X_Audio_SLAudio = X.Class._override(
\r
26 new X.EventDispatcher(),
\r
28 backendName : 'Silverlight Audio',
\r
30 detect : function( source, ext ){
\r
31 var ok = ext === 'mp3' || ext === 'wma';
\r
33 this.asyncDispatch( 0, ok ? 'support' : 'nosupport' );
\r
38 register : function( proxy, source, option ){
\r
39 X_Audio_SLAudio_LIVE_LIST.push( new X_Audio_SLAudioWrapper( proxy, source, option ) );
\r
43 return getSLAudioWrapper( this ).close();
\r
46 play : function( position ){
\r
47 return getSLAudioWrapper( this ).play( position );
\r
51 return getSLAudioWrapper( this ).pause();
\r
55 return getSLAudioWrapper( this ).stop();
\r
58 loop : function( v ){
\r
59 return getSLAudioWrapper( this ).loop( v );
\r
63 return getSLAudioWrapper( this ).state();
\r
66 volume : function( v ){
\r
67 return getSLAudioWrapper( this ).volume( v );
\r
70 startTime : function( time ){
\r
71 return getSLAudioWrapper( this ).startTime( time );
\r
74 currentTime : function( time ){
\r
75 return getSLAudioWrapper( this ).currentTime( time );
\r
78 isPlaying : function(){
\r
79 return getSLAudioWrapper( this ).isPlaying();
\r
84 X_Audio_BACKENDS.push( X_Audio_SLAudio );
\r
90 X_Audio_SLAudioWrapper = X.EventDispatcher.inherits(
\r
91 'X.AV.SilverlightAudioWrapper',
\r
92 X.Class.POOL_OBJECT,
\r
94 _isSilverlight : true, // for X.EventDispatcher.listen
\r
107 _lastUserAction : '',
\r
110 _interval : 0, // setInterval timer id
\r
112 Constructor : function( proxy, source, option ){
\r
114 if( !X_Audio_SLAudio_uid ){
\r
116 //X.Dom.Node._systemNode.create( 'script', { type : 'text/xaml', id : 'silverlightaudio' } )
\r
117 // .text( '<Canvas xmlns="http://schemas.microsoft.com/client/2007" ' +
\r
118 // 'xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"></Canvas>');
\r
121 // <script id="silverlightaudio" type="text/xaml"><Canvas xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"></Canvas></script>
\r
124 * [Silverlight 2]JavaScriptコードからSilverlightのオブジェクトを利用するには?[C#、VB]
\r
125 * http://www.atmarkit.co.jp/fdotnet/dotnettips/902slobjcallfromjs/slobjcallfromjs.html
\r
126 * このページのサンプルは sl5+firefox32 環境で動いている。xaml を js から利用する形ではなく、.xap を sl4 以下で作るのがよさそう.
\r
128 this.proxy = proxy;
\r
129 this._onload = 'XAudioSilverlightOnLoad';// + ( ++X_Audio_SLAudio_uid );
\r
130 this._callback = window[ this._onload ] = X.Callback.create( this, this.onSLReady, [ option.autoplay ] );
\r
131 this.xnodeObject = X.Dom.Node._body
\r
132 .create( 'object', {
\r
133 type : 'application/x-silverlight-2',
\r
134 data : 'data:application/x-silverlight-2,',
\r
139 '<param name="background" value="#00000000">' + // transparent
\r
140 '<param name="windowless" value="true">' +
\r
141 '<param name="source" value="#silverlightaudio">' + // XAML ID
\r
142 '<param name="onload" value="' + this._onload + '">'// + // bond to global
\r
143 //'<param value="2.0.31005.0" name="minRuntimeVersion">' +
\r
144 //'<param value="true" name="autoUpgrade">' +
\r
145 //'<param name="onerror" value="slerror">' // bond to global
\r
148 this._loop = option.loop;
\r
149 this._source = source;
\r
150 if( option.volume ) this._volume = option.volume;
\r
151 if( option.startTime ) this._startTime = option.startTime;
\r
153 this.listenOnce( X.Event.KILL_INSTANCE );
\r
156 onSLReady : function( sender, autoplay ){
\r
157 if( !this._onload ) return;
\r
159 window[ this._onload ] = null;
\r
160 delete this._onload;
\r
161 this._callback.kill();
\r
162 delete this._callback;
\r
164 sender.children.add(
\r
168 '<Canvas xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">' +
\r
169 '<MediaElement x:Name="media" Source="' + this._source + '" Volume="' + this._volume + '" AutoPlay="false" />' +
\r
172 this._rawObject = sender.findName('media'); // x:Name='media'
\r
174 this.listen( [ 'MediaFailed', 'MediaOpened', 'MediaEnded', 'CurrentStateChanged' ] );
\r
176 autoplay && X.Timer.once( 100, this, this.play );
\r
179 handleEvent : function( e ){
\r
180 var lastState, currentState;
\r
184 case 'MediaFailed' :
\r
186 this._ended = true;
\r
187 this._paused = false;
\r
189 this.proxy.dispatch( 'error' ); // open failed
\r
191 case 'MediaOpened' :
\r
192 // http://msdn.microsoft.com/ja-jp/library/bb979710(VS.95).aspx
\r
193 this._duration = this._rawObject.NaturalDuration.Seconds;
\r
194 // TODO 'canplaythrough'
\r
195 this.proxy.dispatch( 'canplay' );
\r
197 case 'MediaEnded' :
\r
198 this.currentTime(this._startTime);
\r
201 this._rawObject.play();
\r
204 case 'CurrentStateChanged' :
\r
205 lastState = this._lastState,
\r
206 currentState = this._rawObject.CurrentState;
\r
208 // ignore consecutive events or 'Closed' == 'Error'
\r
209 if( lastState === currentState
\r
210 || ( (lastState === 'Closed' || lastState === 'Error') && ( currentState === 'Closed' || currentState === 'Error') ) ){
\r
213 this._lastState = currentState; // update last state
\r
215 switch (currentState) {
\r
220 // media.play(none supported file) -> 'Error'
\r
221 // media.play(file not found) -> 'Closed'
\r
222 // media.load -> 'Error'
\r
226 this._ended = true;
\r
227 this._paused = false;
\r
228 this.proxy.dispatch( 'error' );
\r
231 // userAction.pause() -> MediaState('Paused') -> x
\r
232 // userAction.stop() -> MediaState('Paused') -> x
\r
233 // userAction.play() + file end -> MediaState('Paused') -> uueventfire('ended')
\r
235 switch (this._lastUserAction) {
\r
236 case 'play': // play() -> file end -> event('ended')
\r
237 this._ended = true;
\r
238 this._paused = false;
\r
239 this.proxy.dispatch( 'ended' );
\r
240 this.currentTime(this._startTime);
\r
243 this._ended = false;
\r
244 this._paused = true;
\r
247 this._ended = true;
\r
248 this._paused = false;
\r
252 // media.play -> 'Playing'
\r
255 this._ended = false;
\r
256 this._paused = false;
\r
257 this.proxy.dispatch( 'playing' );
\r
262 this._ended = true;
\r
263 this._paused = false;
\r
264 this.currentTime(this._startTime);
\r
268 case X.Event.KILL_INSTANCE :
\r
269 if( this._onload ){
\r
270 window[ this._onload ] = null;
\r
271 this._callback.kill();
\r
273 this.xnodeObject.destroy();
\r
278 close : function(){
\r
279 if (this._interval) {
\r
280 X.Timer.remove( this._interval );
\r
281 delete this._interval;
\r
283 this.proxy.dispatch( 'ended' );
\r
287 // SilverlightAudio.play
\r
289 if (!this._error) {
\r
290 this._lastUserAction = 'play';
\r
292 this.currentTime(this._startTime);
\r
295 this._rawObject.play();
\r
296 this.proxy.dispatch( 'play' );
\r
298 if (!this._interval) {
\r
299 this._interval = X.Timer.add( 1000, 0, this, this._onInterval );
\r
304 _onInterval : function(){
\r
305 this.isPlaying() && this.proxy.dispatch( 'timeupdate' );
\r
308 // SilverlightAudio.pause
\r
309 pause : function(){
\r
310 if (!this._error) {
\r
311 this._lastUserAction = 'pause';
\r
312 this._paused = true;
\r
313 this._ended = false;
\r
314 this._rawObject.pause();
\r
315 this.proxy.dispatch( 'pause' );
\r
319 // SilverlightAudio.stop
\r
321 if (!this._error) {
\r
322 this._lastUserAction = 'stop';
\r
323 this._rawObject.stop();
\r
324 this._ended = true;
\r
328 // SilverlightAudio.loop
\r
329 loop : function(value){ // @param Boolean: true is loop
\r
330 // @return Boolean/void: true is loop
\r
331 if (value === undefined) {
\r
334 this._loop = value;
\r
337 // SilverlightAudio.state
\r
338 state : function(){ // @return Hash: { loop, error, paused, ended, source, duration }
\r
341 error: this._error,
\r
342 paused: this._paused,
\r
343 ended: this._ended,
\r
344 source: this._source,
\r
345 duration: this._duration
\r
349 // SilverlightAudio.volume
\r
350 volume : function(value){ // @param Number: 0.0 ~ 1.0
\r
351 // @return Number/void:
\r
352 if (value === undefined) {
\r
353 return this._volume;
\r
355 this._volume = value;
\r
356 this._rawObject.Volume = value;
\r
359 // SilverlightAudio.startTime
\r
360 startTime : function(time){ // @param Number: time
\r
361 // @return Number/void:
\r
362 if (time === undefined) {
\r
363 return this._startTime;
\r
365 this._startTime = time;
\r
368 // SilverlightAudio.currentTime
\r
369 currentTime : function(time){ // @param Number: time
\r
370 // @return Number/void:
\r
371 var position = this._rawObject.Position; // [!] create instance
\r
373 if (time === undefined) {
\r
374 return position.Seconds;
\r
377 position.Seconds = time; // set current time
\r
379 this._rawObject.Position = position; // [!] reattach instance
\r
382 // SilverlightAudio.isPlaying
\r
383 isPlaying : function(){ // @return Boolean:
\r
384 if (!this._error && !this._paused && !this._ended) {
\r