1 /**
  2  * The Render Engine
  3  * SM2
  4  *
  5  * @fileoverview The SoundManager 2 sound system.
  6  *
  7  * @author: Brett Fattori (brettf@renderengine.com)
  8  * @author: $Author: bfattori@gmail.com $
  9  * @version: $Revision: 1562 $
 10  *
 11  * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com)
 12  *
 13  * Permission is hereby granted, free of charge, to any person obtaining a copy
 14  * of this software and associated documentation files (the "Software"), to deal
 15  * in the Software without restriction, including without limitation the rights
 16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 17  * copies of the Software, and to permit persons to whom the Software is
 18  * furnished to do so, subject to the following conditions:
 19  *
 20  * The above copyright notice and this permission notice shall be included in
 21  * all copies or substantial portions of the Software.
 22  *
 23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 26  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 29  * THE SOFTWARE.
 30  *
 31  */
 32 
 33 // The class this file defines and its required classes
 34 R.Engine.define({
 35     "class":"R.sound.SM2",
 36     "requires":[
 37         "R.sound.AbstractSoundSystem"
 38     ],
 39     "includes":[
 40         "/libs/soundmanager2.js",
 41         "/libs/AC_OETags.js"
 42     ]
 43 });
 44 
 45 /**
 46  * @class Initializes the SoundManager2 sound system.  The SoundManager2 sound system will only
 47  *    render MP3 audio as supported by Flash.
 48  *
 49  * @constructor
 50  * @extends R.sound.AbstractSoundSystem
 51  */
 52 R.sound.SM2 = function () {
 53     return R.sound.AbstractSoundSystem.extend(/** @scope R.sound.SM2.prototype */{
 54 
 55         init:false,
 56         soundManager:null,
 57 
 58         /** @private */
 59         constructor:function () {
 60             this.base();
 61             if (typeof SoundManager !== "undefined") {
 62 
 63                 // Create a link to the object
 64                 this.soundManager = window.soundManager;
 65                 this.soundManager.debugMode = false;
 66 
 67                 // directory where SM2 .SWFs live
 68                 this.soundManager.url = R.Engine.getEnginePath() + '/libs/';
 69 
 70                 var swfVer = GetSwfVer();
 71                 if (swfVer && swfVer != -1) {
 72                     // Detect the version of flash available.  If 9 or higher, use 9
 73                     var hasReqestedVersion = DetectFlashVer(9, 0, 0);
 74                     if (hasReqestedVersion) {
 75                         this.soundManager.flashVersion = 9;
 76                     }
 77                     else {
 78                         this.soundManager.flashVersion = 8;
 79                     }
 80 
 81                     // Debugging enabled?
 82                     this.soundManager.debugMode = R.engine.Support.checkBooleanParam("debugSound");
 83 
 84                     var self = this;
 85 
 86                     /** @private */
 87                     this.soundManager.onload = function () {
 88                         self.init = true;
 89                         R.debug.Console.warn("SoundManager loaded successfully");
 90                         self.makeReady();
 91                     };
 92 
 93                     /** @private */
 94                     this.soundManager.onerror = function () {
 95                         self.init = false;
 96                         R.debug.Console.warn("SoundManager not loaded");
 97                     };
 98 
 99                     if (R.Engine.getEnginePath().indexOf("file:") == 0) {
100                         this.soundManager.sandbox.type = "localWithFile";
101                     }
102 
103                     this.soundManager.go();
104 
105                 }
106                 else {
107                     // Flash not installed
108                     R.debug.Console.warn("SoundManager failed: No Flash Installed");
109                     this.init = false;
110                 }
111 
112             }
113             else {
114                 // SoundManager isn't defined
115                 R.debug.Console.warn("SoundManager failed: Not loaded or defined");
116                 this.init = false;
117             }
118         },
119 
120         /**
121          * Shutdown the sound system
122          * @private
123          */
124         shutdown:function () {
125             this.soundManager.destruct();
126         },
127 
128         /**
129          * Retrieve the sound from the network, when the sound system is ready, and create the sound object.
130          * @param resourceLoader {R.resources.loades.SoundLoader} The sound resource loader
131          * @param name {String} The name of the sound object
132          * @param url {String} The URL of the sound to load
133          * @return {R.resources.types.Sound} The sound object
134          * @private
135          */
136         retrieveSound:function (resourceLoader, name, url) {
137             // See if the sound object is already cached by the given name
138             var sound = this.base(resourceLoader, name, url);
139 
140             if (sound.getSoundObject() == null) {
141                 // Nope, this is a new sound object
142 
143                 // Only MP3 files are supported
144                 if (url.indexOf(".mp3") == -1) {
145                     sound.setSupportedTypeFlag(false);
146                     return sound;
147                 }
148 
149                 if (!this.init) {
150                     return sound;
151                 }
152 
153                 // Create the sound object
154                 var sm2sound = this.soundManager.createSound({
155                     "id":name,
156                     "url":url,
157                     "autoPlay":false,
158                     "autoLoad":true,
159                     "volume":50
160                 });
161                 sound.setSoundObject(sm2sound);
162             }
163 
164             return sound;
165         },
166 
167         /**
168          * Destroy the given sound object
169          * @param sound {R.resources.types.Sound} The sound object
170          */
171         destroySound:function (sound) {
172             if (!(this.init && this.getSoundReadyState(sound))) {
173                 return;
174             }
175             sound.unload();
176         },
177 
178         /**
179          * Play the given sound object
180          * @param sound {R.resources.types.Sound} The sound object
181          */
182         playSound:function (sound) {
183             if (!(this.init && this.getSoundReadyState(sound))) {
184                 return;
185             }
186             sound.play();
187         },
188 
189         /**
190          * Stop the given sound object
191          * @param sound {R.resources.types.Sound} The sound object
192          */
193         stopSound:function (sound) {
194             if (!(this.init && this.getSoundReadyState(sound))) {
195                 return;
196             }
197             sound.stop();
198         },
199 
200         /**
201          * Pause the given sound object
202          * @param sound {R.resources.types.Sound} The sound object
203          */
204         pauseSound:function (sound) {
205             if (!(this.init && this.getSoundReadyState(sound))) {
206                 return;
207             }
208             sound.pause();
209         },
210 
211         /**
212          * Resume the given sound object
213          * @param sound {R.resources.types.Sound} The sound object
214          */
215         resumeSound:function (sound) {
216             if (!(this.init && this.getSoundReadyState(sound))) {
217                 return;
218             }
219             sound.resume();
220         },
221 
222         /**
223          * Mute the given sound object
224          * @param sound {R.resources.types.Sound} The sound object
225          */
226         muteSound:function (sound) {
227             if (!(this.init && this.getSoundReadyState(sound))) {
228                 return;
229             }
230             sound.mute();
231         },
232 
233         /**
234          * Unmute the given sound object
235          * @param sound {R.resources.types.Sound} The sound object
236          */
237         unmuteSound:function (sound) {
238             if (!(this.init && this.getSoundReadyState(sound))) {
239                 return;
240             }
241             sound.unmute();
242         },
243 
244         /**
245          * Set the volume of the given sound object
246          * @param sound {R.resources.types.Sound} The sound object
247          * @param volume {Number} A value between 0 and 100, with 0 being muted
248          */
249         setSoundVolume:function (sound, volume) {
250             if (!(this.init && this.getSoundReadyState(sound))) {
251                 return;
252             }
253             sound.setVolume(volume);
254         },
255 
256         /**
257          * Pan the given sound object from left to right
258          * @param sound {R.resources.types.Sound} The sound object
259          * @param pan {Number} A value between -100 and 100, with -100 being full left
260          *         and zero being center
261          */
262         setSoundPan:function (sound, pan) {
263             if (!(this.init && this.getSoundReadyState(sound))) {
264                 return;
265             }
266             sound.setPan(pan);
267         },
268 
269         /**
270          * Set the position, within the sound's length, to play at
271          * @param sound {R.resources.types.Sound} The sound object
272          * @param millisecondOffset {Number} The millisecond offset from the start of
273          *         the sounds duration
274          */
275         setSoundPosition:function (sound, millisecondOffset) {
276             if (!(this.init && this.getSoundReadyState(sound))) {
277                 return;
278             }
279             sound.setPosition(millisecondOffset);
280         },
281 
282         /**
283          * Get the position, in milliseconds, within a playing or paused sound
284          * @param sound {R.resources.types.Sound} The sound object
285          * @return {Number}
286          */
287         getSoundPosition:function (sound) {
288             if (!(this.init && this.getSoundReadyState(sound))) {
289                 return 0;
290             }
291             return sound.position;
292         },
293 
294         /**
295          * Get the size of the sound object, in bytes
296          * @param sound {R.resources.types.Sound} The sound object
297          * @return {Number}
298          */
299         getSoundSize:function (sound) {
300             if (!(this.init && this.getSoundReadyState(sound))) {
301                 return 0;
302             }
303             return sound.bytesTotal;
304         },
305 
306         /**
307          * Get the length (duration) of the sound object, in milliseconds
308          * @param sound {R.resources.types.Sound} The sound object
309          * @return {Number}
310          */
311         getSoundDuration:function (sound) {
312             if (!(this.init && this.getSoundReadyState(sound))) {
313                 return 0;
314             }
315             return sound.duration;
316         },
317 
318         /**
319          * Determine if the sound object is ready to be used
320          * @param sound {R.resources.types.Sound} The sound object
321          * @return {Boolean} <code>true</code> if the sound is ready
322          */
323         getSoundReadyState:function (sound) {
324             if (!this.init) {
325                 return true;
326             }
327             if (!sound) {
328                 return false;
329             }
330             return (sound.readyState == R.sound.SM2.LOAD_SUCCESS);
331         }
332 
333     }, {
334         LOAD_LOADING:1,
335         LOAD_ERROR:2,
336         LOAD_SUCCESS:3
337     });
338 
339 };