scratch – Blame information for rev 73
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
73 | office | 1 | /*! |
2 | * SoundJS |
||
3 | * Visit http://createjs.com/ for documentation, updates and examples. |
||
4 | * |
||
5 | * Copyright (c) 2010 gskinner.com, inc. |
||
6 | * |
||
7 | * Permission is hereby granted, free of charge, to any person |
||
8 | * obtaining a copy of this software and associated documentation |
||
9 | * files (the "Software"), to deal in the Software without |
||
10 | * restriction, including without limitation the rights to use, |
||
11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell |
||
12 | * copies of the Software, and to permit persons to whom the |
||
13 | * Software is furnished to do so, subject to the following |
||
14 | * conditions: |
||
15 | * |
||
16 | * The above copyright notice and this permission notice shall be |
||
17 | * included in all copies or substantial portions of the Software. |
||
18 | * |
||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
||
21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||
22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
||
23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
||
24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
26 | * OTHER DEALINGS IN THE SOFTWARE. |
||
27 | */ |
||
28 | |||
29 | |||
30 | //############################################################################## |
||
31 | // CordovaAudioLoader.js |
||
32 | //############################################################################## |
||
33 | |||
34 | this.createjs = this.createjs || {}; |
||
35 | |||
36 | (function () { |
||
37 | "use strict"; |
||
38 | |||
39 | /** |
||
40 | * Loader provides a mechanism to preload Cordova audio content via PreloadJS or internally. Instances are returned to |
||
41 | * the preloader, and the load method is called when the asset needs to be requested. |
||
42 | * Currently files are assumed to be local and no loading actually takes place. This class exists to more easily support |
||
43 | * the existing architecture. |
||
44 | * |
||
45 | * @class CordovaAudioLoader |
||
46 | * @param {String} loadItem The item to be loaded |
||
47 | * @extends XHRRequest |
||
48 | * @protected |
||
49 | */ |
||
50 | function Loader(loadItem) { |
||
51 | this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.SOUND); |
||
52 | |||
53 | /** |
||
54 | * A Media object used to determine if src exists and to get duration |
||
55 | * @property _media |
||
56 | * @type {Media} |
||
57 | * @protected |
||
58 | */ |
||
59 | this._media = null; |
||
60 | |||
61 | /** |
||
62 | * A time counter that triggers timeout if loading takes too long |
||
63 | * @property _loadTime |
||
64 | * @type {number} |
||
65 | * @protected |
||
66 | */ |
||
67 | this._loadTime = 0; |
||
68 | |||
69 | /** |
||
70 | * The frequency to fire the loading timer until duration can be retrieved |
||
71 | * @property _TIMER_FREQUENCY |
||
72 | * @type {number} |
||
73 | * @protected |
||
74 | */ |
||
75 | this._TIMER_FREQUENCY = 100; |
||
76 | }; |
||
77 | var p = createjs.extend(Loader, createjs.AbstractLoader); |
||
78 | |||
79 | |||
80 | // public methods |
||
81 | p.load = function() { |
||
82 | this._media = new Media(this._item.src, null, createjs.proxy(this._mediaErrorHandler,this)); |
||
83 | this._media.seekTo(0); // needed to get duration |
||
84 | |||
85 | this._getMediaDuration(); |
||
86 | }; |
||
87 | |||
88 | p.toString = function () { |
||
89 | return "[CordovaAudioLoader]"; |
||
90 | }; |
||
91 | |||
92 | |||
93 | // private methods |
||
94 | /** |
||
95 | * Fires if audio cannot seek, indicating that src does not exist. |
||
96 | * @method _mediaErrorHandler |
||
97 | * @param error |
||
98 | * @protected |
||
99 | */ |
||
100 | p._mediaErrorHandler = function(error) { |
||
101 | this._media.release(); |
||
102 | this._sendError(); |
||
103 | }; |
||
104 | |||
105 | /** |
||
106 | * will attempt to get duration of audio until successful or time passes this._item.loadTimeout |
||
107 | * @method _getMediaDuration |
||
108 | * @protected |
||
109 | */ |
||
110 | p._getMediaDuration = function() { |
||
111 | this._result = this._media.getDuration() * 1000; |
||
112 | if (this._result < 0) { |
||
113 | this._loadTime += this._TIMER_FREQUENCY; |
||
114 | if (this._loadTime > this._item.loadTimeout) { |
||
115 | this.handleEvent({type:"timeout"}); |
||
116 | } else { |
||
117 | setTimeout(createjs.proxy(this._getMediaDuration, this), this._TIMER_FREQUENCY); |
||
118 | } |
||
119 | } else { |
||
120 | this._media.release(); |
||
121 | this._sendComplete(); |
||
122 | } |
||
123 | }; |
||
124 | |||
125 | createjs.CordovaAudioLoader = createjs.promote(Loader, "AbstractLoader"); |
||
126 | }()); |
||
127 | |||
128 | //############################################################################## |
||
129 | // CordovaAudioSoundInstance.js |
||
130 | //############################################################################## |
||
131 | |||
132 | this.createjs = this.createjs || {}; |
||
133 | |||
134 | (function () { |
||
135 | "use strict"; |
||
136 | |||
137 | /** |
||
138 | * CordovaAudioSoundInstance extends the base api of {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} and is used by |
||
139 | * {{#crossLink "CordovaAudioPlugin"}}{{/crossLink}}. |
||
140 | * |
||
141 | * @param {String} src The path to and file name of the sound. |
||
142 | * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds. |
||
143 | * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds. |
||
144 | * @param {Object} playbackResource Any resource needed by plugin to support audio playback. |
||
145 | * @class CordovaAudioSoundInstance |
||
146 | * @extends AbstractSoundInstance |
||
147 | * @constructor |
||
148 | */ |
||
149 | function CordovaAudioSoundInstance(src, startTime, duration, playbackResource) { |
||
150 | this.AbstractSoundInstance_constructor(src, startTime, duration, playbackResource); |
||
151 | |||
152 | // Public Properties |
||
153 | /** |
||
154 | * Sets the playAudioWhenScreenIsLocked property for play calls on iOS devices. |
||
155 | * @property playWhenScreenLocked |
||
156 | * @type {boolean} |
||
157 | */ |
||
158 | this.playWhenScreenLocked = null; |
||
159 | |||
160 | // Private Properties |
||
161 | /** |
||
162 | * Used to approximate the playback position by storing the number of milliseconds elapsed since |
||
163 | * 1 January 1970 00:00:00 UTC when playing |
||
164 | * Note that if js clock is out of sync with Media playback, this will become increasingly inaccurate. |
||
165 | * @property _playStartTime |
||
166 | * @type {Number} |
||
167 | * @protected |
||
168 | */ |
||
169 | this._playStartTime = null; |
||
170 | |||
171 | /** |
||
172 | * A TimeOut used to trigger the end and possible loop of audio sprites. |
||
173 | * @property _audioSpriteTimeout |
||
174 | * @type {null} |
||
175 | * @protected |
||
176 | */ |
||
177 | this._audioSpriteTimeout = null; |
||
178 | |||
179 | /** |
||
180 | * Boolean value that indicates if we are using an audioSprite |
||
181 | * @property _audioSprite |
||
182 | * @type {boolean} |
||
183 | * @protected |
||
184 | */ |
||
185 | this._audioSprite = false; |
||
186 | |||
187 | // Proxies, make removing listeners easier. |
||
188 | this._audioSpriteEndHandler = createjs.proxy(this._handleAudioSpriteComplete, this); |
||
189 | this._mediaPlayFinishedHandler = createjs.proxy(this._handleSoundComplete, this); |
||
190 | this._mediaErrorHandler = createjs.proxy(this._handleMediaError, this); |
||
191 | this._mediaProgressHandler = createjs.proxy(this._handleMediaProgress, this); |
||
192 | |||
193 | this._playbackResource = new Media(src, this._mediaPlayFinishedHandler, this._mediaErrorHandler, this._mediaProgressHandler); |
||
194 | |||
195 | if (duration) { |
||
196 | this._audioSprite = true; |
||
197 | } else { |
||
198 | this._setDurationFromSource(); |
||
199 | } |
||
200 | } |
||
201 | var p = createjs.extend(CordovaAudioSoundInstance, createjs.AbstractSoundInstance); |
||
202 | |||
203 | |||
204 | // Public Methods |
||
205 | /** |
||
206 | * Called by {{#crossLink "Sound"}}{{/crossLink}} when plugin does not handle master volume. |
||
207 | * undoc'd because it is not meant to be used outside of Sound |
||
208 | * #method setMasterVolume |
||
209 | * @param value |
||
210 | */ |
||
211 | p.setMasterVolume = function (value) { |
||
212 | this._updateVolume(); |
||
213 | }; |
||
214 | |||
215 | /** |
||
216 | * Called by {{#crossLink "Sound"}}{{/crossLink}} when plugin does not handle master mute. |
||
217 | * undoc'd because it is not meant to be used outside of Sound |
||
218 | * #method setMasterMute |
||
219 | * @param value |
||
220 | */ |
||
221 | p.setMasterMute = function (isMuted) { |
||
222 | this._updateVolume(); |
||
223 | }; |
||
224 | |||
225 | p.destroy = function() { |
||
226 | // call parent function, then release |
||
227 | this.AbstractSoundInstance_destroy(); |
||
228 | this._playbackResource.release(); |
||
229 | }; |
||
230 | |||
231 | /** |
||
232 | * Maps to <a href="http://plugins.cordova.io/#/package/org.apache.cordova.media" target="_blank">Media.getCurrentPosition</a>, |
||
233 | * which is curiously asynchronus and requires a callback. |
||
234 | * @method getCurrentPosition |
||
235 | * @param {Method} mediaSuccess The callback that is passed the current position in seconds. |
||
236 | * @param {Method} [mediaError=null] (Optional) The callback to execute if an error occurs. |
||
237 | */ |
||
238 | p.getCurrentPosition = function (mediaSuccess, mediaError) { |
||
239 | this._playbackResource.getCurrentPosition(mediaSuccess, mediaError); |
||
240 | }; |
||
241 | |||
242 | p.toString = function () { |
||
243 | return "[CordovaAudioSoundInstance]"; |
||
244 | }; |
||
245 | |||
246 | //Private Methods |
||
247 | /** |
||
248 | * media object has failed and likely will never work |
||
249 | * @method _handleMediaError |
||
250 | * @param error |
||
251 | * @private |
||
252 | */ |
||
253 | p._handleMediaError = function(error) { |
||
254 | clearTimeout(this.delayTimeoutId); // clear timeout that plays delayed sound |
||
255 | |||
256 | this.playState = createjs.Sound.PLAY_FAILED; |
||
257 | this._sendEvent("failed"); |
||
258 | }; |
||
259 | |||
260 | p._handleMediaProgress = function(state) { |
||
261 | // do nothing |
||
262 | }; |
||
263 | |||
264 | p._handleAudioSpriteComplete = function() { |
||
265 | this._playbackResource.pause(); |
||
266 | this._handleSoundComplete(); |
||
267 | }; |
||
268 | /* don't need these for current looping approach |
||
269 | p._removeLooping = function() { |
||
270 | }; |
||
271 | |||
272 | p._addLooping = function() { |
||
273 | }; |
||
274 | */ |
||
275 | |||
276 | p._handleCleanUp = function () { |
||
277 | clearTimeout(this._audioSpriteTimeout); |
||
278 | this._playbackResource.pause(); // OJR cannot use .stop as it prevents .seekTo from working |
||
279 | // todo consider media.release |
||
280 | }; |
||
281 | |||
282 | p._handleSoundReady = function (event) { |
||
283 | this._playbackResource.seekTo(this._startTime + this._position); |
||
284 | |||
285 | if (this._audioSprite) { |
||
286 | this._audioSpriteTimeout = setTimeout(this._audioSpriteEndHandler, this._duration - this._position) |
||
287 | } |
||
288 | |||
289 | this._playbackResource.play({playAudioWhenScreenIsLocked: this.playWhenScreenLocked}); |
||
290 | this._playStartTime = Date.now(); |
||
291 | }; |
||
292 | |||
293 | p._pause = function () { |
||
294 | clearTimeout(this._audioSpriteTimeout); |
||
295 | this._playbackResource.pause(); |
||
296 | if (this._playStartTime) { |
||
297 | this._position = Date.now() - this._playStartTime; |
||
298 | this._playStartTime = null; |
||
299 | } |
||
300 | this._playbackResource.getCurrentPosition(createjs.proxy(this._updatePausePos, this)); |
||
301 | }; |
||
302 | |||
303 | /** |
||
304 | * Synchronizes the best guess position with the actual current position. |
||
305 | * @method _updatePausePos |
||
306 | * @param {Number} pos The current position in seconds |
||
307 | * @private |
||
308 | */ |
||
309 | p._updatePausePos = function (pos) { |
||
310 | this._position = pos * 1000 - this._startTime; |
||
311 | if(this._playStartTime) { |
||
312 | this._playStartTime = Date.now(); |
||
313 | } |
||
314 | }; |
||
315 | |||
316 | p._resume = function () { |
||
317 | if (this._audioSprite) { |
||
318 | this._audioSpriteTimeout = setTimeout(this._audioSpriteEndHandler, this._duration - this._position) |
||
319 | } |
||
320 | |||
321 | this._playbackResource.play({playAudioWhenScreenIsLocked: this.playWhenScreenLocked}); |
||
322 | this._playStartTime = Date.now(); |
||
323 | }; |
||
324 | |||
325 | p._handleStop = function() { |
||
326 | clearTimeout(this._audioSpriteTimeout); |
||
327 | this._playbackResource.pause(); // cannot use .stop because it prevents .seekTo from working |
||
328 | this._playbackResource.seekTo(this._startTime); |
||
329 | if (this._playStartTime) { |
||
330 | this._position = 0; |
||
331 | this._playStartTime = null; |
||
332 | } |
||
333 | }; |
||
334 | |||
335 | p._updateVolume = function () { |
||
336 | var newVolume = (this._muted || createjs.Sound._masterMute) ? 0 : this._volume * createjs.Sound._masterVolume; |
||
337 | this._playbackResource.setVolume(newVolume); |
||
338 | }; |
||
339 | |||
340 | p._calculateCurrentPosition = function() { |
||
341 | // return best guess position. |
||
342 | // Note if Media and js clock are out of sync, this value will become increasingly inaccurate over time |
||
343 | if (this._playStartTime) { |
||
344 | this._position = Date.now() - this._playStartTime + this._position; |
||
345 | this._playStartTime = Date.now(); |
||
346 | } |
||
347 | return this._position; |
||
348 | }; |
||
349 | |||
350 | p._updatePosition = function() { |
||
351 | this._playbackResource.seekTo(this._startTime + this._position); |
||
352 | this._playStartTime = Date.now(); |
||
353 | if (this._audioSprite) { |
||
354 | clearTimeout(this._audioSpriteTimeout); |
||
355 | this._audioSpriteTimeout = setTimeout(this._audioSpriteEndHandler, this._duration - this._position) |
||
356 | } |
||
357 | }; |
||
358 | |||
359 | p._handleLoop = function (event) { |
||
360 | this._handleSoundReady(); |
||
361 | }; |
||
362 | |||
363 | p._updateStartTime = function () { |
||
364 | this._audioSprite = true; |
||
365 | |||
366 | if(this.playState == createjs.Sound.PLAY_SUCCEEDED) { |
||
367 | // do nothing |
||
368 | } |
||
369 | }; |
||
370 | |||
371 | p._updateDuration = function () { |
||
372 | this._audioSprite |
||
373 | |||
374 | if(this.playState == createjs.Sound.PLAY_SUCCEEDED) { |
||
375 | clearTimeout(this._audioSpriteTimeout); |
||
376 | this._audioSpriteTimeout = setTimeout(this._audioSpriteEndHandler, this._duration - this.position) |
||
377 | } |
||
378 | }; |
||
379 | |||
380 | p._setDurationFromSource = function () { |
||
381 | this._duration = createjs.Sound.activePlugin.getSrcDuration(this.src); // TODO find a better way to do this that does not break flow |
||
382 | }; |
||
383 | |||
384 | createjs.CordovaAudioSoundInstance = createjs.promote(CordovaAudioSoundInstance, "AbstractSoundInstance"); |
||
385 | }()); |
||
386 | |||
387 | //############################################################################## |
||
388 | // CordovaAudioPlugin.js |
||
389 | //############################################################################## |
||
390 | |||
391 | this.createjs = this.createjs || {}; |
||
392 | |||
393 | (function () { |
||
394 | |||
395 | "use strict"; |
||
396 | |||
397 | /** |
||
398 | * Play sounds using Cordova Media plugin, which will work with a Cordova app and tools that utilize Cordova such as PhoneGap or Ionic. |
||
399 | * This plugin is not used by default, and must be registered manually in {{#crossLink "Sound"}}{{/crossLink}} |
||
400 | * using the {{#crossLink "Sound/registerPlugins"}}{{/crossLink}} method. |
||
401 | * This plugin is recommended when building a Cordova based app, but is not required. |
||
402 | * |
||
403 | * <b>NOTE the <a href="http://plugins.cordova.io/#/package/org.apache.cordova.media" target="_blank">Cordova Media plugin</a> is required</b> |
||
404 | * |
||
405 | * cordova plugin add org.apache.cordova.media |
||
406 | * |
||
407 | * <h4>Known Issues</h4> |
||
408 | * <b>Audio Position</b> |
||
409 | * <ul>Audio position is calculated asynchronusly by Media. The SoundJS solution to this problem is two-fold: |
||
410 | * <li>Provide {{#crossLink "CordovaAudioSoundInstance/getCurrentPosition"}}{{/crossLink}} that maps directly to media.getCurrentPosition.</li> |
||
411 | * <li>Provide a best guess position based on elapsed time since playback started, which is synchronized with actual position when the audio is paused or stopped. |
||
412 | * Testing showed this to be fairly reliable within 200ms.</li></ul> |
||
413 | * <b>Cordova Media Docs</b> |
||
414 | * <ul><li>See the <a href="http://plugins.cordova.io/#/package/org.apache.cordova.media" target="_blank">Cordova Media Docs</a> for various known OS issues.</li></ul> |
||
415 | * <br /> |
||
416 | * |
||
417 | * @class CordovaAudioPlugin |
||
418 | * @extends AbstractPlugin |
||
419 | * @constructor |
||
420 | */ |
||
421 | function CordovaAudioPlugin() { |
||
422 | this.AbstractPlugin_constructor(); |
||
423 | |||
424 | this._capabilities = s._capabilities; |
||
425 | |||
426 | this._loaderClass = createjs.CordovaAudioLoader; |
||
427 | this._soundInstanceClass = createjs.CordovaAudioSoundInstance; |
||
428 | |||
429 | this._srcDurationHash = {}; |
||
430 | } |
||
431 | |||
432 | var p = createjs.extend(CordovaAudioPlugin, createjs.AbstractPlugin); |
||
433 | var s = CordovaAudioPlugin; |
||
434 | |||
435 | |||
436 | // Static Properties |
||
437 | /** |
||
438 | * Sets a default playAudioWhenScreenIsLocked property for play calls on iOS devices. |
||
439 | * Individual SoundInstances can alter the default with {{#crossLink "CordovaAudioSoundInstance/playWhenScreenLocked"}}{{/crossLink}}. |
||
440 | * @property playWhenScreenLocked |
||
441 | * @type {boolean} |
||
442 | * @static |
||
443 | */ |
||
444 | s.playWhenScreenLocked = false; |
||
445 | |||
446 | /** |
||
447 | * The capabilities of the plugin. This is generated via the {{#crossLink "CordovaAudioPlugin/_generateCapabilities"}}{{/crossLink}} |
||
448 | * method. Please see the Sound {{#crossLink "Sound/getCapabilities"}}{{/crossLink}} method for an overview of all |
||
449 | * of the available properties. |
||
450 | * @property _capabilities |
||
451 | * @type {Object} |
||
452 | * @protected |
||
453 | * @static |
||
454 | */ |
||
455 | s._capabilities = null; |
||
456 | |||
457 | |||
458 | // Static Methods |
||
459 | /** |
||
460 | * Determine if the plugin can be used in the current browser/OS. Note that HTML audio is available in most modern |
||
461 | * browsers, but is disabled in iOS because of its limitations. |
||
462 | * @method isSupported |
||
463 | * @return {Boolean} If the plugin can be initialized. |
||
464 | * @static |
||
465 | */ |
||
466 | s.isSupported = function () { |
||
467 | s._generateCapabilities(); |
||
468 | return (s._capabilities != null); |
||
469 | }; |
||
470 | |||
471 | /** |
||
472 | * Determine the capabilities of the plugin. Used internally. Please see the Sound API {{#crossLink "Sound/getCapabilities"}}{{/crossLink}} |
||
473 | * method for an overview of plugin capabilities. |
||
474 | * @method _generateCapabilities |
||
475 | * @static |
||
476 | * @protected |
||
477 | */ |
||
478 | s._generateCapabilities = function () { |
||
479 | if (s._capabilities != null || !(window.cordova || window.PhoneGap || window.phonegap) || !window.Media) {return;} |
||
480 | |||
481 | // OJR my best guess is that Cordova will have the same limits on playback that the audio tag has, but this could be wrong |
||
482 | var t = document.createElement("audio"); |
||
483 | if (t.canPlayType == null) {return null;} |
||
484 | |||
485 | s._capabilities = { |
||
486 | panning:false, |
||
487 | volume:true, |
||
488 | tracks:-1 |
||
489 | }; |
||
490 | |||
491 | // determine which extensions our browser supports for this plugin by iterating through Sound.SUPPORTED_EXTENSIONS |
||
492 | var supportedExtensions = createjs.Sound.SUPPORTED_EXTENSIONS; |
||
493 | var extensionMap = createjs.Sound.EXTENSION_MAP; |
||
494 | for (var i = 0, l = supportedExtensions.length; i < l; i++) { |
||
495 | var ext = supportedExtensions[i]; |
||
496 | var playType = extensionMap[ext] || ext; |
||
497 | s._capabilities[ext] = (t.canPlayType("audio/" + ext) != "no" && t.canPlayType("audio/" + ext) != "") || (t.canPlayType("audio/" + playType) != "no" && t.canPlayType("audio/" + playType) != ""); |
||
498 | } // OJR another way to do this might be canPlayType:"m4a", codex: mp4 |
||
499 | }; |
||
500 | |||
501 | |||
502 | // public methods |
||
503 | p.create = function (src, startTime, duration) { |
||
504 | var si = this.AbstractPlugin_create(src, startTime, duration); |
||
505 | si.playWhenScreenLocked = this.playWhenScreenLocked; |
||
506 | return si; |
||
507 | }; |
||
508 | |||
509 | p.toString = function () { |
||
510 | return "[CordovaAudioPlugin]"; |
||
511 | }; |
||
512 | |||
513 | // plugin does not support these |
||
514 | p.setVolume = p.getVolume = p.setMute = null; |
||
515 | |||
516 | /** |
||
517 | * Get the duration for a src. Intended for internal use by CordovaAudioSoundInstance. |
||
518 | * @method getSrcDuration |
||
519 | * @param src |
||
520 | * @returns {Number} The duration of the src or null if it does not exist |
||
521 | */ |
||
522 | p.getSrcDuration = function(src) { |
||
523 | return this._srcDurationHash[src]; |
||
524 | }; |
||
525 | |||
526 | // Private Methods |
||
527 | p._handlePreloadComplete = function (event) { |
||
528 | var src = event.target.getItem().src; |
||
529 | this._srcDurationHash[src] = event.result; |
||
530 | this._audioSources[src] = event.result; |
||
531 | //this.AbstractPlugin__handlePreloadComplete(event); // we don't want to do the rest of this |
||
532 | }; |
||
533 | |||
534 | p.removeSound = function (src) { |
||
535 | delete(this._srcDurationHash[src]); |
||
536 | this.AbstractPlugin_removeSound(src); |
||
537 | }; |
||
538 | |||
539 | createjs.CordovaAudioPlugin = createjs.promote(CordovaAudioPlugin, "AbstractPlugin"); |
||
540 | }()); |
||
541 | |||
542 | //############################################################################## |
||
543 | // version_cordovaplugin.js |
||
544 | //############################################################################## |
||
545 | |||
546 | this.createjs = this.createjs || {}; |
||
547 | |||
548 | (function () { |
||
549 | |||
550 | var s = createjs.CordovaAudioPlugin = createjs.CordovaAudioPlugin || {}; |
||
551 | |||
552 | /** |
||
553 | * The version string for this release. |
||
554 | * @for CordovaAudioPlugin |
||
555 | * @property version |
||
556 | * @type String |
||
557 | * @static |
||
558 | **/ |
||
559 | s.version = /*=version*/"NEXT"; // injected by build process |
||
560 | |||
561 | /** |
||
562 | * The build date for this release in UTC format. |
||
563 | * @for CordovaAudioPlugin |
||
564 | * @property buildDate |
||
565 | * @type String |
||
566 | * @static |
||
567 | **/ |
||
568 | s.buildDate = /*=date*/"Mon, 14 Sep 2015 19:11:47 GMT"; // injected by build process |
||
569 | |||
570 | })(); |