Source: env/media/cordovaAudio.js


define(['mmirf/mediaManager'], function(mediaManager){

var globalCtx = typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : typeof global !== 'undefined' ? global : this;

/**
 * Audio handling for Cordova environment
 *
 * @class
 * @name CordovaAudioOutput
 * @memberOf mmir.env.media
 * @hideconstructor
 *
 * @requires cordova-plugin-media
 * @requires window.URL or window.webkitURL for #playWAV
 */
return {
	/**  @memberOf mmir.env.media.CordovaAudioOutput# */
	initialize: function(callBack){

		/**
		 * @default "cordovaAudio"
		 * @readonly
		 * @protected
		 * @memberOf mmir.env.media.CordovaAudioOutput#
		 */
		var _pluginName = 'cordovaAudio';

		/**
		 * HELPER for releasing data-URL
		 *
		 * @param {String} dataUrl
		 * 			The data URL for the audio blob
		 *
		 * @private
		 * @memberOf mmir.env.media.CordovaAudioOutput#
		 */
		function releaseDataUrl(dataUrl){

			if(globalCtx.URL || globalCtx.webkitURL){
				(globalCtx.URL || globalCtx.webkitURL).revokeObjectURL(dataUrl);
			}
			else {
				mediaManager._log.d('cannot release media URL: no URL.revokeObjectURL() available!')
			}
		}

		//invoke the passed-in initializer-callback and export the public functions:
		callBack({
			/**
			 * @public
			 * @memberOf mmir.env.media.CordovaAudioOutput.prototype
			 * @see mmir.MediaManager#playWAV
			 * @copydoc mmir.MediaManager#playWAV
			 * @function
			 */
			playWAV: function(blob, successCallback, failureCallback){
				try {
					var blobURL = (globalCtx.URL || globalCtx.webkitURL).createObjectURL(blob);
					var my_media = new Media(
							blobURL,
							function(){
//									console.log('WAV Audio created');

								my_media.release();
								releaseDataUrl(blobURL);
								if(successCallback){
									successCallback();
								}
							},failureCallback
					);

					my_media.play();

				} catch (e){
					if(failureCallback){
						failureCallback(e);
					}
				}
			},
			/**
			 * @public
			 * @memberOf mmir.env.media.CordovaAudioOutput.prototype
			 * @see mmir.MediaManager#playURL
			 * @copy mmir.MediaManager#playURL
			 * @function
			 */
			playURL: function(url, successCallback, failureCallback){
				try {
//						console.log(url);
					var my_media = new Media(
							url,
							function(){
//									console.log('Audio played');

								my_media.release();
								if(successCallback){
									successCallback.apply(my_media,arguments);
								}
							},
							failureCallback
					);

					my_media.play();
				} catch (e){
					if(failureCallback){
						failureCallback.apply(my_media,arguments);
					}
				}
			},
			/**
			 * @public
			 * @memberOf mmir.env.media.CordovaAudioOutput.prototype
			 * @see mmir.MediaManager#play
			 * @copydoc mmir.MediaManager#play
			 * @function play
			 */
			play: mediaManager.play,
			/**
			 * @public
			 * @memberOf mmir.env.media.CordovaAudioOutput.prototype
			 * @see mmir.MediaManager#getURLAsAudio
			 * @copydoc mmir.MediaManager#getURLAsAudio
			 */
			getURLAsAudio: function(url, onEnd, failureCallback, onCanPlay){

				try {

					/**
					 * @private
					 * @memberOf AudioCordovaImpl#
					 */
					var playStatus = 0;
					/**
					 * @private
					 * @memberOf AudioCordovaImpl#
					 */
					var my_media = new Media(
							url
							,null //DEBUG: function(){console.log('native onReady CB');}
							,failureCallback
							,function(status){
//									console.debug("media status change "+playStatus+" -> "+status+"  for: "+url);

								playStatus = status;

								if (status==1){
									if (onCanPlay){
										onCanPlay.apply(mediaImpl, arguments);
										onCanPlay = null;//remove onCanPlay callback after first invocation
									}
								}
//									else if (status==2){
//									console.log("Audio started");
//									}
//									else if (status==3){
//									console.log("Audio paused");
//									}
								else if(status == 4){
									if (onEnd){
										onEnd.apply(mediaImpl, arguments);
									}
								}
							}
					);

					/**
					 * @private
					 * @memberOf AudioCordovaImpl#
					 */
					var enabled = true;


					/**
					 * The Audio abstraction that is returned by {@link mmir.MediaManager#getURLAsAudio}.
					 *
					 * <p>
					 * NOTE: when an audio object is not used anymore, its {@link #release} method should
					 * 		 be called.
					 *
					 * <p>
					 * This is the same interface as {@link mmir.env.media.AudioHtml5Impl}.
					 *
					 * @class
					 * @name AudioCordovaImpl
					 * @memberOf mmir.env.media
					 * @implements mmir.env.media.IAudio
					 * @hideconstructor
					 * @public
					 */
					var mediaImpl = {
							/**
							 * Play audio.
							 *
							 * @inheritdoc
							 * @name play
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							play: function(){
								if (enabled){
									my_media.play();
									return playStatus >= 1;
								}
								return false;
							},
							/**
							 * Stop playing audio.
							 *
							 * @inheritdoc
							 * @name stop
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							stop: function(){
								//use "manual" stop instead of Cordova's stop
								//in order to allow "forgiving" behavior when audio is already stopped
								//	-> Cordova's stop() requires the audio to be playing, otherwise an error is thrown/triggered

//									console.info('CordovaAudio.stop[state '+playStatus
//											+', duration '+my_media.duration
//											+', position '+my_media.position
////											+', currentPosition '+my_media.getCurrentPosition()
//											+']: '+url);

								//only try to stop if playing and/or paused
								if(playStatus == 2 || playStatus == 3){
									my_media.stop();
									return true;
								}

//									if(playStatus == 2){//playing
//										my_media.stop();
//									}
//									else if(playStatus == 3){//paused
//										my_media.seekTo(0);
//									}
////									my_media.stop();
								return playStatus === 4;
							},
							/**
							 * Enable audio (should only be used internally).
							 *
							 * @inheritdoc
							 * @name enable
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							enable: function(){
								enabled = true;
							},
							/**
							 * Disable audio (should only be used internally).
							 *
							 * @inheritdoc
							 * @name disable
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							disable: function(){
								if(enabled){
									this.stop();
									enabled = false;
								}
							},
							/**
							 * Release audio: should be called when the audio
							 * file is not used any more.
							 *
							 * NOTE Android has limited resources available - not releasing resources
							 *      may result in not being able to instantiate new (audio) resources.
							 *
							 * @inheritdoc
							 * @name release
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							release: function(){
								if(enabled && ! this.isPaused()){
									this.stop();
								}
								enabled= false;
								if(my_media){
									my_media.release();
								}

							},
							/**
							 * Set the volume of this audio file
							 *
							 * @param {Number} value
							 * 			the new value for the volume:
							 * 			a number between [0.0, 1.0]
							 *
							 * @inheritdoc
							 * @name setVolume
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							setVolume: function(value){
								if(my_media){
									my_media.setVolume(value);
								}
							},
							/**
							 * Get the duration of the audio file
							 *
							 * @returns {Number} the duration in MS (or -1 if unknown)
							 *
							 * @inheritdoc
							 * @name getDuration
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							getDuration: function(){
								if(my_media){
									return my_media.duration;
								}
								return -1;
							},
							/**
							 * Check if audio is currently paused.
							 *
							 * NOTE: "paused" is a different status than "stopped".
							 *
							 * @returns {Boolean} TRUE if paused, FALSE otherwise
							 *
							 * @inheritdoc
							 * @name isPaused
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							isPaused: function(){
								if(my_media){
									return playStatus == 3;
								}
								return false;
							},
							/**
							 * Check if audio is currently enabled
							 *
							 * @returns {Boolean} TRUE if enabled
							 *
							 * @inheritdoc
							 * @name isEnabled
							 * @memberOf mmir.env.media.AudioCordovaImpl.prototype
							 */
							isEnabled: function(){
								return enabled;
							}
					};

					//WORK-AROUND for Android: need to invoke a method on the Media object in
					//							order to trigger the on-init callback.
					my_media.seekTo(0);


					return mediaImpl;

				} catch (e){
					console.error(e);
					if(failureCallback){
						failureCallback(e);
					}
				}
			},//END: getURLAsAudio
			/**
			 * @public
			 * @memberOf mmir.env.media.CordovaAudioOutput.prototype
			 * @see mmir.MediaManager#getAudio
			 * @copydoc mmir.MediaManager#getAudio
			 * @function
			 */
			getAudio: function(url, onPlayedCallback, failureCallBack, onLoadedCallBack){
				if(typeof url !== 'string'){
					mediaManager._log.error(_pluginName+'.getAudio(): getWAVAsAudio is not supported by this module.');
				} else {
					return this.getURLAsAudio.apply(this, arguments);
				}
			}

		});//END: callBack({...
	}
};

});//END module wrapper/factory