summaryrefslogtreecommitdiff
path: root/plugins/org.apache.cordova.media/src
diff options
context:
space:
mode:
authorArjun Roychowdhury <pliablepixels@gmail.com>2015-10-31 08:21:38 -0400
committerArjun Roychowdhury <pliablepixels@gmail.com>2015-10-31 08:21:38 -0400
commit02811010cf62f1b21a06780d1e470d04bb24c50f (patch)
tree0d933789068aac11c810ed4bb169d14ab16c43c6 /plugins/org.apache.cordova.media/src
parentbca561c1b3989d62a1fba829e0380c6fbf36caf5 (diff)
removed unecessary files from git
Diffstat (limited to 'plugins/org.apache.cordova.media/src')
-rw-r--r--plugins/org.apache.cordova.media/src/android/AudioHandler.java410
-rw-r--r--plugins/org.apache.cordova.media/src/android/AudioPlayer.java587
-rw-r--r--plugins/org.apache.cordova.media/src/android/FileHelper.java38
-rw-r--r--plugins/org.apache.cordova.media/src/blackberry10/index.js237
-rw-r--r--plugins/org.apache.cordova.media/src/ios/CDVSound.h113
-rw-r--r--plugins/org.apache.cordova.media/src/ios/CDVSound.m703
-rw-r--r--plugins/org.apache.cordova.media/src/tizen/MediaProxy.js223
-rw-r--r--plugins/org.apache.cordova.media/src/ubuntu/media.cpp128
-rw-r--r--plugins/org.apache.cordova.media/src/ubuntu/media.h267
-rw-r--r--plugins/org.apache.cordova.media/src/windows8/MediaProxy.js217
-rw-r--r--plugins/org.apache.cordova.media/src/wp/AudioPlayer.cs647
-rw-r--r--plugins/org.apache.cordova.media/src/wp/Media.cs590
12 files changed, 0 insertions, 4160 deletions
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<String, AudioPlayer> players; // Audio player object
- ArrayList<AudioPlayer> 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<String, AudioPlayer>();
- this.pausedForPhone = new ArrayList<AudioPlayer>();
- }
-
- /**
- * 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 <Foundation/Foundation.h>
-#import <AudioToolbox/AudioServices.h>
-#import <AVFoundation/AVFoundation.h>
-
-#import <Cordova/CDVPlugin.h>
-
-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 <AVAudioPlayerDelegate, AVAudioRecorderDelegate>
-{
- 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 <Cordova/NSArray+Comparisons.h>
-
-#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<Player>(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> 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> 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> 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> 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> 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> 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> 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> 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 <QtMultimedia/QMediaPlayer>
-#include <QtCore>
-#include <QAudioRecorder>
-#include <QtMultimedia/QAudioEncoderSettings>
-
-#include <cplugin.h>
-#include <cordova.h>
-
-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<QString, QSharedPointer<Player> > _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<double>(_player.duration()) / 1000.0;
- }
- double getPosition() {
- if (_mode != MODE_PLAY)
- return -1;
- return static_cast<double>(_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
-{
-
- /// <summary>
- /// Implements audio record and play back functionality.
- /// </summary>
- 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
-
-
- /// <summary>
- /// The AudioHandler object
- /// </summary>
- private Media handler;
-
- /// <summary>
- /// Temporary buffer to store audio chunk
- /// </summary>
- private byte[] buffer;
-
- /// <summary>
- /// Xna game loop dispatcher
- /// </summary>
- DispatcherTimer dtXna;
-
-
- /// <summary>
- /// Output buffer
- /// </summary>
- private MemoryStream memoryStream;
-
- /// <summary>
- /// The id of this player (used to identify Media object in JavaScript)
- /// </summary>
- private String id;
-
- /// <summary>
- /// State of recording or playback
- /// </summary>
- private int state = PlayerState_None;
-
- /// <summary>
- /// File name to play or record to
- /// </summary>
- private String audioFile = null;
-
- /// <summary>
- /// Duration of audio
- /// </summary>
- private double duration = -1;
-
- /// <summary>
- /// Audio player object
- /// </summary>
- private MediaElement player = null;
-
- /// <summary>
- /// Audio source
- /// </summary>
- private Microphone recorder;
-
- /// <summary>
- /// Internal flag specified that we should only open audio w/o playing it
- /// </summary>
- private bool prepareOnly = false;
-
- /// <summary>
- /// Creates AudioPlayer instance
- /// </summary>
- /// <param name="handler">Media object</param>
- /// <param name="id">player id</param>
- public AudioPlayer(Media handler, String id)
- {
- this.handler = handler;
- this.id = id;
- }
-
-
- /// <summary>
- /// Destroys player and stop audio playing or recording
- /// </summary>
- 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);
- }
-
- /// <summary>
- /// Starts recording, data is stored in memory
- /// </summary>
- /// <param name="filePath"></param>
- 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<EventArgs>(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);
- }
- }
-
- /// <summary>
- /// Stops recording
- /// </summary>
- 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
- }
- }
- }
- }
-
- /// <summary>
- /// Starts or resume playing audio file
- /// </summary>
- /// <param name="filePath">The name of the audio file</param>
- /// <summary>
- /// Starts or resume playing audio file
- /// </summary>
- /// <param name="filePath">The name of the audio file</param>
- 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);
- }
- }
- }
-
- /// <summary>
- /// Callback to be invoked when the media source is ready for playback
- /// </summary>
- 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
- }
- }
-
- /// <summary>
- /// Callback to be invoked when playback of a media source has completed
- /// </summary>
- private void MediaEnded(object sender, RoutedEventArgs arg)
- {
- this.SetState(PlayerState_Stopped);
- }
-
- /// <summary>
- /// Callback to be invoked when playback of a media source has failed
- /// </summary>
- 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);
- }
-
- /// <summary>
- /// Seek or jump to a new time in the track
- /// </summary>
- /// <param name="milliseconds">The new track position</param>
- 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);
- }
- }
-
- /// <summary>
- /// Set the volume of the player
- /// </summary>
- /// <param name="vol">volume 0.0-1.0, default value is 0.5</param>
- public void setVolume(double vol)
- {
- if (this.player != null)
- {
- this.player.Volume = vol;
- }
- }
-
- /// <summary>
- /// Pauses playing
- /// </summary>
- 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);
- }
- }
-
-
- /// <summary>
- /// Stops playing the audio file
- /// </summary>
- 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);
- //}
- }
-
- /// <summary>
- /// Gets current position of playback
- /// </summary>
- /// <returns>current position</returns>
- 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;
- }
- }
-
- /// <summary>
- /// Gets the duration of the audio file
- /// </summary>
- /// <param name="filePath">The name of the audio file</param>
- /// <returns>track duration</returns>
- 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;
- }
- }
-
- /// <summary>
- /// Sets the state and send it to JavaScript
- /// </summary>
- /// <param name="state">state</param>
- 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
-
- /// <summary>
- /// Copies data from recorder to memory storages and updates recording state
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void recorderBufferReady(object sender, EventArgs e)
- {
- this.recorder.GetData(this.buffer);
- this.memoryStream.Write(this.buffer, 0, this.buffer.Length);
- }
-
- /// <summary>
- /// Writes audio data from memory to isolated storage
- /// </summary>
- /// <returns></returns>
- 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
- /// <summary>
- /// Special initialization required for the microphone: XNA game loop
- /// </summary>
- 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();
- }
- /// <summary>
- /// Finalizes XNA game loop for microphone
- /// </summary>
- 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
-{
- /// <summary>
- /// Provides the ability to record and play back audio files on a device.
- /// </summary>
- public class Media : BaseCommand
- {
- /// <summary>
- /// Audio player objects
- /// </summary>
- private static Dictionary<string, AudioPlayer> players = new Dictionary<string, AudioPlayer>();
-
- /// <summary>
- /// Represents Media action options.
- /// </summary>
- [DataContract]
- public class MediaOptions
- {
- /// <summary>
- /// Audio id
- /// </summary>
- [DataMember(Name = "id", IsRequired = true)]
- public string Id { get; set; }
-
- /// <summary>
- /// Path to audio file
- /// </summary>
- [DataMember(Name = "src")]
- public string Src { get; set; }
-
- /// <summary>
- /// New track position
- /// </summary>
- [DataMember(Name = "milliseconds")]
- public int Milliseconds { get; set; }
-
- public string CallbackId { get; set; }
- }
-
- /// <summary>
- /// Releases the audio player instance to save memory.
- /// </summary>
- public void release(string options)
- {
- string callbackId = this.CurrentCommandCallbackId;
- try
- {
- MediaOptions mediaOptions = new MediaOptions();
-
- try
- {
- string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(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;
- }
-
- /// <summary>
- /// Starts recording and save the specified file
- /// </summary>
- public void startRecordingAudio(string options)
- {
- string callbackId = this.CurrentCommandCallbackId;
- try
- {
- MediaOptions mediaOptions = new MediaOptions();
-
- try
- {
- string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(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);
- }
- }
-
- /// <summary>
- /// Stops recording and save to the file specified when recording started
- /// </summary>
- public void stopRecordingAudio(string options)
- {
- string callbackId = this.CurrentCommandCallbackId;
-
- try
- {
- string[] optStrings = JSON.JsonHelper.Deserialize<string[]>(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<string[]>(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<string[]>(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);
- }
- }
-
- /// <summary>
- /// Starts or resume playing audio file
- /// </summary>
- public void startPlayingAudio(string options)
- {
- string callbackId = this.CurrentCommandCallbackId;
- try
- {
- MediaOptions mediaOptions;
- try
- {
- string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(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);
- }
- }
-
-
- /// <summary>
- /// Seeks to a location
- /// </summary>
- public void seekToAudio(string options)
- {
- string callbackId = this.CurrentCommandCallbackId;
- try
- {
- MediaOptions mediaOptions;
-
- try
- {
- string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(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);
- }
- }
-
- /// <summary>
- /// Pauses playing
- /// </summary>
- public void pausePlayingAudio(string options)
- {
- string callbackId = this.CurrentCommandCallbackId;
- try
- {
- string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(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);
- }
-
-
- }
-
-
- /// <summary>
- /// Stops playing the audio file
- /// </summary>
- public void stopPlayingAudio(String options)
- {
- string callbackId = this.CurrentCommandCallbackId;
- try
- {
- string[] optionsStrings = JSON.JsonHelper.Deserialize<string[]>(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);
- }
- }
-
- /// <summary>
- /// Gets current position of playback
- /// </summary>
- public void getCurrentPositionAudio(string options)
- {
- string callbackId = this.CurrentCommandCallbackId;
- try
- {
- string[] optionsStrings = JSON.JsonHelper.Deserialize<string[]>(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;
- }
- }
-
-
- /// <summary>
- /// Gets the duration of the audio file
- /// </summary>
-
- [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<string[]>(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);
- }
- }
- }
-}