[Media] Stubs for media adapted to cordova plugin model.
authorPiotr Czaja <p.czaja@samsung.com>
Mon, 2 Nov 2015 09:44:31 +0000 (10:44 +0100)
committerLukasz Foniok <l.foniok@samsung.com>
Wed, 4 Nov 2015 10:26:16 +0000 (11:26 +0100)
Change-Id: I6101a021ecee61ab76685b6d199f7019b01d7cc8
Signed-off-by: root <p.czaja@samsung.com>
src/cordova-api.gyp
src/lib/cordova_plugins.js
src/lib/plugins/cordova-plugin-media/www/Media.js [new file with mode: 0644]
src/lib/plugins/cordova-plugin-media/www/MediaError.js [new file with mode: 0644]
src/media/cordova_media_api.js
src/media/cordova_media_extension.cc

index 1f637dac0fdde8c8baa1e5e71a36eaca66f037fe..24ed756435fcab1f5fae52d6a15299e16dc13ee2 100644 (file)
@@ -15,6 +15,7 @@
         'globalization/cordova_globalization.gyp:*',
         'networkinformation/cordova_networkinformation.gyp:*',
         'filetransfer/cordova_filetransfer.gyp:*',
+        'media/cordova_media.gyp:*',
       ],
     },
   ], # end targets
index 441eb7264d5caf4783101e250b19cf630eddb86b..e3baec61859ce9aa33d28acbcd8b954bcdfefee0 100644 (file)
@@ -208,6 +208,20 @@ module.exports = [
         "clobbers": [
             "navigator.globalization"
         ]
+    },
+    {
+        "file": "plugins/cordova-plugin-media/www/MediaError.js",
+        "id": "cordova-plugin-media.MediaError",
+        "clobbers": [
+            "window.MediaError"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-media/www/Media.js",
+        "id": "cordova-plugin-media.Media",
+        "clobbers": [
+            "window.Media"
+        ]
     }
 ];
 module.exports.metadata =
@@ -220,6 +234,7 @@ module.exports.metadata =
     "cordova-plugin-file-transfer": "1.3.0",
     "cordova-plugin-network-information": "1.0.1",
     "cordova-plugin-globalization": "1.0.1",
+    "cordova-plugin-media": "1.0.1",
 }
 // BOTTOM OF METADATA
 });
diff --git a/src/lib/plugins/cordova-plugin-media/www/Media.js b/src/lib/plugins/cordova-plugin-media/www/Media.js
new file mode 100644 (file)
index 0000000..3378253
--- /dev/null
@@ -0,0 +1,231 @@
+cordova.define("cordova-plugin-media.Media", function(require, exports, module) { /*
+/*
+ *
+ * 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 argscheck = require('cordova/argscheck'),
+    utils = require('cordova/utils'),
+    exec = require('cordova/exec');
+
+var mediaObjects = {};
+
+/**
+ * This class provides access to the device media, interfaces to both sound and video
+ *
+ * @constructor
+ * @param src                   The file name or url to play
+ * @param successCallback       The callback to be called when the file is done playing or recording.
+ *                                  successCallback()
+ * @param errorCallback         The callback to be called if there is an error.
+ *                                  errorCallback(int errorCode) - OPTIONAL
+ * @param statusCallback        The callback to be called when media status has changed.
+ *                                  statusCallback(int statusCode) - OPTIONAL
+ */
+var Media = function(src, successCallback, errorCallback, statusCallback) {
+    argscheck.checkArgs('sFFF', 'Media', arguments);
+    this.id = utils.createUUID();
+    mediaObjects[this.id] = this;
+    this.src = src;
+    this.successCallback = successCallback;
+    this.errorCallback = errorCallback;
+    this.statusCallback = statusCallback;
+    this._duration = -1;
+    this._position = -1;
+    exec(null, this.errorCallback, "Media", "create", [this.id, this.src]);
+};
+
+// Media messages
+Media.MEDIA_STATE = 1;
+Media.MEDIA_DURATION = 2;
+Media.MEDIA_POSITION = 3;
+Media.MEDIA_ERROR = 9;
+
+// Media states
+Media.MEDIA_NONE = 0;
+Media.MEDIA_STARTING = 1;
+Media.MEDIA_RUNNING = 2;
+Media.MEDIA_PAUSED = 3;
+Media.MEDIA_STOPPED = 4;
+Media.MEDIA_MSG = ["None", "Starting", "Running", "Paused", "Stopped"];
+
+// "static" function to return existing objs.
+Media.get = function(id) {
+    return mediaObjects[id];
+};
+
+/**
+ * Start or resume playing audio file.
+ */
+Media.prototype.play = function(options) {
+    exec(null, null, "Media", "startPlayingAudio", [this.id, this.src, options]);
+};
+
+/**
+ * Stop playing audio file.
+ */
+Media.prototype.stop = function() {
+    var me = this;
+    exec(function() {
+        me._position = 0;
+    }, this.errorCallback, "Media", "stopPlayingAudio", [this.id]);
+};
+
+/**
+ * Seek or jump to a new time in the track..
+ */
+Media.prototype.seekTo = function(milliseconds) {
+    var me = this;
+    exec(function(p) {
+        me._position = p;
+    }, this.errorCallback, "Media", "seekToAudio", [this.id, milliseconds]);
+};
+
+/**
+ * Pause playing audio file.
+ */
+Media.prototype.pause = function() {
+    exec(null, this.errorCallback, "Media", "pausePlayingAudio", [this.id]);
+};
+
+/**
+ * Get duration of an audio file.
+ * The duration is only set for audio that is playing, paused or stopped.
+ *
+ * @return      duration or -1 if not known.
+ */
+Media.prototype.getDuration = function() {
+    return this._duration;
+};
+
+/**
+ * Get position of audio.
+ */
+Media.prototype.getCurrentPosition = function(success, fail) {
+    var me = this;
+    exec(function(p) {
+        me._position = p;
+        success(p);
+    }, fail, "Media", "getCurrentPositionAudio", [this.id]);
+};
+
+/**
+ * Start recording audio file.
+ */
+Media.prototype.startRecord = function() {
+    exec(null, this.errorCallback, "Media", "startRecordingAudio", [this.id, this.src]);
+};
+
+/**
+ * Stop recording audio file.
+ */
+Media.prototype.stopRecord = function() {
+    exec(null, this.errorCallback, "Media", "stopRecordingAudio", [this.id]);
+};
+
+/**
+ * Release the resources.
+ */
+Media.prototype.release = function() {
+    exec(null, this.errorCallback, "Media", "release", [this.id]);
+};
+
+/**
+ * Adjust the volume.
+ */
+Media.prototype.setVolume = function(volume) {
+    exec(null, null, "Media", "setVolume", [this.id, volume]);
+};
+
+/**
+ * Adjust the playback rate.
+ */
+Media.prototype.setRate = function(rate) {
+    if (cordova.platformId === 'ios'){
+        exec(null, null, "Media", "setRate", [this.id, rate]);
+    } else {
+        console.warn('media.setRate method is currently not supported for', cordova.platformId, 'platform.')
+    }
+};
+
+
+/**
+ * Audio has status update.
+ * PRIVATE
+ *
+ * @param id            The media object id (string)
+ * @param msgType       The 'type' of update this is
+ * @param value         Use of value is determined by the msgType
+ */
+Media.onStatus = function(id, msgType, value) {
+
+    var media = mediaObjects[id];
+
+    if(media) {
+        switch(msgType) {
+            case Media.MEDIA_STATE :
+                media.statusCallback && media.statusCallback(value);
+                if(value == Media.MEDIA_STOPPED) {
+                    media.successCallback && media.successCallback();
+                }
+                break;
+            case Media.MEDIA_DURATION :
+                media._duration = value;
+                break;
+            case Media.MEDIA_ERROR :
+                media.errorCallback && media.errorCallback(value);
+                break;
+            case Media.MEDIA_POSITION :
+                media._position = Number(value);
+                break;
+            default :
+                console.error && console.error("Unhandled Media.onStatus :: " + msgType);
+                break;
+        }
+    }
+    else {
+         console.error && console.error("Received Media.onStatus callback for unknown media :: " + id);
+    }
+
+};
+
+module.exports = Media;
+
+function onMessageFromNative(msg) {
+    if (msg.action == 'status') {
+        Media.onStatus(msg.status.id, msg.status.msgType, msg.status.value);
+    } else {
+        throw new Error('Unknown media action' + msg.action);
+    }
+}
+
+if (cordova.platformId === 'android' || cordova.platformId === 'amazon-fireos' || cordova.platformId === 'windowsphone') {
+
+    var channel = require('cordova/channel');
+
+    channel.createSticky('onMediaPluginReady');
+    channel.waitForInitialization('onMediaPluginReady');
+
+    channel.onCordovaReady.subscribe(function() {
+        exec(onMessageFromNative, undefined, 'Media', 'messageChannel', []);
+        channel.initializationComplete('onMediaPluginReady');
+    });
+}
+
+});
diff --git a/src/lib/plugins/cordova-plugin-media/www/MediaError.js b/src/lib/plugins/cordova-plugin-media/www/MediaError.js
new file mode 100644 (file)
index 0000000..79b65f6
--- /dev/null
@@ -0,0 +1,58 @@
+cordova.define("cordova-plugin-media.MediaError", function(require, exports, module) { /*
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * This class contains information about any Media errors.
+*/
+/*
+ According to :: http://dev.w3.org/html5/spec-author-view/video.html#mediaerror
+ We should never be creating these objects, we should just implement the interface
+ which has 1 property for an instance, 'code'
+
+ instead of doing :
+    errorCallbackFunction( new MediaError(3,'msg') );
+we should simply use a literal :
+    errorCallbackFunction( {'code':3} );
+ */
+
+
+  var _MediaError = window.MediaError;
+
+
+if(!_MediaError) {
+    window.MediaError = _MediaError = function(code, msg) {
+        this.code = (typeof code != 'undefined') ? code : null;
+        this.message = msg || ""; // message is NON-standard! do not use!
+    };
+}
+
+_MediaError.MEDIA_ERR_NONE_ACTIVE    = _MediaError.MEDIA_ERR_NONE_ACTIVE    || 0;
+_MediaError.MEDIA_ERR_ABORTED        = _MediaError.MEDIA_ERR_ABORTED        || 1;
+_MediaError.MEDIA_ERR_NETWORK        = _MediaError.MEDIA_ERR_NETWORK        || 2;
+_MediaError.MEDIA_ERR_DECODE         = _MediaError.MEDIA_ERR_DECODE         || 3;
+_MediaError.MEDIA_ERR_NONE_SUPPORTED = _MediaError.MEDIA_ERR_NONE_SUPPORTED || 4;
+// TODO: MediaError.MEDIA_ERR_NONE_SUPPORTED is legacy, the W3 spec now defines it as below.
+// as defined by http://dev.w3.org/html5/spec-author-view/video.html#error-codes
+_MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = _MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED || 4;
+
+module.exports = _MediaError;
+});
index f538820dacddb57983bb1c716be391c99baceef7..c9fa2f9176bd8022983b27cbeafb8b1b71b3f409 100755 (executable)
  *    limitations under the License.
  */
 
-var _global = window || global || {};
-var _document = document || {};
-
-/**
- * This class contains information about any Media errors
-*/
-/*
- According to :: http://dev.w3.org/html5/spec-author-view/video.html#mediaerror
- We should never be creating these objects, we should just implement the interface
- which has 1 property for an instance, 'code'
-
- instead of doing :
-    errorCallbackFunction( new MediaError(3,'msg') );
-we should simply use a literal :
-    errorCallbackFunction( {'code':3} );
- */
-
- var _MediaError = window.MediaError;
-
-
-if(!_MediaError) {
-    window.MediaError = _MediaError = function(code, msg) {
-        this.code = (typeof code != 'undefined') ? code : null;
-        this.message = msg || ""; // message is NON-standard! do not use!
-    };
-}
-
-_MediaError.MEDIA_ERR_NONE_ACTIVE    = _MediaError.MEDIA_ERR_NONE_ACTIVE    || 0;
-_MediaError.MEDIA_ERR_ABORTED        = _MediaError.MEDIA_ERR_ABORTED        || 1;
-_MediaError.MEDIA_ERR_NETWORK        = _MediaError.MEDIA_ERR_NETWORK        || 2;
-_MediaError.MEDIA_ERR_DECODE         = _MediaError.MEDIA_ERR_DECODE         || 3;
-_MediaError.MEDIA_ERR_NONE_SUPPORTED = _MediaError.MEDIA_ERR_NONE_SUPPORTED || 4;
-// TODO: MediaError.MEDIA_ERR_NONE_SUPPORTED is legacy, the W3 spec now defines it as below.
-// as defined by http://dev.w3.org/html5/spec-author-view/video.html#error-codes
-_MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = _MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED || 4;
-
-MediaError = _MediaError;
-
-var audioObjects = {};
-var mediaObjects = {};
-
-
-
-function create(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();
-    };
-}
-
-function Media(src, mediaSuccess, mediaError, mediaStatus) {
-    this.src = src;
-    this.id = utils.createUUID();
-    this.mediaSuccess = mediaSuccess;
-    this.mediaError = mediaError;
-    this.mediaStatus = mediaStatus;
-    this._duration = -1;
-    this._position = -1;
-    mediaObjects[this.id] = this;
-    create([this.id, this.src])
-}
-
-/**
- * Audio has status update.
- * PRIVATE
- *
- * @param id            The media object id (string)
- * @param msgType       The 'type' of update this is
- * @param value         Use of value is determined by the msgType
- */
-Media.onStatus = function(id, msgType, value) {
-
-    var media = mediaObjects[id];
-
-    if(media) {
-        switch(msgType) {
-            case Media.MEDIA_STATE :
-                media.statusCallback && media.statusCallback(value);
-                if(value == Media.MEDIA_STOPPED) {
-                    media.successCallback && media.successCallback();
-                }
-                break;
-            case Media.MEDIA_DURATION :
-                media._duration = value;
-                break;
-            case Media.MEDIA_ERROR :
-                media.errorCallback && media.errorCallback(value);
-                break;
-            case Media.MEDIA_POSITION :
-                media._position = Number(value);
-                break;
-            default :
-                console.error && console.error("Unhandled Media.onStatus :: " + msgType);
-                break;
-        }
-    }
-    else {
-         console.error && console.error("Received Media.onStatus callback for unknown media :: " + id);
-    }
-
+// TODO: remove when added to public cordova repository -> begin
+var plugin_name = 'cordova-plugin-media.tizen.Media';
+
+cordova.define(plugin_name, function(require, exports, module) {
+// TODO: remove -> end
+
+  exports = {
+  create: function(successCallback, errorCallback, args) {
+    console.log("Media create stub");
+  },
+  startPlayingAudio: function(successCallback, errorCallback, args) {},
+  stopPlayingAudio: function(successCallback, errorCallback, args) {},
+  seekToAudio: function(successCallback, errorCallback, args) {},
+  pausePlayingAudio: function(successCallback, errorCallback, args) {},
+  getCurrentPositionAudio: function(successCallback, errorCallback, args) {},
+  startRecordingAudio: function(successCallback, errorCallback, args) {},
+  stopRecordingAudio: function(successCallback, errorCallback, args) {},
+  release: function(successCallback, errorCallback, args) {},
+  setVolume: function(successCallback, errorCallback, args) {},
+  setRate: function(successCallback, errorCallback, args) {},
+  messageChannel: function(successCallback, errorCallback, args) {}
 };
+require("cordova/exec/proxy").add("Media", exports);
 
-Media.prototype.getCurrentPosition = function(mediaSuccess, mediaError){}
-
-Media.prototype.getDuration = function(){};
-
-Media.prototype.pause = function(){};
-
-Media.prototype.play = function(){
-    var id = this.id, src = this.src;
-
-    console.log("media::startPlayingAudio() - id =" + id + ", src =" + src);
-
-    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();
-    
-};
-
-Media.prototype.release = function(){};
-
-Media.prototype.seekTo = function(miliseconds){};
-
-Media.prototype.setVolume = function(volume){};
-
-Media.prototype.startRecord = function(){};
-
-Media.prototype.stop = function(){};
-
-Media.prototype.stopRecord = function(){};
-
-_global.Media = Media;
+console.log('Loaded cordova.media API');
 
-console.log('Loaded cordova.device API');
+//TODO: remove when added to public cordova repository -> begin
+});
 
 exports = function(require) {
+  // this plugin is not loaded via cordova_plugins.js, we need to manually add
+  // it to module mapper
+  var mm = require('cordova/modulemapper');
+  mm.runs(plugin_name);
 };
index 7ffebf9cd0b32b2b9565fd0f2250e16f116fc8a2..6565afc016b22707b44d3c6791267bb47ec16060 100755 (executable)
@@ -14,7 +14,7 @@
  *    limitations under the License.
  */
 
-#include "cordova/media/cordova_media_extension.h"
+#include "media/cordova_media_extension.h"
 
 // This will be generated from cordova_media_api.js
 extern const char kSource_cordova_media_api[];