blob: 80fbf47c20edc27655326b4dbae7b18fe86a795b [file] [log] [blame]
/*
*
* 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 cordova */
var argscheck = require('cordova/argscheck');
var utils = require('cordova/utils');
var 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]);
};
/**
* Pause recording audio file.
*/
Media.prototype.pauseRecord = function () {
exec(null, this.errorCallback, 'Media', 'pauseRecordingAudio', [this.id]);
};
/**
* Resume recording audio file.
*/
Media.prototype.resumeRecord = function () {
exec(null, this.errorCallback, 'Media', 'resumeRecordingAudio', [this.id]);
};
/**
* Release the resources.
*/
Media.prototype.release = function () {
var me = this;
exec(
function () {
delete mediaObjects[me.id];
},
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.');
}
};
/**
* Get amplitude of audio.
*/
Media.prototype.getCurrentAmplitude = function (success, fail) {
exec(
function (p) {
success(p);
},
fail,
'Media',
'getCurrentAmplitudeAudio',
[this.id]
);
};
/**
* 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:
if (media.statusCallback) {
media.statusCallback(value);
}
if (value === Media.MEDIA_STOPPED) {
if (media.successCallback) {
media.successCallback();
}
}
break;
case Media.MEDIA_DURATION:
media._duration = value;
break;
case Media.MEDIA_ERROR:
if (media.errorCallback) {
media.errorCallback(value);
}
break;
case Media.MEDIA_POSITION:
media._position = Number(value);
break;
default:
if (console.error) {
console.error('Unhandled Media.onStatus :: ' + msgType);
}
break;
}
} else if (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');
});
}