From 02811010cf62f1b21a06780d1e470d04bb24c50f Mon Sep 17 00:00:00 2001 From: Arjun Roychowdhury Date: Sat, 31 Oct 2015 08:21:38 -0400 Subject: removed unecessary files from git --- .../src/android/AudioHandler.java | 410 ------------ .../src/android/AudioPlayer.java | 587 ----------------- .../src/android/FileHelper.java | 38 -- .../src/blackberry10/index.js | 237 ------- .../org.apache.cordova.media/src/ios/CDVSound.h | 113 ---- .../org.apache.cordova.media/src/ios/CDVSound.m | 703 --------------------- .../src/tizen/MediaProxy.js | 223 ------- .../org.apache.cordova.media/src/ubuntu/media.cpp | 128 ---- .../org.apache.cordova.media/src/ubuntu/media.h | 267 -------- .../src/windows8/MediaProxy.js | 217 ------- .../org.apache.cordova.media/src/wp/AudioPlayer.cs | 647 ------------------- plugins/org.apache.cordova.media/src/wp/Media.cs | 590 ----------------- 12 files changed, 4160 deletions(-) delete mode 100644 plugins/org.apache.cordova.media/src/android/AudioHandler.java delete mode 100644 plugins/org.apache.cordova.media/src/android/AudioPlayer.java delete mode 100644 plugins/org.apache.cordova.media/src/android/FileHelper.java delete mode 100644 plugins/org.apache.cordova.media/src/blackberry10/index.js delete mode 100644 plugins/org.apache.cordova.media/src/ios/CDVSound.h delete mode 100644 plugins/org.apache.cordova.media/src/ios/CDVSound.m delete mode 100644 plugins/org.apache.cordova.media/src/tizen/MediaProxy.js delete mode 100644 plugins/org.apache.cordova.media/src/ubuntu/media.cpp delete mode 100644 plugins/org.apache.cordova.media/src/ubuntu/media.h delete mode 100644 plugins/org.apache.cordova.media/src/windows8/MediaProxy.js delete mode 100644 plugins/org.apache.cordova.media/src/wp/AudioPlayer.cs delete mode 100644 plugins/org.apache.cordova.media/src/wp/Media.cs (limited to 'plugins/org.apache.cordova.media/src') diff --git a/plugins/org.apache.cordova.media/src/android/AudioHandler.java b/plugins/org.apache.cordova.media/src/android/AudioHandler.java deleted file mode 100644 index f06b75a4..00000000 --- a/plugins/org.apache.cordova.media/src/android/AudioHandler.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.media; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaResourceApi; - -import android.content.Context; -import android.media.AudioManager; -import android.net.Uri; -import android.util.Log; - -import java.util.ArrayList; - -import org.apache.cordova.PluginResult; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; - -/** - * This class called by CordovaActivity to play and record audio. - * The file can be local or over a network using http. - * - * Audio formats supported (tested): - * .mp3, .wav - * - * Local audio files must reside in one of two places: - * android_asset: file name must start with /android_asset/sound.mp3 - * sdcard: file name is just sound.mp3 - */ -public class AudioHandler extends CordovaPlugin { - - public static String TAG = "AudioHandler"; - HashMap players; // Audio player object - ArrayList pausedForPhone; // Audio players that were paused when phone call came in - private int origVolumeStream = -1; - private CallbackContext messageChannel; - - /** - * Constructor. - */ - public AudioHandler() { - this.players = new HashMap(); - this.pausedForPhone = new ArrayList(); - } - - /** - * Executes the request and returns PluginResult. - * @param action The action to execute. - * @param args JSONArry of arguments for the plugin. - * @param callbackContext The callback context used when calling back into JavaScript. - * @return A PluginResult object with a status and message. - */ - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - CordovaResourceApi resourceApi = webView.getResourceApi(); - PluginResult.Status status = PluginResult.Status.OK; - String result = ""; - - if (action.equals("startRecordingAudio")) { - String target = args.getString(1); - String fileUriStr; - try { - Uri targetUri = resourceApi.remapUri(Uri.parse(target)); - fileUriStr = targetUri.toString(); - } catch (IllegalArgumentException e) { - fileUriStr = target; - } - this.startRecordingAudio(args.getString(0), FileHelper.stripFileProtocol(fileUriStr)); - } - else if (action.equals("stopRecordingAudio")) { - this.stopRecordingAudio(args.getString(0)); - } - else if (action.equals("startPlayingAudio")) { - String target = args.getString(1); - String fileUriStr; - try { - Uri targetUri = resourceApi.remapUri(Uri.parse(target)); - fileUriStr = targetUri.toString(); - } catch (IllegalArgumentException e) { - fileUriStr = target; - } - this.startPlayingAudio(args.getString(0), FileHelper.stripFileProtocol(fileUriStr)); - } - else if (action.equals("seekToAudio")) { - this.seekToAudio(args.getString(0), args.getInt(1)); - } - else if (action.equals("pausePlayingAudio")) { - this.pausePlayingAudio(args.getString(0)); - } - else if (action.equals("stopPlayingAudio")) { - this.stopPlayingAudio(args.getString(0)); - } else if (action.equals("setVolume")) { - try { - this.setVolume(args.getString(0), Float.parseFloat(args.getString(1))); - } catch (NumberFormatException nfe) { - //no-op - } - } else if (action.equals("getCurrentPositionAudio")) { - float f = this.getCurrentPositionAudio(args.getString(0)); - callbackContext.sendPluginResult(new PluginResult(status, f)); - return true; - } - else if (action.equals("getDurationAudio")) { - float f = this.getDurationAudio(args.getString(0), args.getString(1)); - callbackContext.sendPluginResult(new PluginResult(status, f)); - return true; - } - else if (action.equals("create")) { - String id = args.getString(0); - String src = FileHelper.stripFileProtocol(args.getString(1)); - getOrCreatePlayer(id, src); - } - else if (action.equals("release")) { - boolean b = this.release(args.getString(0)); - callbackContext.sendPluginResult(new PluginResult(status, b)); - return true; - } - else if (action.equals("messageChannel")) { - messageChannel = callbackContext; - return true; - } - else { // Unrecognized action. - return false; - } - - callbackContext.sendPluginResult(new PluginResult(status, result)); - - return true; - } - - /** - * Stop all audio players and recorders. - */ - public void onDestroy() { - if (!players.isEmpty()) { - onLastPlayerReleased(); - } - for (AudioPlayer audio : this.players.values()) { - audio.destroy(); - } - this.players.clear(); - } - - /** - * Stop all audio players and recorders on navigate. - */ - @Override - public void onReset() { - onDestroy(); - } - - /** - * Called when a message is sent to plugin. - * - * @param id The message id - * @param data The message data - * @return Object to stop propagation or null - */ - public Object onMessage(String id, Object data) { - - // If phone message - if (id.equals("telephone")) { - - // If phone ringing, then pause playing - if ("ringing".equals(data) || "offhook".equals(data)) { - - // Get all audio players and pause them - for (AudioPlayer audio : this.players.values()) { - if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal()) { - this.pausedForPhone.add(audio); - audio.pausePlaying(); - } - } - - } - - // If phone idle, then resume playing those players we paused - else if ("idle".equals(data)) { - for (AudioPlayer audio : this.pausedForPhone) { - audio.startPlaying(null); - } - this.pausedForPhone.clear(); - } - } - return null; - } - - //-------------------------------------------------------------------------- - // LOCAL METHODS - //-------------------------------------------------------------------------- - - private AudioPlayer getOrCreatePlayer(String id, String file) { - AudioPlayer ret = players.get(id); - if (ret == null) { - if (players.isEmpty()) { - onFirstPlayerCreated(); - } - ret = new AudioPlayer(this, id, file); - players.put(id, ret); - } - return ret; - } - - /** - * Release the audio player instance to save memory. - * @param id The id of the audio player - */ - private boolean release(String id) { - AudioPlayer audio = players.remove(id); - if (audio == null) { - return false; - } - if (players.isEmpty()) { - onLastPlayerReleased(); - } - audio.destroy(); - return true; - } - - /** - * Start recording and save the specified file. - * @param id The id of the audio player - * @param file The name of the file - */ - public void startRecordingAudio(String id, String file) { - AudioPlayer audio = getOrCreatePlayer(id, file); - audio.startRecording(file); - } - - /** - * Stop recording and save to the file specified when recording started. - * @param id The id of the audio player - */ - public void stopRecordingAudio(String id) { - AudioPlayer audio = this.players.get(id); - if (audio != null) { - audio.stopRecording(); - } - } - - /** - * Start or resume playing audio file. - * @param id The id of the audio player - * @param file The name of the audio file. - */ - public void startPlayingAudio(String id, String file) { - AudioPlayer audio = getOrCreatePlayer(id, file); - audio.startPlaying(file); - } - - /** - * Seek to a location. - * @param id The id of the audio player - * @param milliseconds int: number of milliseconds to skip 1000 = 1 second - */ - public void seekToAudio(String id, int milliseconds) { - AudioPlayer audio = this.players.get(id); - if (audio != null) { - audio.seekToPlaying(milliseconds); - } - } - - /** - * Pause playing. - * @param id The id of the audio player - */ - public void pausePlayingAudio(String id) { - AudioPlayer audio = this.players.get(id); - if (audio != null) { - audio.pausePlaying(); - } - } - - /** - * Stop playing the audio file. - * @param id The id of the audio player - */ - public void stopPlayingAudio(String id) { - AudioPlayer audio = this.players.get(id); - if (audio != null) { - audio.stopPlaying(); - } - } - - /** - * Get current position of playback. - * @param id The id of the audio player - * @return position in msec - */ - public float getCurrentPositionAudio(String id) { - AudioPlayer audio = this.players.get(id); - if (audio != null) { - return (audio.getCurrentPosition() / 1000.0f); - } - return -1; - } - - /** - * Get the duration of the audio file. - * @param id The id of the audio player - * @param file The name of the audio file. - * @return The duration in msec. - */ - public float getDurationAudio(String id, String file) { - AudioPlayer audio = getOrCreatePlayer(id, file); - return audio.getDuration(file); - } - - /** - * Set the audio device to be used for playback. - * - * @param output 1=earpiece, 2=speaker - */ - @SuppressWarnings("deprecation") - public void setAudioOutputDevice(int output) { - AudioManager audiMgr = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE); - if (output == 2) { - audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL); - } - else if (output == 1) { - audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL); - } - else { - System.out.println("AudioHandler.setAudioOutputDevice() Error: Unknown output device."); - } - } - - /** - * Get the audio device to be used for playback. - * - * @return 1=earpiece, 2=speaker - */ - @SuppressWarnings("deprecation") - public int getAudioOutputDevice() { - AudioManager audiMgr = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE); - if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_EARPIECE) { - return 1; - } - else if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_SPEAKER) { - return 2; - } - else { - return -1; - } - } - - /** - * Set the volume for an audio device - * - * @param id The id of the audio player - * @param volume Volume to adjust to 0.0f - 1.0f - */ - public void setVolume(String id, float volume) { - AudioPlayer audio = this.players.get(id); - if (audio != null) { - audio.setVolume(volume); - } else { - System.out.println("AudioHandler.setVolume() Error: Unknown Audio Player " + id); - } - } - - private void onFirstPlayerCreated() { - origVolumeStream = cordova.getActivity().getVolumeControlStream(); - cordova.getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC); - } - - private void onLastPlayerReleased() { - if (origVolumeStream != -1) { - cordova.getActivity().setVolumeControlStream(origVolumeStream); - origVolumeStream = -1; - } - } - - void sendEventMessage(String action, JSONObject actionData) { - JSONObject message = new JSONObject(); - try { - message.put("action", action); - if (actionData != null) { - message.put(action, actionData); - } - } catch (JSONException e) { - Log.e(TAG, "Failed to create event message", e); - } - - PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, message); - pluginResult.setKeepCallback(true); - if (messageChannel != null) { - messageChannel.sendPluginResult(pluginResult); - } - } -} diff --git a/plugins/org.apache.cordova.media/src/android/AudioPlayer.java b/plugins/org.apache.cordova.media/src/android/AudioPlayer.java deleted file mode 100644 index 7524c5b6..00000000 --- a/plugins/org.apache.cordova.media/src/android/AudioPlayer.java +++ /dev/null @@ -1,587 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.media; - -import android.media.AudioManager; -import android.media.MediaPlayer; -import android.media.MediaPlayer.OnCompletionListener; -import android.media.MediaPlayer.OnErrorListener; -import android.media.MediaPlayer.OnPreparedListener; -import android.media.MediaRecorder; -import android.os.Environment; -import android.util.Log; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -/** - * This class implements the audio playback and recording capabilities used by Cordova. - * It is called by the AudioHandler Cordova class. - * Only one file can be played or recorded per class instance. - * - * Local audio files must reside in one of two places: - * android_asset: file name must start with /android_asset/sound.mp3 - * sdcard: file name is just sound.mp3 - */ -public class AudioPlayer implements OnCompletionListener, OnPreparedListener, OnErrorListener { - - // AudioPlayer modes - public enum MODE { NONE, PLAY, RECORD }; - - // AudioPlayer states - public enum STATE { MEDIA_NONE, - MEDIA_STARTING, - MEDIA_RUNNING, - MEDIA_PAUSED, - MEDIA_STOPPED, - MEDIA_LOADING - }; - - private static final String LOG_TAG = "AudioPlayer"; - - // AudioPlayer message ids - private static int MEDIA_STATE = 1; - private static int MEDIA_DURATION = 2; - private static int MEDIA_POSITION = 3; - private static int MEDIA_ERROR = 9; - - // Media error codes - private static int MEDIA_ERR_NONE_ACTIVE = 0; - private static int MEDIA_ERR_ABORTED = 1; -// private static int MEDIA_ERR_NETWORK = 2; -// private static int MEDIA_ERR_DECODE = 3; -// private static int MEDIA_ERR_NONE_SUPPORTED = 4; - - private AudioHandler handler; // The AudioHandler object - private String id; // The id of this player (used to identify Media object in JavaScript) - private MODE mode = MODE.NONE; // Playback or Recording mode - private STATE state = STATE.MEDIA_NONE; // State of recording or playback - - private String audioFile = null; // File name to play or record to - private float duration = -1; // Duration of audio - - private MediaRecorder recorder = null; // Audio recording object - private String tempFile = null; // Temporary recording file name - - private MediaPlayer player = null; // Audio player object - private boolean prepareOnly = true; // playback after file prepare flag - private int seekOnPrepared = 0; // seek to this location once media is prepared - - /** - * Constructor. - * - * @param handler The audio handler object - * @param id The id of this audio player - */ - public AudioPlayer(AudioHandler handler, String id, String file) { - this.handler = handler; - this.id = id; - this.audioFile = file; - this.recorder = new MediaRecorder(); - - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.3gp"; - } else { - this.tempFile = "/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/tmprecording.3gp"; - } - - } - - /** - * Destroy player and stop audio playing or recording. - */ - public void destroy() { - // Stop any play or record - if (this.player != null) { - if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) { - this.player.stop(); - this.setState(STATE.MEDIA_STOPPED); - } - this.player.release(); - this.player = null; - } - if (this.recorder != null) { - this.stopRecording(); - this.recorder.release(); - this.recorder = null; - } - } - - /** - * Start recording the specified file. - * - * @param file The name of the file - */ - public void startRecording(String file) { - switch (this.mode) { - case PLAY: - Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode."); - sendErrorStatus(MEDIA_ERR_ABORTED); - break; - case NONE: - this.audioFile = file; - this.recorder.setAudioSource(MediaRecorder.AudioSource.MIC); - this.recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // THREE_GPP); - this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //AMR_NB); - this.recorder.setOutputFile(this.tempFile); - try { - this.recorder.prepare(); - this.recorder.start(); - this.setState(STATE.MEDIA_RUNNING); - return; - } catch (IllegalStateException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - sendErrorStatus(MEDIA_ERR_ABORTED); - break; - case RECORD: - Log.d(LOG_TAG, "AudioPlayer Error: Already recording."); - sendErrorStatus(MEDIA_ERR_ABORTED); - } - } - - /** - * Save temporary recorded file to specified name - * - * @param file - */ - public void moveFile(String file) { - /* this is a hack to save the file as the specified name */ - File f = new File(this.tempFile); - - if (!file.startsWith("/")) { - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - file = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + file; - } else { - file = "/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/" + file; - } - } - - String logMsg = "renaming " + this.tempFile + " to " + file; - Log.d(LOG_TAG, logMsg); - if (!f.renameTo(new File(file))) Log.e(LOG_TAG, "FAILED " + logMsg); - } - - /** - * Stop recording and save to the file specified when recording started. - */ - public void stopRecording() { - if (this.recorder != null) { - try{ - if (this.state == STATE.MEDIA_RUNNING) { - this.recorder.stop(); - this.setState(STATE.MEDIA_STOPPED); - } - this.recorder.reset(); - this.moveFile(this.audioFile); - } - catch (Exception e) { - e.printStackTrace(); - } - } - } - - //========================================================================== - // Playback - //========================================================================== - - /** - * Start or resume playing audio file. - * - * @param file The name of the audio file. - */ - public void startPlaying(String file) { - if (this.readyPlayer(file) && this.player != null) { - this.player.start(); - this.setState(STATE.MEDIA_RUNNING); - this.seekOnPrepared = 0; //insures this is always reset - } else { - this.prepareOnly = false; - } - } - - /** - * Seek or jump to a new time in the track. - */ - public void seekToPlaying(int milliseconds) { - if (this.readyPlayer(this.audioFile)) { - this.player.seekTo(milliseconds); - Log.d(LOG_TAG, "Send a onStatus update for the new seek"); - sendStatusChange(MEDIA_POSITION, null, (milliseconds / 1000.0f)); - } - else { - this.seekOnPrepared = milliseconds; - } - } - - /** - * Pause playing. - */ - public void pausePlaying() { - - // If playing, then pause - if (this.state == STATE.MEDIA_RUNNING && this.player != null) { - this.player.pause(); - this.setState(STATE.MEDIA_PAUSED); - } - else { - Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: " + this.state.ordinal()); - sendErrorStatus(MEDIA_ERR_NONE_ACTIVE); - } - } - - /** - * Stop playing the audio file. - */ - public void stopPlaying() { - if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) { - this.player.pause(); - this.player.seekTo(0); - Log.d(LOG_TAG, "stopPlaying is calling stopped"); - this.setState(STATE.MEDIA_STOPPED); - } - else { - Log.d(LOG_TAG, "AudioPlayer Error: stopPlaying() called during invalid state: " + this.state.ordinal()); - sendErrorStatus(MEDIA_ERR_NONE_ACTIVE); - } - } - - /** - * Callback to be invoked when playback of a media source has completed. - * - * @param player The MediaPlayer that reached the end of the file - */ - public void onCompletion(MediaPlayer player) { - Log.d(LOG_TAG, "on completion is calling stopped"); - this.setState(STATE.MEDIA_STOPPED); - } - - /** - * Get current position of playback. - * - * @return position in msec or -1 if not playing - */ - public long getCurrentPosition() { - if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) { - int curPos = this.player.getCurrentPosition(); - sendStatusChange(MEDIA_POSITION, null, (curPos / 1000.0f)); - return curPos; - } - else { - return -1; - } - } - - /** - * Determine if playback file is streaming or local. - * It is streaming if file name starts with "http://" - * - * @param file The file name - * @return T=streaming, F=local - */ - public boolean isStreaming(String file) { - if (file.contains("http://") || file.contains("https://")) { - return true; - } - else { - return false; - } - } - - /** - * Get the duration of the audio file. - * - * @param file The name of the audio file. - * @return The duration in msec. - * -1=can't be determined - * -2=not allowed - */ - public float getDuration(String file) { - - // Can't get duration of recording - if (this.recorder != null) { - return (-2); // not allowed - } - - // If audio file already loaded and started, then return duration - if (this.player != null) { - return this.duration; - } - - // If no player yet, then create one - else { - this.prepareOnly = true; - this.startPlaying(file); - - // This will only return value for local, since streaming - // file hasn't been read yet. - return this.duration; - } - } - - /** - * Callback to be invoked when the media source is ready for playback. - * - * @param player The MediaPlayer that is ready for playback - */ - public void onPrepared(MediaPlayer player) { - // Listen for playback completion - this.player.setOnCompletionListener(this); - // seek to any location received while not prepared - this.seekToPlaying(this.seekOnPrepared); - // If start playing after prepared - if (!this.prepareOnly) { - this.player.start(); - this.setState(STATE.MEDIA_RUNNING); - this.seekOnPrepared = 0; //reset only when played - } else { - this.setState(STATE.MEDIA_STARTING); - } - // Save off duration - this.duration = getDurationInSeconds(); - // reset prepare only flag - this.prepareOnly = true; - - // Send status notification to JavaScript - sendStatusChange(MEDIA_DURATION, null, this.duration); - } - - /** - * By default Android returns the length of audio in mills but we want seconds - * - * @return length of clip in seconds - */ - private float getDurationInSeconds() { - return (this.player.getDuration() / 1000.0f); - } - - /** - * Callback to be invoked when there has been an error during an asynchronous operation - * (other errors will throw exceptions at method call time). - * - * @param player the MediaPlayer the error pertains to - * @param arg1 the type of error that has occurred: (MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED) - * @param arg2 an extra code, specific to the error. - */ - public boolean onError(MediaPlayer player, int arg1, int arg2) { - Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2 + ")"); - - // TODO: Not sure if this needs to be sent? - this.player.stop(); - this.player.release(); - - // Send error notification to JavaScript - sendErrorStatus(arg1); - return false; - } - - /** - * Set the state and send it to JavaScript. - * - * @param state - */ - private void setState(STATE state) { - if (this.state != state) { - sendStatusChange(MEDIA_STATE, null, (float)state.ordinal()); - } - this.state = state; - } - - /** - * Set the mode and send it to JavaScript. - * - * @param mode - */ - private void setMode(MODE mode) { - if (this.mode != mode) { - //mode is not part of the expected behavior, so no notification - //this.handler.webView.sendJavascript("cordova.require('org.apache.cordova.media.Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + mode + ");"); - } - this.mode = mode; - } - - /** - * Get the audio state. - * - * @return int - */ - public int getState() { - return this.state.ordinal(); - } - - /** - * Set the volume for audio player - * - * @param volume - */ - public void setVolume(float volume) { - this.player.setVolume(volume, volume); - } - - /** - * attempts to put the player in play mode - * @return true if in playmode, false otherwise - */ - private boolean playMode() { - switch(this.mode) { - case NONE: - this.setMode(MODE.PLAY); - break; - case PLAY: - break; - case RECORD: - Log.d(LOG_TAG, "AudioPlayer Error: Can't play in record mode."); - sendErrorStatus(MEDIA_ERR_ABORTED); - return false; //player is not ready - } - return true; - } - - /** - * attempts to initialize the media player for playback - * @param file the file to play - * @return false if player not ready, reports if in wrong mode or state - */ - private boolean readyPlayer(String file) { - if (playMode()) { - switch (this.state) { - case MEDIA_NONE: - if (this.player == null) { - this.player = new MediaPlayer(); - } - try { - this.loadAudioFile(file); - } catch (Exception e) { - sendErrorStatus(MEDIA_ERR_ABORTED); - } - return false; - case MEDIA_LOADING: - //cordova js is not aware of MEDIA_LOADING, so we send MEDIA_STARTING instead - Log.d(LOG_TAG, "AudioPlayer Loading: startPlaying() called during media preparation: " + STATE.MEDIA_STARTING.ordinal()); - this.prepareOnly = false; - return false; - case MEDIA_STARTING: - case MEDIA_RUNNING: - case MEDIA_PAUSED: - return true; - case MEDIA_STOPPED: - //if we are readying the same file - if (this.audioFile.compareTo(file) == 0) { - //reset the audio file - player.seekTo(0); - player.pause(); - return true; - } else { - //reset the player - this.player.reset(); - try { - this.loadAudioFile(file); - } catch (Exception e) { - sendErrorStatus(MEDIA_ERR_ABORTED); - } - //if we had to prepare the file, we won't be in the correct state for playback - return false; - } - default: - Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: " + this.state); - sendErrorStatus(MEDIA_ERR_ABORTED); - } - } - return false; - } - - /** - * load audio file - * @throws IOException - * @throws IllegalStateException - * @throws SecurityException - * @throws IllegalArgumentException - */ - private void loadAudioFile(String file) throws IllegalArgumentException, SecurityException, IllegalStateException, IOException { - if (this.isStreaming(file)) { - this.player.setDataSource(file); - this.player.setAudioStreamType(AudioManager.STREAM_MUSIC); - //if it's a streaming file, play mode is implied - this.setMode(MODE.PLAY); - this.setState(STATE.MEDIA_STARTING); - this.player.setOnPreparedListener(this); - this.player.prepareAsync(); - } - else { - if (file.startsWith("/android_asset/")) { - String f = file.substring(15); - android.content.res.AssetFileDescriptor fd = this.handler.cordova.getActivity().getAssets().openFd(f); - this.player.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength()); - } - else { - File fp = new File(file); - if (fp.exists()) { - FileInputStream fileInputStream = new FileInputStream(file); - this.player.setDataSource(fileInputStream.getFD()); - fileInputStream.close(); - } - else { - this.player.setDataSource(Environment.getExternalStorageDirectory().getPath() + "/" + file); - } - } - this.setState(STATE.MEDIA_STARTING); - this.player.setOnPreparedListener(this); - this.player.prepare(); - - // Get duration - this.duration = getDurationInSeconds(); - } - } - - private void sendErrorStatus(int errorCode) { - sendStatusChange(MEDIA_ERROR, errorCode, null); - } - - private void sendStatusChange(int messageType, Integer additionalCode, Float value) { - - if (additionalCode != null && value != null) { - throw new IllegalArgumentException("Only one of additionalCode or value can be specified, not both"); - } - - JSONObject statusDetails = new JSONObject(); - try { - statusDetails.put("id", this.id); - statusDetails.put("msgType", messageType); - if (additionalCode != null) { - JSONObject code = new JSONObject(); - code.put("code", additionalCode.intValue()); - statusDetails.put("value", code); - } - else if (value != null) { - statusDetails.put("value", value.floatValue()); - } - } catch (JSONException e) { - Log.e(LOG_TAG, "Failed to create status details", e); - } - - this.handler.sendEventMessage("status", statusDetails); - } -} diff --git a/plugins/org.apache.cordova.media/src/android/FileHelper.java b/plugins/org.apache.cordova.media/src/android/FileHelper.java deleted file mode 100644 index e20752c6..00000000 --- a/plugins/org.apache.cordova.media/src/android/FileHelper.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ -package org.apache.cordova.media; - -import android.net.Uri; - -public class FileHelper { - - /** - * Removes the "file://" prefix from the given URI string, if applicable. - * If the given URI string doesn't have a "file://" prefix, it is returned unchanged. - * - * @param uriString the URI string to operate on - * @return a path without the "file://" prefix - */ - public static String stripFileProtocol(String uriString) { - if (uriString.startsWith("file://")) { - return Uri.parse(uriString).getPath(); - } - return uriString; - } -} diff --git a/plugins/org.apache.cordova.media/src/blackberry10/index.js b/plugins/org.apache.cordova.media/src/blackberry10/index.js deleted file mode 100644 index 1b9b7860..00000000 --- a/plugins/org.apache.cordova.media/src/blackberry10/index.js +++ /dev/null @@ -1,237 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var audioObjects = {}, - mediaErrorsHandled = false; - -// There is a bug in the webplatform handling of media error -// dialogs prior to 10.2. This function needs to be run once -// on the webview which plays audio to prevent freezing. -function handleMediaErrors() { - var webview = qnx.webplatform.getWebViews()[0], - handler = webview.onDialogRequested; - if (!mediaErrorsHandled) { - webview.allowWebEvent("DialogRequested"); - webview.onDialogRequested = undefined; - webview.onDialogRequested = function (eventArgs) { - var parsedArgs = JSON.parse(eventArgs); - if (parsedArgs.dialogType === 'MediaError') { - return '{"setPreventDefault": true}'; - } - handler(eventArgs); - }; - mediaErrorsHandled = true; - } -} - -module.exports = { - - create: function (success, fail, args, env) { - var result = new PluginResult(args, env), - id; - - if (!args[0]) { - result.error("Media Object id was not sent in arguments"); - return; - } - - id = JSON.parse(decodeURIComponent(args[0])); - - if (!args[1]){ - audioObjects[id] = new Audio(); - } else { - audioObjects[id] = new Audio(JSON.parse(decodeURIComponent(args[1]))); - } - - handleMediaErrors(); - - result.ok(); - }, - - startPlayingAudio: function (success, fail, args, env) { - - var audio, - id, - result = new PluginResult(args, env); - - if (!args[0]) { - result.error("Media Object id was not sent in arguments"); - return; - } - - id = JSON.parse(decodeURIComponent(args[0])); - - audio = audioObjects[id]; - - if (!audio) { - result.error("Audio object has not been initialized"); - } else { - audio.play(); - result.ok(); - } - }, - - stopPlayingAudio: function (success, fail, args, env) { - - var audio, - id, - result = new PluginResult(args, env); - - if (!args[0]) { - result.error("Media Object id was not sent in arguments"); - return; - } - - id = JSON.parse(decodeURIComponent(args[0])); - - audio = audioObjects[id]; - - if (!audio) { - result.error("Audio Object has not been initialized"); - return; - } - - audio.pause(); - audio.currentTime = 0; - - result.ok(); - }, - - seekToAudio: function (success, fail, args, env) { - - var audio, - result = new PluginResult(args, env); - - if (!args[0]) { - result.error("Media Object id was not sent in arguments"); - return; - } - - audio = audioObjects[JSON.parse(decodeURIComponent(args[0]))]; - - if (!audio) { - result.error("Audio Object has not been initialized"); - } else if (!args[1]) { - result.error("Media seek time argument not found"); - } else { - try { - audio.currentTime = JSON.parse(decodeURIComponent(args[1])) / 1000; - result.ok(); - } catch (e) { - result.error("Error seeking audio: " + e); - } - } - }, - - pausePlayingAudio: function (success, fail, args, env) { - - var audio, - result = new PluginResult(args, env); - - if (!args[0]) { - result.error("Media Object id was not sent in arguments"); - return; - } - - audio = audioObjects[JSON.parse(decodeURIComponent(args[0]))]; - - if (!audio) { - result.error("Audio Object has not been initialized"); - return; - } - - audio.pause(); - }, - - getCurrentPositionAudio: function (success, fail, args, env) { - - var audio, - result = new PluginResult(args, env); - - if (!args[0]) { - result.error("Media Object id was not sent in arguments"); - return; - } - - audio = audioObjects[JSON.parse(decodeURIComponent(args[0]))]; - - if (!audio) { - result.error("Audio Object has not been initialized"); - return; - } - - result.ok(audio.currentTime); - }, - - getDuration: function (success, fail, args, env) { - - var audio, - result = new PluginResult(args, env); - - if (!args[0]) { - result.error("Media Object id was not sent in arguments"); - return; - } - - audio = audioObjects[JSON.parse(decodeURIComponent(args[0]))]; - - if (!audio) { - result.error("Audio Object has not been initialized"); - return; - } - - result.ok(audio.duration); - }, - - startRecordingAudio: function (success, fail, args, env) { - var result = new PluginResult(args, env); - result.error("Not supported"); - }, - - stopRecordingAudio: function (success, fail, args, env) { - var result = new PluginResult(args, env); - result.error("Not supported"); - }, - - release: function (success, fail, args, env) { - var audio, - id, - result = new PluginResult(args, env); - - if (!args[0]) { - result.error("Media Object id was not sent in arguments"); - return; - } - - id = JSON.parse(decodeURIComponent(args[0])); - - audio = audioObjects[id]; - - if (audio) { - if(audio.src !== ""){ - audio.src = undefined; - } - audioObjects[id] = undefined; - } - - result.ok(); - } -}; diff --git a/plugins/org.apache.cordova.media/src/ios/CDVSound.h b/plugins/org.apache.cordova.media/src/ios/CDVSound.h deleted file mode 100644 index 984924de..00000000 --- a/plugins/org.apache.cordova.media/src/ios/CDVSound.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import -#import -#import - -#import - -enum CDVMediaError { - MEDIA_ERR_ABORTED = 1, - MEDIA_ERR_NETWORK = 2, - MEDIA_ERR_DECODE = 3, - MEDIA_ERR_NONE_SUPPORTED = 4 -}; -typedef NSUInteger CDVMediaError; - -enum CDVMediaStates { - MEDIA_NONE = 0, - MEDIA_STARTING = 1, - MEDIA_RUNNING = 2, - MEDIA_PAUSED = 3, - MEDIA_STOPPED = 4 -}; -typedef NSUInteger CDVMediaStates; - -enum CDVMediaMsg { - MEDIA_STATE = 1, - MEDIA_DURATION = 2, - MEDIA_POSITION = 3, - MEDIA_ERROR = 9 -}; -typedef NSUInteger CDVMediaMsg; - -@interface CDVAudioPlayer : AVAudioPlayer -{ - NSString* mediaId; -} -@property (nonatomic, copy) NSString* mediaId; -@end - -@interface CDVAudioRecorder : AVAudioRecorder -{ - NSString* mediaId; -} -@property (nonatomic, copy) NSString* mediaId; -@end - -@interface CDVAudioFile : NSObject -{ - NSString* resourcePath; - NSURL* resourceURL; - CDVAudioPlayer* player; - CDVAudioRecorder* recorder; - NSNumber* volume; -} - -@property (nonatomic, strong) NSString* resourcePath; -@property (nonatomic, strong) NSURL* resourceURL; -@property (nonatomic, strong) CDVAudioPlayer* player; -@property (nonatomic, strong) NSNumber* volume; - -@property (nonatomic, strong) CDVAudioRecorder* recorder; - -@end - -@interface CDVSound : CDVPlugin -{ - NSMutableDictionary* soundCache; - AVAudioSession* avSession; -} -@property (nonatomic, strong) NSMutableDictionary* soundCache; -@property (nonatomic, strong) AVAudioSession* avSession; - -- (void)startPlayingAudio:(CDVInvokedUrlCommand*)command; -- (void)pausePlayingAudio:(CDVInvokedUrlCommand*)command; -- (void)stopPlayingAudio:(CDVInvokedUrlCommand*)command; -- (void)seekToAudio:(CDVInvokedUrlCommand*)command; -- (void)release:(CDVInvokedUrlCommand*)command; -- (void)getCurrentPositionAudio:(CDVInvokedUrlCommand*)command; - -- (BOOL)hasAudioSession; - -// helper methods -- (NSURL*)urlForRecording:(NSString*)resourcePath; -- (NSURL*)urlForPlaying:(NSString*)resourcePath; - -- (CDVAudioFile*)audioFileForResource:(NSString*)resourcePath withId:(NSString*)mediaId doValidation:(BOOL)bValidate forRecording:(BOOL)bRecord; -- (BOOL)prepareToPlay:(CDVAudioFile*)audioFile withId:(NSString*)mediaId; -- (NSString*)createMediaErrorWithCode:(CDVMediaError)code message:(NSString*)message; - -- (void)startRecordingAudio:(CDVInvokedUrlCommand*)command; -- (void)stopRecordingAudio:(CDVInvokedUrlCommand*)command; - -- (void)setVolume:(CDVInvokedUrlCommand*)command; - -@end diff --git a/plugins/org.apache.cordova.media/src/ios/CDVSound.m b/plugins/org.apache.cordova.media/src/ios/CDVSound.m deleted file mode 100644 index 309b2e29..00000000 --- a/plugins/org.apache.cordova.media/src/ios/CDVSound.m +++ /dev/null @@ -1,703 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import "CDVSound.h" -#import "CDVFile.h" -#import - -#define DOCUMENTS_SCHEME_PREFIX @"documents://" -#define HTTP_SCHEME_PREFIX @"http://" -#define HTTPS_SCHEME_PREFIX @"https://" -#define CDVFILE_PREFIX @"cdvfile://" -#define RECORDING_WAV @"wav" - -@implementation CDVSound - -@synthesize soundCache, avSession; - -// Maps a url for a resource path for recording -- (NSURL*)urlForRecording:(NSString*)resourcePath -{ - NSURL* resourceURL = nil; - NSString* filePath = nil; - NSString* docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; - - // first check for correct extension - if ([[resourcePath pathExtension] caseInsensitiveCompare:RECORDING_WAV] != NSOrderedSame) { - resourceURL = nil; - NSLog(@"Resource for recording must have %@ extension", RECORDING_WAV); - } else if ([resourcePath hasPrefix:DOCUMENTS_SCHEME_PREFIX]) { - // try to find Documents:// resources - filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/", docsPath]]; - NSLog(@"Will use resource '%@' from the documents folder with path = %@", resourcePath, filePath); - } else if ([resourcePath hasPrefix:CDVFILE_PREFIX]) { - CDVFile *filePlugin = [self.commandDelegate getCommandInstance:@"File"]; - CDVFilesystemURL *url = [CDVFilesystemURL fileSystemURLWithString:resourcePath]; - filePath = [filePlugin filesystemPathForURL:url]; - if (filePath == nil) { - resourceURL = [NSURL URLWithString:resourcePath]; - } - } else { - // if resourcePath is not from FileSystem put in tmp dir, else attempt to use provided resource path - NSString* tmpPath = [NSTemporaryDirectory()stringByStandardizingPath]; - BOOL isTmp = [resourcePath rangeOfString:tmpPath].location != NSNotFound; - BOOL isDoc = [resourcePath rangeOfString:docsPath].location != NSNotFound; - if (!isTmp && !isDoc) { - // put in temp dir - filePath = [NSString stringWithFormat:@"%@/%@", tmpPath, resourcePath]; - } else { - filePath = resourcePath; - } - } - - if (filePath != nil) { - // create resourceURL - resourceURL = [NSURL fileURLWithPath:filePath]; - } - return resourceURL; -} - -// Maps a url for a resource path for playing -// "Naked" resource paths are assumed to be from the www folder as its base -- (NSURL*)urlForPlaying:(NSString*)resourcePath -{ - NSURL* resourceURL = nil; - NSString* filePath = nil; - - // first try to find HTTP:// or Documents:// resources - - if ([resourcePath hasPrefix:HTTP_SCHEME_PREFIX] || [resourcePath hasPrefix:HTTPS_SCHEME_PREFIX]) { - // if it is a http url, use it - NSLog(@"Will use resource '%@' from the Internet.", resourcePath); - resourceURL = [NSURL URLWithString:resourcePath]; - } else if ([resourcePath hasPrefix:DOCUMENTS_SCHEME_PREFIX]) { - NSString* docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; - filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/", docsPath]]; - NSLog(@"Will use resource '%@' from the documents folder with path = %@", resourcePath, filePath); - } else if ([resourcePath hasPrefix:CDVFILE_PREFIX]) { - CDVFile *filePlugin = [self.commandDelegate getCommandInstance:@"File"]; - CDVFilesystemURL *url = [CDVFilesystemURL fileSystemURLWithString:resourcePath]; - filePath = [filePlugin filesystemPathForURL:url]; - if (filePath == nil) { - resourceURL = [NSURL URLWithString:resourcePath]; - } - } else { - // attempt to find file path in www directory or LocalFileSystem.TEMPORARY directory - filePath = [self.commandDelegate pathForResource:resourcePath]; - if (filePath == nil) { - // see if this exists in the documents/temp directory from a previous recording - NSString* testPath = [NSString stringWithFormat:@"%@/%@", [NSTemporaryDirectory()stringByStandardizingPath], resourcePath]; - if ([[NSFileManager defaultManager] fileExistsAtPath:testPath]) { - // inefficient as existence will be checked again below but only way to determine if file exists from previous recording - filePath = testPath; - NSLog(@"Will attempt to use file resource from LocalFileSystem.TEMPORARY directory"); - } else { - // attempt to use path provided - filePath = resourcePath; - NSLog(@"Will attempt to use file resource '%@'", filePath); - } - } else { - NSLog(@"Found resource '%@' in the web folder.", filePath); - } - } - // if the resourcePath resolved to a file path, check that file exists - if (filePath != nil) { - // create resourceURL - resourceURL = [NSURL fileURLWithPath:filePath]; - // try to access file - NSFileManager* fMgr = [NSFileManager defaultManager]; - if (![fMgr fileExistsAtPath:filePath]) { - resourceURL = nil; - NSLog(@"Unknown resource '%@'", resourcePath); - } - } - - return resourceURL; -} - -// Creates or gets the cached audio file resource object -- (CDVAudioFile*)audioFileForResource:(NSString*)resourcePath withId:(NSString*)mediaId doValidation:(BOOL)bValidate forRecording:(BOOL)bRecord -{ - BOOL bError = NO; - CDVMediaError errcode = MEDIA_ERR_NONE_SUPPORTED; - NSString* errMsg = @""; - NSString* jsString = nil; - CDVAudioFile* audioFile = nil; - NSURL* resourceURL = nil; - - if ([self soundCache] == nil) { - [self setSoundCache:[NSMutableDictionary dictionaryWithCapacity:1]]; - } else { - audioFile = [[self soundCache] objectForKey:mediaId]; - } - if (audioFile == nil) { - // validate resourcePath and create - if ((resourcePath == nil) || ![resourcePath isKindOfClass:[NSString class]] || [resourcePath isEqualToString:@""]) { - bError = YES; - errcode = MEDIA_ERR_ABORTED; - errMsg = @"invalid media src argument"; - } else { - audioFile = [[CDVAudioFile alloc] init]; - audioFile.resourcePath = resourcePath; - audioFile.resourceURL = nil; // validate resourceURL when actually play or record - [[self soundCache] setObject:audioFile forKey:mediaId]; - } - } - if (bValidate && (audioFile.resourceURL == nil)) { - if (bRecord) { - resourceURL = [self urlForRecording:resourcePath]; - } else { - resourceURL = [self urlForPlaying:resourcePath]; - } - if (resourceURL == nil) { - bError = YES; - errcode = MEDIA_ERR_ABORTED; - errMsg = [NSString stringWithFormat:@"Cannot use audio file from resource '%@'", resourcePath]; - } else { - audioFile.resourceURL = resourceURL; - } - } - - if (bError) { - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:errcode message:errMsg]]; - [self.commandDelegate evalJs:jsString]; - } - - return audioFile; -} - -// returns whether or not audioSession is available - creates it if necessary -- (BOOL)hasAudioSession -{ - BOOL bSession = YES; - - if (!self.avSession) { - NSError* error = nil; - - self.avSession = [AVAudioSession sharedInstance]; - if (error) { - // is not fatal if can't get AVAudioSession , just log the error - NSLog(@"error creating audio session: %@", [[error userInfo] description]); - self.avSession = nil; - bSession = NO; - } - } - return bSession; -} - -// helper function to create a error object string -- (NSString*)createMediaErrorWithCode:(CDVMediaError)code message:(NSString*)message -{ - NSMutableDictionary* errorDict = [NSMutableDictionary dictionaryWithCapacity:2]; - - [errorDict setObject:[NSNumber numberWithUnsignedInteger:code] forKey:@"code"]; - [errorDict setObject:message ? message:@"" forKey:@"message"]; - - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:errorDict options:0 error:nil]; - return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; -} - -- (void)create:(CDVInvokedUrlCommand*)command -{ - NSString* mediaId = [command argumentAtIndex:0]; - NSString* resourcePath = [command argumentAtIndex:1]; - - CDVAudioFile* audioFile = [self audioFileForResource:resourcePath withId:mediaId doValidation:NO forRecording:NO]; - - if (audioFile == nil) { - NSString* errorMessage = [NSString stringWithFormat:@"Failed to initialize Media file with path %@", resourcePath]; - NSString* jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_ABORTED message:errorMessage]]; - [self.commandDelegate evalJs:jsString]; - } else { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - } -} - -- (void)setVolume:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - -#pragma unused(callbackId) - NSString* mediaId = [command argumentAtIndex:0]; - NSNumber* volume = [command argumentAtIndex:1 withDefault:[NSNumber numberWithFloat:1.0]]; - - if ([self soundCache] != nil) { - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - if (audioFile != nil) { - audioFile.volume = volume; - if (audioFile.player) { - audioFile.player.volume = [volume floatValue]; - } - [[self soundCache] setObject:audioFile forKey:mediaId]; - } - } - - // don't care for any callbacks -} - -- (void)startPlayingAudio:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - -#pragma unused(callbackId) - NSString* mediaId = [command argumentAtIndex:0]; - NSString* resourcePath = [command argumentAtIndex:1]; - NSDictionary* options = [command argumentAtIndex:2 withDefault:nil]; - - BOOL bError = NO; - NSString* jsString = nil; - - CDVAudioFile* audioFile = [self audioFileForResource:resourcePath withId:mediaId doValidation:YES forRecording:NO]; - if ((audioFile != nil) && (audioFile.resourceURL != nil)) { - if (audioFile.player == nil) { - bError = [self prepareToPlay:audioFile withId:mediaId]; - } - if (!bError) { - // audioFile.player != nil or player was successfully created - // get the audioSession and set the category to allow Playing when device is locked or ring/silent switch engaged - if ([self hasAudioSession]) { - NSError* __autoreleasing err = nil; - NSNumber* playAudioWhenScreenIsLocked = [options objectForKey:@"playAudioWhenScreenIsLocked"]; - BOOL bPlayAudioWhenScreenIsLocked = YES; - if (playAudioWhenScreenIsLocked != nil) { - bPlayAudioWhenScreenIsLocked = [playAudioWhenScreenIsLocked boolValue]; - } - - NSString* sessionCategory = bPlayAudioWhenScreenIsLocked ? AVAudioSessionCategoryPlayback : AVAudioSessionCategorySoloAmbient; - [self.avSession setCategory:sessionCategory error:&err]; - if (![self.avSession setActive:YES error:&err]) { - // other audio with higher priority that does not allow mixing could cause this to fail - NSLog(@"Unable to play audio: %@", [err localizedFailureReason]); - bError = YES; - } - } - if (!bError) { - NSLog(@"Playing audio sample '%@'", audioFile.resourcePath); - NSNumber* loopOption = [options objectForKey:@"numberOfLoops"]; - NSInteger numberOfLoops = 0; - if (loopOption != nil) { - numberOfLoops = [loopOption intValue] - 1; - } - audioFile.player.numberOfLoops = numberOfLoops; - if (audioFile.player.isPlaying) { - [audioFile.player stop]; - audioFile.player.currentTime = 0; - } - if (audioFile.volume != nil) { - audioFile.player.volume = [audioFile.volume floatValue]; - } - - [audioFile.player play]; - double position = round(audioFile.player.duration * 1000) / 1000; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%.3f);\n%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_DURATION, position, @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_STATE, MEDIA_RUNNING]; - [self.commandDelegate evalJs:jsString]; - } - } - if (bError) { - /* I don't see a problem playing previously recorded audio so removing this section - BG - NSError* error; - // try loading it one more time, in case the file was recorded previously - audioFile.player = [[ AVAudioPlayer alloc ] initWithContentsOfURL:audioFile.resourceURL error:&error]; - if (error != nil) { - NSLog(@"Failed to initialize AVAudioPlayer: %@\n", error); - audioFile.player = nil; - } else { - NSLog(@"Playing audio sample '%@'", audioFile.resourcePath); - audioFile.player.numberOfLoops = numberOfLoops; - [audioFile.player play]; - } */ - // error creating the session or player - // jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_NONE_SUPPORTED]; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_NONE_SUPPORTED message:nil]]; - [self.commandDelegate evalJs:jsString]; - } - } - // else audioFile was nil - error already returned from audioFile for resource - return; -} - -- (BOOL)prepareToPlay:(CDVAudioFile*)audioFile withId:(NSString*)mediaId -{ - BOOL bError = NO; - NSError* __autoreleasing playerError = nil; - - // create the player - NSURL* resourceURL = audioFile.resourceURL; - - if ([resourceURL isFileURL]) { - audioFile.player = [[CDVAudioPlayer alloc] initWithContentsOfURL:resourceURL error:&playerError]; - } else { - NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:resourceURL]; - NSString* userAgent = [self.commandDelegate userAgent]; - if (userAgent) { - [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; - } - - NSURLResponse* __autoreleasing response = nil; - NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&playerError]; - if (playerError) { - NSLog(@"Unable to download audio from: %@", [resourceURL absoluteString]); - } else { - // bug in AVAudioPlayer when playing downloaded data in NSData - we have to download the file and play from disk - CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault); - CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidRef); - NSString* filePath = [NSString stringWithFormat:@"%@/%@", [NSTemporaryDirectory()stringByStandardizingPath], uuidString]; - CFRelease(uuidString); - CFRelease(uuidRef); - - [data writeToFile:filePath atomically:YES]; - NSURL* fileURL = [NSURL fileURLWithPath:filePath]; - audioFile.player = [[CDVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&playerError]; - } - } - - if (playerError != nil) { - NSLog(@"Failed to initialize AVAudioPlayer: %@\n", [playerError localizedDescription]); - audioFile.player = nil; - if (self.avSession) { - [self.avSession setActive:NO error:nil]; - } - bError = YES; - } else { - audioFile.player.mediaId = mediaId; - audioFile.player.delegate = self; - bError = ![audioFile.player prepareToPlay]; - } - return bError; -} - -- (void)stopPlayingAudio:(CDVInvokedUrlCommand*)command -{ - NSString* mediaId = [command argumentAtIndex:0]; - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - NSString* jsString = nil; - - if ((audioFile != nil) && (audioFile.player != nil)) { - NSLog(@"Stopped playing audio sample '%@'", audioFile.resourcePath); - [audioFile.player stop]; - audioFile.player.currentTime = 0; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_STATE, MEDIA_STOPPED]; - } // ignore if no media playing - if (jsString) { - [self.commandDelegate evalJs:jsString]; - } -} - -- (void)pausePlayingAudio:(CDVInvokedUrlCommand*)command -{ - NSString* mediaId = [command argumentAtIndex:0]; - NSString* jsString = nil; - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - - if ((audioFile != nil) && (audioFile.player != nil)) { - NSLog(@"Paused playing audio sample '%@'", audioFile.resourcePath); - [audioFile.player pause]; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_STATE, MEDIA_PAUSED]; - } - // ignore if no media playing - - if (jsString) { - [self.commandDelegate evalJs:jsString]; - } -} - -- (void)seekToAudio:(CDVInvokedUrlCommand*)command -{ - // args: - // 0 = Media id - // 1 = path to resource - // 2 = seek to location in milliseconds - - NSString* mediaId = [command argumentAtIndex:0]; - - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - double position = [[command argumentAtIndex:1] doubleValue]; - - if ((audioFile != nil) && (audioFile.player != nil)) { - NSString* jsString; - double posInSeconds = position / 1000; - if (posInSeconds >= audioFile.player.duration) { - // The seek is past the end of file. Stop media and reset to beginning instead of seeking past the end. - [audioFile.player stop]; - audioFile.player.currentTime = 0; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%.3f);\n%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_POSITION, 0.0, @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_STATE, MEDIA_STOPPED]; - // NSLog(@"seekToEndJsString=%@",jsString); - } else { - audioFile.player.currentTime = posInSeconds; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%f);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_POSITION, posInSeconds]; - // NSLog(@"seekJsString=%@",jsString); - } - - [self.commandDelegate evalJs:jsString]; - } -} - -- (void)release:(CDVInvokedUrlCommand*)command -{ - NSString* mediaId = [command argumentAtIndex:0]; - - if (mediaId != nil) { - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - if (audioFile != nil) { - if (audioFile.player && [audioFile.player isPlaying]) { - [audioFile.player stop]; - } - if (audioFile.recorder && [audioFile.recorder isRecording]) { - [audioFile.recorder stop]; - } - if (self.avSession) { - [self.avSession setActive:NO error:nil]; - self.avSession = nil; - } - [[self soundCache] removeObjectForKey:mediaId]; - NSLog(@"Media with id %@ released", mediaId); - } - } -} - -- (void)getCurrentPositionAudio:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSString* mediaId = [command argumentAtIndex:0]; - -#pragma unused(mediaId) - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - double position = -1; - - if ((audioFile != nil) && (audioFile.player != nil) && [audioFile.player isPlaying]) { - position = round(audioFile.player.currentTime * 1000) / 1000; - } - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:position]; - - NSString* jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%.3f);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_POSITION, position]; - [self.commandDelegate evalJs:jsString]; - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; -} - -- (void)startRecordingAudio:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - -#pragma unused(callbackId) - - NSString* mediaId = [command argumentAtIndex:0]; - CDVAudioFile* audioFile = [self audioFileForResource:[command argumentAtIndex:1] withId:mediaId doValidation:YES forRecording:YES]; - __block NSString* jsString = nil; - __block NSString* errorMsg = @""; - - if ((audioFile != nil) && (audioFile.resourceURL != nil)) { - void (^startRecording)(void) = ^{ - NSError* __autoreleasing error = nil; - - if (audioFile.recorder != nil) { - [audioFile.recorder stop]; - audioFile.recorder = nil; - } - // get the audioSession and set the category to allow recording when device is locked or ring/silent switch engaged - if ([self hasAudioSession]) { - if (![self.avSession.category isEqualToString:AVAudioSessionCategoryPlayAndRecord]) { - [self.avSession setCategory:AVAudioSessionCategoryRecord error:nil]; - } - - if (![self.avSession setActive:YES error:&error]) { - // other audio with higher priority that does not allow mixing could cause this to fail - errorMsg = [NSString stringWithFormat:@"Unable to record audio: %@", [error localizedFailureReason]]; - // jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_ABORTED]; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_ABORTED message:errorMsg]]; - [self.commandDelegate evalJs:jsString]; - return; - } - } - - // create a new recorder for each start record - audioFile.recorder = [[CDVAudioRecorder alloc] initWithURL:audioFile.resourceURL settings:nil error:&error]; - - bool recordingSuccess = NO; - if (error == nil) { - audioFile.recorder.delegate = self; - audioFile.recorder.mediaId = mediaId; - recordingSuccess = [audioFile.recorder record]; - if (recordingSuccess) { - NSLog(@"Started recording audio sample '%@'", audioFile.resourcePath); - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_STATE, MEDIA_RUNNING]; - [self.commandDelegate evalJs:jsString]; - } - } - - if ((error != nil) || (recordingSuccess == NO)) { - if (error != nil) { - errorMsg = [NSString stringWithFormat:@"Failed to initialize AVAudioRecorder: %@\n", [error localizedFailureReason]]; - } else { - errorMsg = @"Failed to start recording using AVAudioRecorder"; - } - audioFile.recorder = nil; - if (self.avSession) { - [self.avSession setActive:NO error:nil]; - } - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_ABORTED message:errorMsg]]; - [self.commandDelegate evalJs:jsString]; - } - }; - - SEL rrpSel = NSSelectorFromString(@"requestRecordPermission:"); - if ([self hasAudioSession] && [self.avSession respondsToSelector:rrpSel]) - { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - [self.avSession performSelector:rrpSel withObject:^(BOOL granted){ - if (granted) { - startRecording(); - } else { - NSString* msg = @"Error creating audio session, microphone permission denied."; - NSLog(@"%@", msg); - audioFile.recorder = nil; - if (self.avSession) { - [self.avSession setActive:NO error:nil]; - } - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_ABORTED message:msg]]; - [self.commandDelegate evalJs:jsString]; - } - }]; -#pragma clang diagnostic pop - } else { - startRecording(); - } - - } else { - // file did not validate - NSString* errorMsg = [NSString stringWithFormat:@"Could not record audio at '%@'", audioFile.resourcePath]; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_ABORTED message:errorMsg]]; - [self.commandDelegate evalJs:jsString]; - } -} - -- (void)stopRecordingAudio:(CDVInvokedUrlCommand*)command -{ - NSString* mediaId = [command argumentAtIndex:0]; - - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - NSString* jsString = nil; - - if ((audioFile != nil) && (audioFile.recorder != nil)) { - NSLog(@"Stopped recording audio sample '%@'", audioFile.resourcePath); - [audioFile.recorder stop]; - // no callback - that will happen in audioRecorderDidFinishRecording - } - // ignore if no media recording - if (jsString) { - [self.commandDelegate evalJs:jsString]; - } -} - -- (void)audioRecorderDidFinishRecording:(AVAudioRecorder*)recorder successfully:(BOOL)flag -{ - CDVAudioRecorder* aRecorder = (CDVAudioRecorder*)recorder; - NSString* mediaId = aRecorder.mediaId; - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - NSString* jsString = nil; - - if (audioFile != nil) { - NSLog(@"Finished recording audio sample '%@'", audioFile.resourcePath); - } - if (flag) { - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_STATE, MEDIA_STOPPED]; - } else { - // jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_DECODE]; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_DECODE message:nil]]; - } - if (self.avSession) { - [self.avSession setActive:NO error:nil]; - } - [self.commandDelegate evalJs:jsString]; -} - -- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer*)player successfully:(BOOL)flag -{ - CDVAudioPlayer* aPlayer = (CDVAudioPlayer*)player; - NSString* mediaId = aPlayer.mediaId; - CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId]; - NSString* jsString = nil; - - if (audioFile != nil) { - NSLog(@"Finished playing audio sample '%@'", audioFile.resourcePath); - } - if (flag) { - audioFile.player.currentTime = 0; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_STATE, MEDIA_STOPPED]; - } else { - // jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_DECODE]; - jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('org.apache.cordova.media.Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_DECODE message:nil]]; - } - if (self.avSession) { - [self.avSession setActive:NO error:nil]; - } - [self.commandDelegate evalJs:jsString]; -} - -- (void)onMemoryWarning -{ - [[self soundCache] removeAllObjects]; - [self setSoundCache:nil]; - [self setAvSession:nil]; - - [super onMemoryWarning]; -} - -- (void)dealloc -{ - [[self soundCache] removeAllObjects]; -} - -- (void)onReset -{ - for (CDVAudioFile* audioFile in [[self soundCache] allValues]) { - if (audioFile != nil) { - if (audioFile.player != nil) { - [audioFile.player stop]; - audioFile.player.currentTime = 0; - } - if (audioFile.recorder != nil) { - [audioFile.recorder stop]; - } - } - } - - [[self soundCache] removeAllObjects]; -} - -@end - -@implementation CDVAudioFile - -@synthesize resourcePath; -@synthesize resourceURL; -@synthesize player, volume; -@synthesize recorder; - -@end -@implementation CDVAudioPlayer -@synthesize mediaId; - -@end - -@implementation CDVAudioRecorder -@synthesize mediaId; - -@end diff --git a/plugins/org.apache.cordova.media/src/tizen/MediaProxy.js b/plugins/org.apache.cordova.media/src/tizen/MediaProxy.js deleted file mode 100644 index c2ee4b07..00000000 --- a/plugins/org.apache.cordova.media/src/tizen/MediaProxy.js +++ /dev/null @@ -1,223 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var cordova = require('cordova'), - Media = require('org.apache.cordova.media.Media'); - -var MediaError = require('org.apache.cordova.media.MediaError'), - audioObjects = {}; - -module.exports = { - // Initiates the audio file - create:function(successCallback, errorCallback, args) { - var id = args[0], src = args[1]; - - console.log("media::create() - id =" + id + ", src =" + src); - - audioObjects[id] = new Audio(src); - - audioObjects[id].onStalledCB = function () { - console.log("media::onStalled()"); - - audioObjects[id].timer = window.setTimeout( - function () { - audioObjects[id].pause(); - - if (audioObjects[id].currentTime !== 0) - audioObjects[id].currentTime = 0; - - console.log("media::onStalled() - MEDIA_ERROR -> " + MediaError.MEDIA_ERR_ABORTED); - - var err = new MediaError(MediaError.MEDIA_ERR_ABORTED, "Stalled"); - - Media.onStatus(id, Media.MEDIA_ERROR, err); - }, - 2000); - }; - - audioObjects[id].onEndedCB = function () { - console.log("media::onEndedCB() - MEDIA_STATE -> MEDIA_STOPPED"); - - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_STOPPED); - }; - - audioObjects[id].onErrorCB = function () { - console.log("media::onErrorCB() - MEDIA_ERROR -> " + event.srcElement.error); - - Media.onStatus(id, Media.MEDIA_ERROR, event.srcElement.error); - }; - - audioObjects[id].onPlayCB = function () { - console.log("media::onPlayCB() - MEDIA_STATE -> MEDIA_STARTING"); - - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_STARTING); - }; - - audioObjects[id].onPlayingCB = function () { - console.log("media::onPlayingCB() - MEDIA_STATE -> MEDIA_RUNNING"); - - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_RUNNING); - }; - - audioObjects[id].onDurationChangeCB = function () { - console.log("media::onDurationChangeCB() - MEDIA_DURATION -> " + audioObjects[id].duration); - - Media.onStatus(id, Media.MEDIA_DURATION, audioObjects[id].duration); - }; - - audioObjects[id].onTimeUpdateCB = function () { - console.log("media::onTimeUpdateCB() - MEDIA_POSITION -> " + audioObjects[id].currentTime); - - Media.onStatus(id, Media.MEDIA_POSITION, audioObjects[id].currentTime); - }; - - audioObjects[id].onCanPlayCB = function () { - console.log("media::onCanPlayCB()"); - - window.clearTimeout(audioObjects[id].timer); - - audioObjects[id].play(); - }; - - }, - - // Start playing the audio - startPlayingAudio:function(successCallback, errorCallback, args) { - var id = args[0], src = args[1], options = args[2]; - - console.log("media::startPlayingAudio() - id =" + id + ", src =" + src + ", options =" + options); - - audioObjects[id].addEventListener('canplay', audioObjects[id].onCanPlayCB); - audioObjects[id].addEventListener('ended', audioObjects[id].onEndedCB); - audioObjects[id].addEventListener('timeupdate', audioObjects[id].onTimeUpdateCB); - audioObjects[id].addEventListener('durationchange', audioObjects[id].onDurationChangeCB); - audioObjects[id].addEventListener('playing', audioObjects[id].onPlayingCB); - audioObjects[id].addEventListener('play', audioObjects[id].onPlayCB); - audioObjects[id].addEventListener('error', audioObjects[id].onErrorCB); - audioObjects[id].addEventListener('stalled', audioObjects[id].onStalledCB); - - audioObjects[id].play(); - }, - - // Stops the playing audio - stopPlayingAudio:function(successCallback, errorCallback, args) { - var id = args[0]; - - window.clearTimeout(audioObjects[id].timer); - - audioObjects[id].pause(); - - if (audioObjects[id].currentTime !== 0) - audioObjects[id].currentTime = 0; - - console.log("media::stopPlayingAudio() - MEDIA_STATE -> MEDIA_STOPPED"); - - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_STOPPED); - - audioObjects[id].removeEventListener('canplay', audioObjects[id].onCanPlayCB); - audioObjects[id].removeEventListener('ended', audioObjects[id].onEndedCB); - audioObjects[id].removeEventListener('timeupdate', audioObjects[id].onTimeUpdateCB); - audioObjects[id].removeEventListener('durationchange', audioObjects[id].onDurationChangeCB); - audioObjects[id].removeEventListener('playing', audioObjects[id].onPlayingCB); - audioObjects[id].removeEventListener('play', audioObjects[id].onPlayCB); - audioObjects[id].removeEventListener('error', audioObjects[id].onErrorCB); - audioObjects[id].removeEventListener('error', audioObjects[id].onStalledCB); - }, - - // Seeks to the position in the audio - seekToAudio:function(successCallback, errorCallback, args) { - var id = args[0], milliseconds = args[1]; - - console.log("media::seekToAudio()"); - - audioObjects[id].currentTime = milliseconds; - successCallback( audioObjects[id].currentTime); - }, - - // Pauses the playing audio - pausePlayingAudio:function(successCallback, errorCallback, args) { - var id = args[0]; - - console.log("media::pausePlayingAudio() - MEDIA_STATE -> MEDIA_PAUSED"); - - audioObjects[id].pause(); - - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_PAUSED); - }, - - // Gets current position in the audio - getCurrentPositionAudio:function(successCallback, errorCallback, args) { - var id = args[0]; - console.log("media::getCurrentPositionAudio()"); - successCallback(audioObjects[id].currentTime); - }, - - // Start recording audio - startRecordingAudio:function(successCallback, errorCallback, args) { - var id = args[0], src = args[1]; - - console.log("media::startRecordingAudio() - id =" + id + ", src =" + src); - - function gotStreamCB(stream) { - audioObjects[id].src = webkitURL.createObjectURL(stream); - console.log("media::startRecordingAudio() - stream CB"); - } - - function gotStreamFailedCB(error) { - console.log("media::startRecordingAudio() - error CB:" + error.toString()); - } - - if (navigator.webkitGetUserMedia) { - audioObjects[id] = new Audio(); - navigator.webkitGetUserMedia('audio', gotStreamCB, gotStreamFailedCB); - } else { - console.log("webkitGetUserMedia not supported"); - } - successCallback(); - }, - - // Stop recording audio - stopRecordingAudio:function(successCallback, errorCallback, args) { - var id = args[0]; - - console.log("media::stopRecordingAudio() - id =" + id); - - audioObjects[id].pause(); - successCallback(); - }, - - // Release the media object - release:function(successCallback, errorCallback, args) { - var id = args[0]; - window.clearTimeout(audioObjects[id].timer); - console.log("media::release()"); - }, - - setVolume:function(successCallback, errorCallback, args) { - var id = args[0], volume = args[1]; - - console.log("media::setVolume()"); - - audioObjects[id].volume = volume; - } -}; - -require("cordova/tizen/commandProxy").add("Media", module.exports); diff --git a/plugins/org.apache.cordova.media/src/ubuntu/media.cpp b/plugins/org.apache.cordova.media/src/ubuntu/media.cpp deleted file mode 100644 index 2814b5b3..00000000 --- a/plugins/org.apache.cordova.media/src/ubuntu/media.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -#include "media.h" - -void Media::create(int scId, int ecId, const QString &id, const QString &src) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - - if (_id2Player.find(id) != _id2Player.end()) { - _id2Player[id]->stop(); - _id2Player.remove(id); - } - - _id2Player[id] = QSharedPointer(new Player(id, src, this)); -} - -void Media::relase(int scId, int ecId, const QString &id) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - - if (_id2Player.find(id) == _id2Player.end()) - return; - _id2Player.remove(id); -} - -void Media::startPlayingAudio(int scId, int ecId, const QString &id, const QString &src, QVariantMap options) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - Q_UNUSED(src); - Q_UNUSED(options); - - if (_id2Player.find(id) == _id2Player.end()) - return; - QSharedPointer player = _id2Player[id]; - player->play(); -} - -void Media::pausePlayingAudio(int scId, int ecId, const QString &id) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - - if (_id2Player.find(id) == _id2Player.end()) - return; - QSharedPointer player = _id2Player[id]; - player->pause(); -} - -void Media::stopPlayingAudio(int scId, int ecId, const QString &id) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - - if (_id2Player.find(id) == _id2Player.end()) - return; - QSharedPointer player = _id2Player[id]; - player->stop(); -} - -void Media::startRecordingAudio(int scId, int ecId, const QString &id, const QString &src) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - Q_UNUSED(src); - - if (_id2Player.find(id) == _id2Player.end()) - return; - QSharedPointer player = _id2Player[id]; - player->startRecording(); -} - -void Media::stopRecordingAudio(int scId, int ecId, const QString &id) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - - if (_id2Player.find(id) == _id2Player.end()) - return; - QSharedPointer player = _id2Player[id]; - player->stopRecording(); -} - -void Media::getCurrentPositionAudio(int scId, int ecId, const QString &id) { - Q_UNUSED(ecId); - - if (_id2Player.find(id) == _id2Player.end()) - return; - - QSharedPointer player = _id2Player[id]; - double position = player->getPosition(); - this->cb(scId, position); -} - -void Media::seekToAudio(int scId, int ecId, const QString &id, qint64 position) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - - if (_id2Player.find(id) == _id2Player.end()) - return; - - QSharedPointer player = _id2Player[id]; - player->seekTo(position); -} - -void Media::setVolume(int scId, int ecId, const QString &id, int volume) { - Q_UNUSED(scId); - Q_UNUSED(ecId); - - if (_id2Player.find(id) == _id2Player.end()) - return; - QSharedPointer player = _id2Player[id]; - player->setVolume(volume); -} diff --git a/plugins/org.apache.cordova.media/src/ubuntu/media.h b/plugins/org.apache.cordova.media/src/ubuntu/media.h deleted file mode 100644 index c1f37122..00000000 --- a/plugins/org.apache.cordova.media/src/ubuntu/media.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -#ifndef MEDIA_H_789768978 -#define MEDIA_H_789768978 - -#include -#include -#include -#include - -#include -#include - -class Player; - -class Media: public CPlugin { - Q_OBJECT -public: - explicit Media(Cordova *cordova): CPlugin(cordova) { - } - - virtual const QString fullName() override { - return Media::fullID(); - } - - virtual const QString shortName() override { - return "Media"; - } - - static const QString fullID() { - return "Media"; - } - - enum State { - MEDIA_NONE = 0, - MEDIA_STARTING = 1, - MEDIA_RUNNING = 2, - MEDIA_PAUSED = 3, - MEDIA_STOPPED = 4 - }; - enum ErrorCode { - MEDIA_ERR_NONE_ACTIVE = 0, - MEDIA_ERR_ABORTED = 1, - MEDIA_ERR_NETWORK = 2, - MEDIA_ERR_DECODE = 3, - MEDIA_ERR_NONE_SUPPORTED = 4 - }; - - void execJS(const QString &js) { - m_cordova->execJS(js); - } -public slots: - void create(int scId, int ecId, const QString &id, const QString &src); - void relase(int scId, int ecId, const QString &id); - - void startRecordingAudio(int scId, int ecId, const QString &id, const QString &src); - void stopRecordingAudio(int scId, int ecId, const QString &id); - - void startPlayingAudio(int scId, int ecId, const QString &id, const QString &src, QVariantMap options); - void pausePlayingAudio(int scId, int ecId, const QString &id); - void stopPlayingAudio(int scId, int ecId, const QString &id); - void getCurrentPositionAudio(int scId, int ecId, const QString &id); - void seekToAudio(int scId, int ecId, const QString &id, qint64 position); - void setVolume(int scId, int ecId, const QString &id, int volume); - -private: - QMap > _id2Player; -}; - -class Player: public QObject { - Q_OBJECT -public: - Player(const QString &id, QString src, Media *plugin): - _state(Media::MEDIA_NONE), - _src(src), - _mode(MODE_NONE), - _plugin(plugin), - _id(id), - _stateChanged(false) { - QUrl url(src, QUrl::TolerantMode); - - if (url.scheme().isEmpty()) { - QAudioEncoderSettings audioSettings; - - _recorder.setEncodingSettings(audioSettings); - _recorder.setOutputLocation(QFileInfo(src).absoluteFilePath()); - - _player.setMedia(QUrl::fromLocalFile(QFileInfo(src).absoluteFilePath())); - } else { - _player.setMedia(url); - } - QObject::connect(&_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(onMediaStatusChanged(QMediaPlayer::MediaStatus))); - QObject::connect(&_recorder, SIGNAL(error(QMediaRecorder::Error)), this, SLOT(onError(QMediaRecorder::Error))); - - connect(&_timer, SIGNAL(timeout()), this, SLOT(reportPosition())); - } - - void startRecording() { - if (recordMode() && _state != Media::MEDIA_RUNNING) { - _recorder.record(); - setState(Media::MEDIA_RUNNING); - } - } - void stopRecording() { - if (recordMode() && _state == Media::MEDIA_RUNNING) { - _recorder.stop(); - setState(Media::MEDIA_STOPPED); - } - } - - void setVolume(int volume) { - _player.setVolume(volume); - } - - void play() { - if (playMode() && _state != Media::MEDIA_RUNNING) { - _player.play(); - setState(Media::MEDIA_RUNNING); - } - } - void pause() { - if (playMode() && _state == Media::MEDIA_RUNNING) { - _player.pause(); - setState(Media::MEDIA_PAUSED); - } - } - void stop() { - if (playMode() && (_state == Media::MEDIA_RUNNING || _state == Media::MEDIA_PAUSED)) { - _player.stop(); - setState(Media::MEDIA_STOPPED); - } - } - double getDuration() { - if (_mode == MODE_NONE || _player.duration() == -1) - return -1; - if (_mode != MODE_PLAY) - return -2; - return static_cast(_player.duration()) / 1000.0; - } - double getPosition() { - if (_mode != MODE_PLAY) - return -1; - return static_cast(_player.position()) / 1000.0; - } - bool seekTo(qint64 position) { - if (!_player.isSeekable()) - return false; - _player.setPosition(position * 1000); - return true; - } -private slots: - void reportPosition() { - double position = getPosition(); - _plugin->execJS(QString("Media.onStatus('%1', Media.MEDIA_POSITION, %2)") - .arg(_id).arg(position)); - double duration = getDuration(); - _plugin->execJS(QString("Media.onStatus('%1', Media.MEDIA_DURATION, %2)") - .arg(_id).arg(duration)); - - if (_stateChanged && !(_state == Media::MEDIA_RUNNING && (duration == -1 || position == 0))) { - qCritical() << _id << "POSITION" << position << ":" << duration; - _stateChanged = false; - _plugin->execJS(QString("Media.onStatus('%1', Media.MEDIA_STATE, %2)").arg(_id).arg(_state)); - } - } - - void onMediaStatusChanged(QMediaPlayer::MediaStatus status) { - if (status == QMediaPlayer::InvalidMedia) { - reportError(Media::MEDIA_ERR_ABORTED, "AudioPlayer Error: The current media cannot be played."); - setState(Media::MEDIA_STOPPED); - } - if (status == QMediaPlayer::EndOfMedia) { - setState(Media::MEDIA_STOPPED); - seekTo(0); - } - } - void onError(QMediaRecorder::Error) { - reportError(Media::MEDIA_ERR_NONE_SUPPORTED, "AudioPlayer Error: Device is not ready or not available."); - setState(Media::MEDIA_STOPPED); - } - -private: - void reportError(int code, const QString &descr) { - Q_UNUSED(descr); - _plugin->execJS(QString("Media.onStatus('%1', Media.MEDIA_ERROR, {code: %2})") - .arg(_id).arg(code)); - } - - bool playMode() { - switch (_mode) { - case Player::MODE_NONE: - _mode = MODE_PLAY; - break; - case Player::MODE_PLAY: - break; - case Player::MODE_RECORD: - reportError(Media::MEDIA_ERR_NONE_SUPPORTED, "AudioPlayer Error: Can't play in record mode."); - return false; - break; - } - return true; - } - - bool recordMode() { - switch (_mode) { - case Player::MODE_NONE: - if (_recorder.outputLocation().isEmpty()) { - reportError(Media::MEDIA_ERR_NONE_SUPPORTED, "AudioPlayer Error: unsupported output location."); - return false; - } - _mode = MODE_RECORD; - break; - case Player::MODE_PLAY: - reportError(Media::MEDIA_ERR_NONE_SUPPORTED, "AudioPlayer Error: Can't play in play mode."); - return false; - break; - case Player::MODE_RECORD: - break; - } - return true; - } - - void setState(Media::State state) { - _state = state; - _stateChanged = true; - _timer.start(250); - } - - QMediaPlayer _player; - - QAudioRecorder _recorder; - QTimer _timer; - - Media::State _state; - QString _src; - enum Mode { - MODE_NONE, - MODE_PLAY, - MODE_RECORD - }; - Mode _mode; - Media *_plugin; - QString _id; - - bool _stateChanged; -}; - -#endif diff --git a/plugins/org.apache.cordova.media/src/windows8/MediaProxy.js b/plugins/org.apache.cordova.media/src/windows8/MediaProxy.js deleted file mode 100644 index e7ec51b7..00000000 --- a/plugins/org.apache.cordova.media/src/windows8/MediaProxy.js +++ /dev/null @@ -1,217 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -/*global Windows:true */ - -var cordova = require('cordova'), - Media = require('org.apache.cordova.media.Media'); - -var MediaError = require('org.apache.cordova.media.MediaError'); - -var recordedFile; - -module.exports = { - mediaCaptureMrg:null, - - // Initiates the audio file - create:function(win, lose, args) { - var id = args[0]; - var src = args[1]; - var thisM = Media.get(id); - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_STARTING); - - Media.prototype.node = null; - - var fn = src.split('.').pop(); // gets the file extension - if (thisM.node === null) { - if (fn === 'mp3' || fn === 'wma' || fn === 'wav' || - fn === 'cda' || fn === 'adx' || fn === 'wm' || - fn === 'm3u' || fn === 'wmx' || fn === 'm4a') { - thisM.node = new Audio(src); - thisM.node.load(); - - var getDuration = function () { - var dur = thisM.node.duration; - if (isNaN(dur)) { - dur = -1; - } - Media.onStatus(id, Media.MEDIA_DURATION, dur); - }; - - thisM.node.onloadedmetadata = getDuration; - getDuration(); - } - else { - lose && lose({code:MediaError.MEDIA_ERR_ABORTED}); - } - } - }, - - // Start playing the audio - startPlayingAudio:function(win, lose, args) { - var id = args[0]; - //var src = args[1]; - //var options = args[2]; - - var thisM = Media.get(id); - // if Media was released, then node will be null and we need to create it again - if (!thisM.node) { - module.exports.create(win, lose, args); - } - - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_RUNNING); - - thisM.node.play(); - }, - - // Stops the playing audio - stopPlayingAudio:function(win, lose, args) { - var id = args[0]; - try { - (Media.get(id)).node.pause(); - (Media.get(id)).node.currentTime = 0; - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_STOPPED); - win(); - } catch (err) { - lose("Failed to stop: "+err); - } - }, - - // Seeks to the position in the audio - seekToAudio:function(win, lose, args) { - var id = args[0]; - var milliseconds = args[1]; - try { - (Media.get(id)).node.currentTime = milliseconds / 1000; - win(); - } catch (err) { - lose("Failed to seek: "+err); - } - }, - - // Pauses the playing audio - pausePlayingAudio:function(win, lose, args) { - var id = args[0]; - var thisM = Media.get(id); - try { - thisM.node.pause(); - Media.onStatus(id, Media.MEDIA_STATE, Media.MEDIA_PAUSED); - } catch (err) { - lose("Failed to pause: "+err); - } - }, - - // Gets current position in the audio - getCurrentPositionAudio:function(win, lose, args) { - var id = args[0]; - try { - var p = (Media.get(id)).node.currentTime; - Media.onStatus(id, Media.MEDIA_POSITION, p); - win(p); - } catch (err) { - lose(err); - } - }, - - // Start recording audio - startRecordingAudio:function(win, lose, args) { - var id = args[0]; - var src = args[1]; - - var normalizedSrc = src.replace(/\//g, '\\'); - var destPath = normalizedSrc.substr(0, normalizedSrc.lastIndexOf('\\')); - var destFileName = normalizedSrc.replace(destPath + '\\', ''); - - // Initialize device - Media.prototype.mediaCaptureMgr = null; - var thisM = (Media.get(id)); - var captureInitSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings(); - captureInitSettings.streamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.audio; - thisM.mediaCaptureMgr = new Windows.Media.Capture.MediaCapture(); - thisM.mediaCaptureMgr.addEventListener("failed", lose); - - thisM.mediaCaptureMgr.initializeAsync(captureInitSettings).done(function (result) { - thisM.mediaCaptureMgr.addEventListener("recordlimitationexceeded", lose); - thisM.mediaCaptureMgr.addEventListener("failed", lose); - - // Start recording - Windows.Storage.ApplicationData.current.temporaryFolder.createFileAsync(destFileName, Windows.Storage.CreationCollisionOption.replaceExisting).done(function (newFile) { - recordedFile = newFile; - var encodingProfile = null; - switch (newFile.fileType) { - case '.m4a': - encodingProfile = Windows.Media.MediaProperties.MediaEncodingProfile.createM4a(Windows.Media.MediaProperties.AudioEncodingQuality.auto); - break; - case '.mp3': - encodingProfile = Windows.Media.MediaProperties.MediaEncodingProfile.createMp3(Windows.Media.MediaProperties.AudioEncodingQuality.auto); - break; - case '.wma': - encodingProfile = Windows.Media.MediaProperties.MediaEncodingProfile.createWma(Windows.Media.MediaProperties.AudioEncodingQuality.auto); - break; - default: - lose("Invalid file type for record"); - break; - } - thisM.mediaCaptureMgr.startRecordToStorageFileAsync(encodingProfile, newFile).done(win, lose); - }, lose); - }, lose); - }, - - // Stop recording audio - stopRecordingAudio:function(win, lose, args) { - var id = args[0]; - var thisM = Media.get(id); - - var normalizedSrc = thisM.src.replace(/\//g, '\\'); - var destPath = normalizedSrc.substr(0, normalizedSrc.lastIndexOf('\\')); - var destFileName = normalizedSrc.replace(destPath + '\\', ''); - - thisM.mediaCaptureMgr.stopRecordAsync().done(function () { - if (destPath) { - Windows.Storage.StorageFolder.getFolderFromPathAsync(destPath).done(function(destFolder) { - recordedFile.copyAsync(destFolder, destFileName, Windows.Storage.CreationCollisionOption.replaceExisting).done(win, lose); - }, lose); - } else { - // if path is not defined, we leave recorded file in temporary folder (similar to iOS) - win(); - } - }, lose); - }, - - // Release the media object - release:function(win, lose, args) { - var id = args[0]; - var thisM = Media.get(id); - try { - delete thisM.node; - } catch (err) { - lose("Failed to release: "+err); - } - }, - setVolume:function(win, lose, args) { - var id = args[0]; - var volume = args[1]; - var thisM = Media.get(id); - thisM.volume = volume; - } -}; - -require("cordova/exec/proxy").add("Media",module.exports); diff --git a/plugins/org.apache.cordova.media/src/wp/AudioPlayer.cs b/plugins/org.apache.cordova.media/src/wp/AudioPlayer.cs deleted file mode 100644 index 882eb96e..00000000 --- a/plugins/org.apache.cordova.media/src/wp/AudioPlayer.cs +++ /dev/null @@ -1,647 +0,0 @@ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -using System; -using System.IO; -using System.IO.IsolatedStorage; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Threading; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Audio; -using Microsoft.Xna.Framework.Media; -using Microsoft.Phone.Controls; -using System.Diagnostics; -using System.Windows.Resources; - -namespace WPCordovaClassLib.Cordova.Commands -{ - - /// - /// Implements audio record and play back functionality. - /// - internal class AudioPlayer : IDisposable - { - #region Constants - - // AudioPlayer states - private const int PlayerState_None = 0; - private const int PlayerState_Starting = 1; - private const int PlayerState_Running = 2; - private const int PlayerState_Paused = 3; - private const int PlayerState_Stopped = 4; - - // AudioPlayer messages - private const int MediaState = 1; - private const int MediaDuration = 2; - private const int MediaPosition = 3; - private const int MediaError = 9; - - // AudioPlayer errors - private const int MediaErrorPlayModeSet = 1; - private const int MediaErrorAlreadyRecording = 2; - private const int MediaErrorStartingRecording = 3; - private const int MediaErrorRecordModeSet = 4; - private const int MediaErrorStartingPlayback = 5; - private const int MediaErrorResumeState = 6; - private const int MediaErrorPauseState = 7; - private const int MediaErrorStopState = 8; - - //TODO: get rid of this callback, it should be universal - //private const string CallbackFunction = "CordovaMediaonStatus"; - - #endregion - - - /// - /// The AudioHandler object - /// - private Media handler; - - /// - /// Temporary buffer to store audio chunk - /// - private byte[] buffer; - - /// - /// Xna game loop dispatcher - /// - DispatcherTimer dtXna; - - - /// - /// Output buffer - /// - private MemoryStream memoryStream; - - /// - /// The id of this player (used to identify Media object in JavaScript) - /// - private String id; - - /// - /// State of recording or playback - /// - private int state = PlayerState_None; - - /// - /// File name to play or record to - /// - private String audioFile = null; - - /// - /// Duration of audio - /// - private double duration = -1; - - /// - /// Audio player object - /// - private MediaElement player = null; - - /// - /// Audio source - /// - private Microphone recorder; - - /// - /// Internal flag specified that we should only open audio w/o playing it - /// - private bool prepareOnly = false; - - /// - /// Creates AudioPlayer instance - /// - /// Media object - /// player id - public AudioPlayer(Media handler, String id) - { - this.handler = handler; - this.id = id; - } - - - /// - /// Destroys player and stop audio playing or recording - /// - public void Dispose() - { - if (this.player != null) - { - this.stopPlaying(); - this.player = null; - } - if (this.recorder != null) - { - this.stopRecording(); - this.recorder = null; - } - - this.FinalizeXnaGameLoop(); - } - - private void InvokeCallback(int message, string value, bool removeHandler) - { - string args = string.Format("('{0}',{1},{2});", this.id, message, value); - string callback = @"(function(id,msg,value){ - try { - if (msg == Media.MEDIA_ERROR) { - value = {'code':value}; - } - Media.onStatus(id,msg,value); - } - catch(e) { - console.log('Error calling Media.onStatus :: ' + e); - } - })" + args; - this.handler.InvokeCustomScript(new ScriptCallback("eval", new string[] { callback }), false); - } - - private void InvokeCallback(int message, int value, bool removeHandler) - { - InvokeCallback(message, value.ToString(), removeHandler); - } - - private void InvokeCallback(int message, double value, bool removeHandler) - { - InvokeCallback(message, value.ToString(), removeHandler); - } - - /// - /// Starts recording, data is stored in memory - /// - /// - public void startRecording(string filePath) - { - if (this.player != null) - { - InvokeCallback(MediaError, MediaErrorPlayModeSet, false); - } - else if (this.recorder == null) - { - try - { - this.audioFile = filePath; - this.InitializeXnaGameLoop(); - this.recorder = Microphone.Default; - this.recorder.BufferDuration = TimeSpan.FromMilliseconds(500); - this.buffer = new byte[recorder.GetSampleSizeInBytes(this.recorder.BufferDuration)]; - this.recorder.BufferReady += new EventHandler(recorderBufferReady); - MemoryStream stream = new MemoryStream(); - this.memoryStream = stream; - int numBits = 16; - int numBytes = numBits / 8; - - // inline version from AudioFormatsHelper - stream.Write(System.Text.Encoding.UTF8.GetBytes("RIFF"), 0, 4); - stream.Write(BitConverter.GetBytes(0), 0, 4); - stream.Write(System.Text.Encoding.UTF8.GetBytes("WAVE"), 0, 4); - stream.Write(System.Text.Encoding.UTF8.GetBytes("fmt "), 0, 4); - stream.Write(BitConverter.GetBytes(16), 0, 4); - stream.Write(BitConverter.GetBytes((short)1), 0, 2); - stream.Write(BitConverter.GetBytes((short)1), 0, 2); - stream.Write(BitConverter.GetBytes(this.recorder.SampleRate), 0, 4); - stream.Write(BitConverter.GetBytes(this.recorder.SampleRate * numBytes), 0, 4); - stream.Write(BitConverter.GetBytes((short)(numBytes)), 0, 2); - stream.Write(BitConverter.GetBytes((short)(numBits)), 0, 2); - stream.Write(System.Text.Encoding.UTF8.GetBytes("data"), 0, 4); - stream.Write(BitConverter.GetBytes(0), 0, 4); - - this.recorder.Start(); - FrameworkDispatcher.Update(); - this.SetState(PlayerState_Running); - } - catch (Exception) - { - InvokeCallback(MediaError, MediaErrorStartingRecording, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingRecording),false); - } - } - else - { - InvokeCallback(MediaError, MediaErrorAlreadyRecording, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorAlreadyRecording),false); - } - } - - /// - /// Stops recording - /// - public void stopRecording() - { - if (this.recorder != null) - { - if (this.state == PlayerState_Running) - { - try - { - this.recorder.Stop(); - this.recorder.BufferReady -= recorderBufferReady; - this.recorder = null; - SaveAudioClipToLocalStorage(); - this.FinalizeXnaGameLoop(); - this.SetState(PlayerState_Stopped); - } - catch (Exception) - { - //TODO - } - } - } - } - - /// - /// Starts or resume playing audio file - /// - /// The name of the audio file - /// - /// Starts or resume playing audio file - /// - /// The name of the audio file - public void startPlaying(string filePath) - { - if (this.recorder != null) - { - InvokeCallback(MediaError, MediaErrorRecordModeSet, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorRecordModeSet),false); - return; - } - - - if (this.player == null || this.player.Source.AbsolutePath.LastIndexOf(filePath) < 0) - { - try - { - // this.player is a MediaElement, it must be added to the visual tree in order to play - PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; - if (frame != null) - { - PhoneApplicationPage page = frame.Content as PhoneApplicationPage; - if (page != null) - { - Grid grid = page.FindName("LayoutRoot") as Grid; - if (grid != null) - { - - this.player = grid.FindName("playerMediaElement") as MediaElement; - if (this.player == null) // still null ? - { - this.player = new MediaElement(); - this.player.Name = "playerMediaElement"; - grid.Children.Add(this.player); - this.player.Visibility = Visibility.Visible; - } - if (this.player.CurrentState == System.Windows.Media.MediaElementState.Playing) - { - this.player.Stop(); // stop it! - } - - this.player.Source = null; // Garbage collect it. - this.player.MediaOpened += MediaOpened; - this.player.MediaEnded += MediaEnded; - this.player.MediaFailed += MediaFailed; - } - } - } - - this.audioFile = filePath; - - Uri uri = new Uri(filePath, UriKind.RelativeOrAbsolute); - if (uri.IsAbsoluteUri) - { - this.player.Source = uri; - } - else - { - using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication()) - { - if (!isoFile.FileExists(filePath)) - { - // try to unpack it from the dll into isolated storage - StreamResourceInfo fileResourceStreamInfo = Application.GetResourceStream(new Uri(filePath, UriKind.Relative)); - if (fileResourceStreamInfo != null) - { - using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream)) - { - byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length); - - string[] dirParts = filePath.Split('/'); - string dirName = ""; - for (int n = 0; n < dirParts.Length - 1; n++) - { - dirName += dirParts[n] + "/"; - } - if (!isoFile.DirectoryExists(dirName)) - { - isoFile.CreateDirectory(dirName); - } - - using (IsolatedStorageFileStream outFile = isoFile.OpenFile(filePath, FileMode.Create)) - { - using (BinaryWriter writer = new BinaryWriter(outFile)) - { - writer.Write(data); - } - } - } - } - } - if (isoFile.FileExists(filePath)) - { - using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, isoFile)) - { - this.player.SetSource(stream); - } - } - else - { - InvokeCallback(MediaError, MediaErrorPlayModeSet, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, 1), false); - return; - } - } - } - this.SetState(PlayerState_Starting); - } - catch (Exception e) - { - Debug.WriteLine("Error in AudioPlayer::startPlaying : " + e.Message); - InvokeCallback(MediaError, MediaErrorStartingPlayback, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingPlayback),false); - } - } - else - { - if (this.state != PlayerState_Running) - { - this.player.Play(); - this.SetState(PlayerState_Running); - } - else - { - InvokeCallback(MediaError, MediaErrorResumeState, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorResumeState),false); - } - } - } - - /// - /// Callback to be invoked when the media source is ready for playback - /// - private void MediaOpened(object sender, RoutedEventArgs arg) - { - if (this.player != null) - { - this.duration = this.player.NaturalDuration.TimeSpan.TotalSeconds; - InvokeCallback(MediaDuration, this.duration, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaDuration, this.duration),false); - if (!this.prepareOnly) - { - this.player.Play(); - this.SetState(PlayerState_Running); - } - this.prepareOnly = false; - } - else - { - // TODO: occasionally MediaOpened is signalled, but player is null - } - } - - /// - /// Callback to be invoked when playback of a media source has completed - /// - private void MediaEnded(object sender, RoutedEventArgs arg) - { - this.SetState(PlayerState_Stopped); - } - - /// - /// Callback to be invoked when playback of a media source has failed - /// - private void MediaFailed(object sender, RoutedEventArgs arg) - { - player.Stop(); - InvokeCallback(MediaError, MediaErrorStartingPlayback, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError.ToString(), "Media failed"),false); - } - - /// - /// Seek or jump to a new time in the track - /// - /// The new track position - public void seekToPlaying(int milliseconds) - { - if (this.player != null) - { - TimeSpan tsPos = new TimeSpan(0, 0, 0, 0, milliseconds); - this.player.Position = tsPos; - InvokeCallback(MediaPosition, milliseconds / 1000.0f, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaPosition, milliseconds / 1000.0f),false); - } - } - - /// - /// Set the volume of the player - /// - /// volume 0.0-1.0, default value is 0.5 - public void setVolume(double vol) - { - if (this.player != null) - { - this.player.Volume = vol; - } - } - - /// - /// Pauses playing - /// - public void pausePlaying() - { - if (this.state == PlayerState_Running) - { - this.player.Pause(); - this.SetState(PlayerState_Paused); - } - else - { - InvokeCallback(MediaError, MediaErrorPauseState, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorPauseState),false); - } - } - - - /// - /// Stops playing the audio file - /// - public void stopPlaying() - { - if ((this.state == PlayerState_Running) || (this.state == PlayerState_Paused)) - { - this.player.Stop(); - - this.player.Position = new TimeSpan(0L); - this.SetState(PlayerState_Stopped); - } - //else // Why is it an error to call stop on a stopped media? - //{ - // this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStopState), false); - //} - } - - /// - /// Gets current position of playback - /// - /// current position - public double getCurrentPosition() - { - if ((this.state == PlayerState_Running) || (this.state == PlayerState_Paused)) - { - double currentPosition = this.player.Position.TotalSeconds; - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaPosition, currentPosition),false); - return currentPosition; - } - else - { - return 0; - } - } - - /// - /// Gets the duration of the audio file - /// - /// The name of the audio file - /// track duration - public double getDuration(string filePath) - { - if (this.recorder != null) - { - return (-2); - } - - if (this.player != null) - { - return this.duration; - - } - else - { - this.prepareOnly = true; - this.startPlaying(filePath); - return this.duration; - } - } - - /// - /// Sets the state and send it to JavaScript - /// - /// state - private void SetState(int state) - { - if (this.state != state) - { - InvokeCallback(MediaState, state, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaState, state),false); - } - - this.state = state; - } - - #region record methods - - /// - /// Copies data from recorder to memory storages and updates recording state - /// - /// - /// - private void recorderBufferReady(object sender, EventArgs e) - { - this.recorder.GetData(this.buffer); - this.memoryStream.Write(this.buffer, 0, this.buffer.Length); - } - - /// - /// Writes audio data from memory to isolated storage - /// - /// - private void SaveAudioClipToLocalStorage() - { - if (memoryStream == null || memoryStream.Length <= 0) - { - return; - } - - long position = memoryStream.Position; - memoryStream.Seek(4, SeekOrigin.Begin); - memoryStream.Write(BitConverter.GetBytes((int)memoryStream.Length - 8), 0, 4); - memoryStream.Seek(40, SeekOrigin.Begin); - memoryStream.Write(BitConverter.GetBytes((int)memoryStream.Length - 44), 0, 4); - memoryStream.Seek(position, SeekOrigin.Begin); - - try - { - using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication()) - { - string directory = Path.GetDirectoryName(audioFile); - - if (!isoFile.DirectoryExists(directory)) - { - isoFile.CreateDirectory(directory); - } - - this.memoryStream.Seek(0, SeekOrigin.Begin); - - using (IsolatedStorageFileStream fileStream = isoFile.CreateFile(audioFile)) - { - this.memoryStream.CopyTo(fileStream); - } - } - } - catch (Exception) - { - //TODO: log or do something else - throw; - } - } - - #region Xna loop - /// - /// Special initialization required for the microphone: XNA game loop - /// - private void InitializeXnaGameLoop() - { - // Timer to simulate the XNA game loop (Microphone is from XNA) - this.dtXna = new DispatcherTimer(); - this.dtXna.Interval = TimeSpan.FromMilliseconds(33); - this.dtXna.Tick += delegate { try { FrameworkDispatcher.Update(); } catch { } }; - this.dtXna.Start(); - } - /// - /// Finalizes XNA game loop for microphone - /// - private void FinalizeXnaGameLoop() - { - // Timer to simulate the XNA game loop (Microphone is from XNA) - if (this.dtXna != null) - { - this.dtXna.Stop(); - this.dtXna = null; - } - } - - #endregion - - #endregion - } -} diff --git a/plugins/org.apache.cordova.media/src/wp/Media.cs b/plugins/org.apache.cordova.media/src/wp/Media.cs deleted file mode 100644 index aedd2bb6..00000000 --- a/plugins/org.apache.cordova.media/src/wp/Media.cs +++ /dev/null @@ -1,590 +0,0 @@ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using System.Windows; -using System.Diagnostics; - -namespace WPCordovaClassLib.Cordova.Commands -{ - /// - /// Provides the ability to record and play back audio files on a device. - /// - public class Media : BaseCommand - { - /// - /// Audio player objects - /// - private static Dictionary players = new Dictionary(); - - /// - /// Represents Media action options. - /// - [DataContract] - public class MediaOptions - { - /// - /// Audio id - /// - [DataMember(Name = "id", IsRequired = true)] - public string Id { get; set; } - - /// - /// Path to audio file - /// - [DataMember(Name = "src")] - public string Src { get; set; } - - /// - /// New track position - /// - [DataMember(Name = "milliseconds")] - public int Milliseconds { get; set; } - - public string CallbackId { get; set; } - } - - /// - /// Releases the audio player instance to save memory. - /// - public void release(string options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - MediaOptions mediaOptions = new MediaOptions(); - - try - { - string[] optionsString = JSON.JsonHelper.Deserialize(options); - mediaOptions.Id = optionsString[0]; - callbackId = mediaOptions.CallbackId = optionsString[1]; - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId); - return; - } - - if (!Media.players.ContainsKey(mediaOptions.Id)) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, false), callbackId); - return; - } - - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - AudioPlayer audio = Media.players[mediaOptions.Id]; - Media.players.Remove(mediaOptions.Id); - audio.Dispose(); - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, true), mediaOptions.CallbackId); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), mediaOptions.CallbackId); - } - }); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - } - - private AudioPlayer GetOrCreatePlayerById(string id) - { - AudioPlayer audio = null; - - lock (Media.players) - { - if (!Media.players.TryGetValue(id, out audio)) - { - audio = new AudioPlayer(this, id); - Media.players.Add(id, audio); - Debug.WriteLine("Media Created in GetOrCreatePlayerById"); - } - } - - - - return audio; - } - - /// - /// Starts recording and save the specified file - /// - public void startRecordingAudio(string options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - MediaOptions mediaOptions = new MediaOptions(); - - try - { - string[] optionsString = JSON.JsonHelper.Deserialize(options); - mediaOptions.Id = optionsString[0]; - mediaOptions.Src = optionsString[1]; - callbackId = mediaOptions.CallbackId = optionsString[2]; - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), mediaOptions.CallbackId); - return; - } - - if (mediaOptions != null) - { - - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - AudioPlayer audio; - if (!Media.players.ContainsKey(mediaOptions.Id)) - { - audio = new AudioPlayer(this, mediaOptions.Id); - Media.players.Add(mediaOptions.Id, audio); - } - else - { - audio = Media.players[mediaOptions.Id]; - } - - if (audio != null) - { - audio.startRecording(mediaOptions.Src); - DispatchCommandResult(new PluginResult(PluginResult.Status.OK), mediaOptions.CallbackId); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, - "Error accessing AudioPlayer for key " + mediaOptions.Id), mediaOptions.CallbackId); - } - - - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), mediaOptions.CallbackId); - } - - }); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), mediaOptions.CallbackId); - } - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - } - - /// - /// Stops recording and save to the file specified when recording started - /// - public void stopRecordingAudio(string options) - { - string callbackId = this.CurrentCommandCallbackId; - - try - { - string[] optStrings = JSON.JsonHelper.Deserialize(options); - string mediaId = optStrings[0]; - callbackId = optStrings[1]; - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - if (Media.players.ContainsKey(mediaId)) - { - AudioPlayer audio = Media.players[mediaId]; - audio.stopRecording(); - Media.players.Remove(mediaId); - } - DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - }); - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId); - } - } - - public void setVolume(string options) // id,volume - { - string callbackId = this.CurrentCommandCallbackId; - try - { - string[] optionsString = JSON.JsonHelper.Deserialize(options); - string id = optionsString[0]; - double volume = 0.0d; - double.TryParse(optionsString[1], out volume); - - callbackId = optionsString[2]; - - if (Media.players.ContainsKey(id)) - { - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - AudioPlayer player = Media.players[id]; - player.setVolume(volume); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - }); - } - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, - "Error parsing options into setVolume method"), callbackId); - } - } - - // Some Audio Notes: - // In the Windows Phone Emulator, playback of video or audio content using the MediaElement control is not supported. - // While playing, a MediaElement stops all other media playback on the phone. - // Multiple MediaElement controls are NOT supported - - // Called when you create a new Media('blah.wav') object in JS. - public void create(string options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - MediaOptions mediaOptions; - try - { - string[] optionsString = JSON.JsonHelper.Deserialize(options); - mediaOptions = new MediaOptions(); - mediaOptions.Id = optionsString[0]; - mediaOptions.Src = optionsString[1]; - callbackId = mediaOptions.CallbackId = optionsString[2]; - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, - "Error parsing options into create method"), callbackId); - return; - } - - GetOrCreatePlayerById(mediaOptions.Id); - DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId); - - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - } - - /// - /// Starts or resume playing audio file - /// - public void startPlayingAudio(string options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - MediaOptions mediaOptions; - try - { - string[] optionsString = JSON.JsonHelper.Deserialize(options); - mediaOptions = new MediaOptions(); - mediaOptions.Id = optionsString[0]; - mediaOptions.Src = optionsString[1]; - int msec = 0; - if (int.TryParse(optionsString[2], out msec)) - { - mediaOptions.Milliseconds = msec; - } - callbackId = mediaOptions.CallbackId = optionsString[3]; - - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId); - return; - } - - AudioPlayer audio = GetOrCreatePlayerById(mediaOptions.Id); - - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - audio.startPlaying(mediaOptions.Src); - DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - }); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - } - - - /// - /// Seeks to a location - /// - public void seekToAudio(string options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - MediaOptions mediaOptions; - - try - { - string[] optionsString = JSON.JsonHelper.Deserialize(options); - mediaOptions = new MediaOptions(); - mediaOptions.Id = optionsString[0]; - int msec = 0; - if (int.TryParse(optionsString[2], out msec)) - { - mediaOptions.Milliseconds = msec; - } - callbackId = mediaOptions.CallbackId = optionsString[3]; - - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId); - return; - } - - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - if (Media.players.ContainsKey(mediaOptions.Id)) - { - AudioPlayer audio = Media.players[mediaOptions.Id]; - audio.seekToPlaying(mediaOptions.Milliseconds); - } - else - { - Debug.WriteLine("ERROR: seekToAudio could not find mediaPlayer for " + mediaOptions.Id); - } - - DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - }); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - } - - /// - /// Pauses playing - /// - public void pausePlayingAudio(string options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - string[] optionsString = JSON.JsonHelper.Deserialize(options); - string mediaId = optionsString[0]; - callbackId = optionsString[1]; - - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - if (Media.players.ContainsKey(mediaId)) - { - AudioPlayer audio = Media.players[mediaId]; - audio.pausePlaying(); - } - else - { - Debug.WriteLine("ERROR: pausePlayingAudio could not find mediaPlayer for " + mediaId); - } - - DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message),callbackId); - } - }); - - - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION),callbackId); - } - - - } - - - /// - /// Stops playing the audio file - /// - public void stopPlayingAudio(String options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - string[] optionsStrings = JSON.JsonHelper.Deserialize(options); - string mediaId = optionsStrings[0]; - callbackId = optionsStrings[1]; - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - if (Media.players.ContainsKey(mediaId)) - { - AudioPlayer audio = Media.players[mediaId]; - audio.stopPlaying(); - } - else - { - Debug.WriteLine("stopPlaying could not find mediaPlayer for " + mediaId); - } - - DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - }); - - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId); - } - } - - /// - /// Gets current position of playback - /// - public void getCurrentPositionAudio(string options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - string[] optionsStrings = JSON.JsonHelper.Deserialize(options); - string mediaId = optionsStrings[0]; - callbackId = optionsStrings[1]; - Deployment.Current.Dispatcher.BeginInvoke(() => - { - try - { - if (Media.players.ContainsKey(mediaId)) - { - AudioPlayer audio = Media.players[mediaId]; - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, audio.getCurrentPosition()), callbackId); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, -1), callbackId); - } - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - }); - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId); - return; - } - } - - - /// - /// Gets the duration of the audio file - /// - - [Obsolete("This method will be removed shortly")] - public void getDurationAudio(string options) - { - string callbackId = this.CurrentCommandCallbackId; - try - { - MediaOptions mediaOptions; - - try - { - string[] optionsString = JSON.JsonHelper.Deserialize(options); - - mediaOptions = new MediaOptions(); - mediaOptions.Id = optionsString[0]; - mediaOptions.Src = optionsString[1]; - callbackId = mediaOptions.CallbackId = optionsString[2]; - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId); - return; - } - - AudioPlayer audio; - if (Media.players.ContainsKey(mediaOptions.Id)) - { - audio = Media.players[mediaOptions.Id]; - } - else - { - Debug.WriteLine("ERROR: getDurationAudio could not find mediaPlayer for " + mediaOptions.Id); - audio = new AudioPlayer(this, mediaOptions.Id); - Media.players.Add(mediaOptions.Id, audio); - } - - Deployment.Current.Dispatcher.BeginInvoke(() => - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, audio.getDuration(mediaOptions.Src)), callbackId); - }); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId); - } - } - } -} -- cgit v1.2.3