1 /* 2 * Copyright (C) 2012-2013 DFKI GmbH 3 * Deutsches Forschungszentrum fuer Kuenstliche Intelligenz 4 * German Research Center for Artificial Intelligence 5 * http://www.dfki.de 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sublicense, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 newMediaPlugin = { 28 /** @memberOf CordovaAudioOutput# */ 29 initialize: function(callBack){//, mediaManager){//DISABLED this argument is currently un-used -> disabled 30 31 /** @memberOf CordovaAudioOutput# */ 32 var _pluginName = 'codovaAudioOutput'; 33 34 //invoke the passed-in initializer-callback and export the public functions: 35 callBack({ 36 /** 37 * @public 38 * @memberOf CordovaAudioOutput.prototype 39 * @see mmir.MediaManager#playWAV 40 */ 41 playWAV: function(blob, successCallback, failureCallback){ 42 try { 43 var blobURL = window.URL.createObjectURL(blob); 44 var my_media = new Media( 45 blobURL, 46 function(){ 47 // console.log('WAV Audio created'); 48 49 my_media.release(); 50 if(successCallback){ 51 successCallback(); 52 } 53 },failureCallback 54 ); 55 56 my_media.play(); 57 58 } catch (e){ 59 if(failureCallback){ 60 failureCallback(e); 61 } 62 } 63 }, 64 /** 65 * @public 66 * @memberOf CordovaAudioOutput.prototype 67 * @see mmir.MediaManager#playURL 68 */ 69 playURL: function(url, successCallback, failureCallback){ 70 try { 71 // console.log(url); 72 var my_media = new Media( 73 url, 74 function(){ 75 // console.log('Audio played'); 76 77 my_media.release(); 78 if(successCallback){ 79 successCallback.apply(my_media,arguments); 80 } 81 } , 82 failureCallback 83 ); 84 85 my_media.play(); 86 } catch (e){ 87 if(failureCallback){ 88 failureCallback.apply(my_media,arguments); 89 } 90 } 91 }, 92 /** 93 * @public 94 * @memberOf CordovaAudioOutput.prototype 95 * @see mmir.MediaManager#getURLAsAudio 96 */ 97 getURLAsAudio: function(url, onEnd, failureCallback, onCanPlay){ 98 99 try { 100 101 /** 102 * @private 103 * @memberOf AudioCordovaImpl# 104 */ 105 var playStatus = 0; 106 /** 107 * @private 108 * @memberOf AudioCordovaImpl# 109 */ 110 var my_media = new Media( 111 url 112 ,null //DEBUG: function(){console.log('native onReady CB');} 113 ,failureCallback 114 ,function(status){ 115 // console.debug("media status change "+playStatus+" -> "+status+" for: "+url); 116 117 playStatus = status; 118 119 if (status==1){ 120 if (onCanPlay){ 121 onCanPlay.apply(mediaImpl, arguments); 122 onCanPlay = null;//remove onCanPlay callback after first invocation 123 } 124 } 125 // else if (status==2){ 126 // console.log("Audio started"); 127 // } 128 // else if (status==3){ 129 // console.log("Audio paused"); 130 // } 131 else if(status == 4){ 132 if (onEnd){ 133 onEnd.apply(mediaImpl, arguments); 134 } 135 } 136 } 137 ); 138 139 /** 140 * @private 141 * @memberOf AudioCordovaImpl# 142 */ 143 var enabled = true; 144 145 146 /** 147 * The Audio abstraction that is returned by {@link mmir.MediaManager#getURLAsAudio}. 148 * 149 * <p> 150 * NOTE: when an audio object is not used anymore, its {@link #release} method should 151 * be called. 152 * 153 * <p> 154 * This is the same interface as {@link mmir.env.media.AudioHtml5Impl}. 155 * 156 * @class 157 * @name AudioCordovaImpl 158 * @memberOf mmir.env.media 159 * @implements mmir.env.media.IAudio 160 * @public 161 */ 162 var mediaImpl = { 163 /** 164 * Play audio. 165 * 166 * @inheritdoc 167 * @name play 168 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 169 */ 170 play: function(){ 171 if (enabled){ 172 my_media.play(); 173 } 174 }, 175 /** 176 * Stop playing audio. 177 * 178 * @inheritdoc 179 * @name stop 180 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 181 */ 182 stop: function(){ 183 //use "manual" stop instead of Cordova's stop 184 //in order to allow "forgiving" behavior when audio is already stopped 185 // -> Cordova's stop() requires the audio to be playing, otherwise an error is thrown/triggered 186 187 // console.info('CordovaAudio.stop[state '+playStatus 188 // +', duration '+my_media.duration 189 // +', position '+my_media.position 190 //// +', currentPosition '+my_media.getCurrentPosition() 191 // +']: '+url); 192 193 //only try to stop if playing and/or paused 194 if(playStatus == 2 || playStatus == 3){ 195 my_media.stop(); 196 } 197 198 // if(playStatus == 2){//playing 199 // my_media.stop(); 200 // } 201 // else if(playStatus == 3){//paused 202 // my_media.seekTo(0); 203 // } 204 //// my_media.stop(); 205 }, 206 /** 207 * Enable audio (should only be used internally). 208 * 209 * @inheritdoc 210 * @name enable 211 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 212 */ 213 enable: function(){ 214 enabled = true; 215 }, 216 /** 217 * Disable audio (should only be used internally). 218 * 219 * @inheritdoc 220 * @name disable 221 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 222 */ 223 disable: function(){ 224 if(enabled){ 225 this.stop(); 226 enabled = false; 227 } 228 }, 229 /** 230 * Release audio: should be called when the audio 231 * file is not used any more. 232 * 233 * NOTE Android has limited resources available - not releasing resources 234 * may result in not being able to instantiate new (audio) resources. 235 * 236 * @inheritdoc 237 * @name release 238 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 239 */ 240 release: function(){ 241 if(enabled && ! this.isPaused()){ 242 this.stop(); 243 } 244 enabled= false; 245 if(my_media){ 246 my_media.release(); 247 } 248 249 }, 250 /** 251 * Set the volume of this audio file 252 * 253 * @param {Number} value 254 * the new value for the volume: 255 * a number between [0.0, 1.0] 256 * 257 * @inheritdoc 258 * @name setVolume 259 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 260 */ 261 setVolume: function(value){ 262 if(my_media){ 263 my_media.setVolume(value); 264 } 265 }, 266 /** 267 * Get the duration of the audio file 268 * 269 * @returns {Number} the duration in MS (or -1 if unknown) 270 * 271 * @inheritdoc 272 * @name getDuration 273 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 274 */ 275 getDuration: function(){ 276 if(my_media){ 277 return my_media.duration; 278 } 279 return -1; 280 }, 281 /** 282 * Check if audio is currently paused. 283 * 284 * NOTE: "paused" is a different status than "stopped". 285 * 286 * @returns {Boolean} TRUE if paused, FALSE otherwise 287 * 288 * @inheritdoc 289 * @name isPaused 290 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 291 */ 292 isPaused: function(){ 293 if(my_media){ 294 return playStatus == 3; 295 } 296 return false; 297 }, 298 /** 299 * Check if audio is currently enabled 300 * 301 * @returns {Boolean} TRUE if enabled 302 * 303 * @inheritdoc 304 * @name isEnabled 305 * @memberOf mmir.env.media.AudioCordovaImpl.prototype 306 */ 307 isEnabled: function(){ 308 return enabled; 309 } 310 }; 311 312 //WORK-AROUND for Android: need to invoke a method on the Media object in 313 // order to trigger the on-init callback. 314 my_media.seekTo(0); 315 316 317 return mediaImpl; 318 319 } catch (e){ 320 console.error(e); 321 if(failureCallback){ 322 failureCallback(e); 323 } 324 } 325 }//END: getURLAsAudio 326 327 });//END: callBack({... 328 } 329 };