[Cordova] Media plugin, create and play method implementation
authorLukasz Foniok <l.foniok@samsung.com>
Tue, 20 Oct 2015 16:54:34 +0000 (18:54 +0200)
committerLukasz Foniok <l.foniok@samsung.com>
Wed, 21 Oct 2015 15:10:41 +0000 (17:10 +0200)
Change-Id: Ibe9426f4655dbd546c6961879169efe5a61b9a70
Signed-off-by: Lukasz Foniok <l.foniok@samsung.com>
src/media/cordova_media_api.js

index 9f73a64c7619d7e92d92f91983e7fa0135c23c07..c0d7704993a7e9fac5749ec9b6413f42ebfa325c 100755 (executable)
 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);
+    }
+
+};
+
 Media.prototype.getCurrentPosition = function(mediaSuccess, mediaError){}
 
 Media.prototype.getDuration = function(){};
 
 Media.prototype.pause = function(){};
 
-Media.prototype.play = 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(){};