summaryrefslogtreecommitdiff
path: root/jaws/src/extras/audio.js
diff options
context:
space:
mode:
Diffstat (limited to 'jaws/src/extras/audio.js')
-rwxr-xr-xjaws/src/extras/audio.js351
1 files changed, 351 insertions, 0 deletions
diff --git a/jaws/src/extras/audio.js b/jaws/src/extras/audio.js
new file mode 100755
index 0000000..ccb1065
--- /dev/null
+++ b/jaws/src/extras/audio.js
@@ -0,0 +1,351 @@
+/**
+ * @fileOverview A jaws.Audio object that detects and loads supported filetypes
+ *
+ * The jaws.Audio object uses jaws.assets to determine if a particular
+ * reported MIME audio filetype can be played within the current enviroment.
+ *
+ * Note: If loading fails at any point or no supported types were found,
+ * the 'audio' property is set to null.
+ *
+ * @see jaws.assets.file_type
+ * @see jaws.assets.can_play
+ *
+ * @class jaws.Audio
+ * @property {array|string|Audio|null} audio A string or array of file locations initally;
+ * replaced with an Audio object if loading was successful
+ *
+ * @example
+ * var audio = new jaws.Audio({audio: ["file.mp3", "file.ogg"], volume: 1.0});
+ *
+ * audio.play() //Assuming either MP3 or OGG is supported
+ *
+ * //Because play(), stop(), and other audio functions will log an error
+ * // if 'audio' is not an Audio object, its load status can be checked too.
+ *
+ * if(audio.isLoaded()) {
+ * audio.play();
+ * }
+ *
+ */
+var jaws = (function(jaws) {
+
+ /**
+ * jaws.Audio object
+ * @constructor
+ * @param {object} options Object-literal of constructor properties
+ * @param {bool} [options.loop] Whether to initially loop the playing or not
+ * @param {bool} [options.mute] Whether to initially mute the audio or not
+ * @param {bool} [options.pause] Whether to initially pause the audio or not
+ * @param {bool} [options.autoplay] Whether to start playing after loading
+ * @param {int} [options.volume] Initial audio volume, between 0.1 and 1.0
+ * @param {function} [options.onend] Initial callback on "end" event for audio
+ * @param {function} [options.onplay] Initial callback on "play" event for audio
+ * @param {function} [options.onpause] Initial callback on "pause" event for audio
+ * @see jaws.audio.set()
+ */
+ jaws.Audio = function Audio(options) {
+ if (!(this instanceof arguments.callee))
+ return new arguments.callee(options);
+
+ if (typeof Audio !== "undefined") {
+ this.set(options);
+ } else {
+ jaws.log.error("jaws.Audio (constructor): 'Audio' object does not exist.");
+ this.audio = null;
+ }
+ };
+
+ /**
+ * The default properties and their values
+ * @type {object}
+ */
+ jaws.Audio.prototype.default_options = {
+ audio: null,
+ autoplay: false,
+ loop: false,
+ volume: 0,
+ onend: null,
+ onplay: null,
+ onpause: null,
+ _constructor: null
+ };
+
+ /**
+ * Compares default_options to the constructor options and loads an audio resource if able
+ * @param {object} options Object-literal of constructor properties
+ * @this {jaws.Audio}
+ * @returns {object} The 'this' scope of the calling instance of an jaws.Audio object
+ */
+ jaws.Audio.prototype.set = function(options) {
+
+ jaws.parseOptions(this, options, this.default_options);
+
+ if (this.audio) {
+ if (jaws.isString(this.audio)) {
+ var type = jaws.assets.getPostfix(this.audio);
+ if (jaws.assets.file_type[type] && jaws.assets.can_play[type]) {
+ this.setAudio(this.audio);
+ } else {
+ jaws.log.warn("jaws.Audio.set: Unknown or unplayable MIME filetype.");
+ this.audio = null;
+ }
+ } else if (jaws.isArray(this.audio)) {
+ for (var i = 0; i < this.audio.length; i++) {
+ if (jaws.isString(this.audio[i])) {
+ var type = jaws.assets.getPostfix(this.audio[i]);
+ if (jaws.assets.file_type[type] && jaws.assets.can_play[type]) {
+ this.setAudio(this.audio[i]);
+ break;
+ }
+ }
+ }
+
+ if (!(this.audio instanceof Audio)) {
+ jaws.log.warn("jaws.Audio.set: No known or playable MIME filetypes were found.");
+ this.audio = null;
+ }
+
+ } else {
+ jaws.log.error("jaws.Audio.set: Passed in 'audio' property is neither a String nor Array");
+ this.audio = null;
+ }
+ }
+ return this;
+ };
+
+ /**
+ * Loads a reference from the jaws.assets cache or requests that an Audio resource URL be loaded
+ * @param {type} value
+ * @this {jaws.Audio}
+ * @returns {object} The 'this' scope of the calling instance of an jaws.Audio object
+ */
+ jaws.Audio.prototype.setAudio = function(value) {
+ var self = this;
+ if (jaws.assets.isLoaded(value)) {
+ var audio = jaws.assets.get(value);
+ if (audio instanceof Audio) {
+ this.audio = audio;
+
+ if (this.volume >= 0 && this.volume <= 1.0 && jaws.isNumber(this.volume))
+ this.audio.volume = this.volume;
+
+ if (this.loop)
+ this.audio.loop = this.loop;
+
+ if (this.onend && jaws.isFunction(this.onend)) {
+ this.audio.addEventListener('end', this.onend);
+ }
+
+ if (this.onplay && jaws.isFunction(this.onplay)) {
+ this.audio.addEventListener('play', this.onplay);
+ }
+
+ if (this.onpause && jaws.isFunction(this.onplay)) {
+ this.audio.addEventListener('pause', this.onpause);
+ }
+
+ if (this.autoplay)
+ this.audio.autoplay = this.autoplay;
+
+ } else {
+ this.audio = null;
+ }
+ } else {
+ jaws.log.warn("jaws.Audio.setAudio: Audio '" + value + "' not preloaded with jaws.assets.add().");
+ jaws.assets.load(value, function() {
+ var audio = jaws.assets.get(value);
+ if (audio instanceof Audio) {
+ self.audio = audio;
+
+ if (self.volume >= 0 && self.volume <= 1.0 && jaws.isNumber(self.volume))
+ self.audio.volume = self.volume;
+
+ if (self.loop)
+ self.audio.loop = self.loop;
+
+ if (self.hasOwnProperty("onend") && jaws.isFunction(self.onend)) {
+ self.audio.addEventListener('end', self.onend);
+ }
+
+ if (self.hasOwnProperty("onplay") && jaws.isFunction(self.onplay)) {
+ self.audio.addEventListener('play', self.onplay);
+ }
+
+ if (self.hasOwnProperty("onpause") && jaws.isFunction(self.onplay)) {
+ self.audio.addEventListener('pause', self.onpause);
+ }
+
+ if (self.autoplay)
+ self.audio.autoplay = self.autoplay;
+
+ } else {
+ self.audio = null;
+ }
+ }, function() {
+ jaws.log.error("jaws.Audio.setAudio: Could not load Audio resource URL " + value);
+ self.audio = null;
+ });
+ }
+ return this;
+ };
+
+ /**
+ * Plays audio
+ * @this {jaws.Audio}
+ */
+ jaws.Audio.prototype.play = function() {
+ if (this.audio instanceof Audio) {
+ this.audio.play();
+ } else {
+ jaws.log.error("jaws.Audio.play: Either 'audio' was loaded incorrectly or does not exist");
+ }
+ };
+
+ /**
+ * Stops audio
+ * @this {jaws.Audio}
+ */
+ jaws.Audio.prototype.stop = function() {
+ if (this.audio instanceof Audio) {
+ this.audio.pause();
+ this.audio.currentTime = 0;
+ } else {
+ jaws.log.error("jaws.Audio.stop: Either 'audio' was loaded incorrectly or does not exist");
+ }
+ };
+
+ /**
+ * Pauses audio
+ * @this {jaws.Audio}
+ */
+ jaws.Audio.prototype.pause = function() {
+ if (this.audio instanceof Audio) {
+ this.audio.pause();
+ } else {
+ jaws.log.error("jaws.Audio.pause: Either 'audio' was loaded incorrectly or does not exist");
+ }
+ };
+
+ /**
+ * Mutes the audio
+ * @this {jaws.Audio}
+ */
+ jaws.Audio.prototype.mute = function() {
+ if (this.audio instanceof Audio) {
+ this.audio.mute = true;
+ } else {
+ jaws.log.error("jaws.Audio.mute: Either 'audio' was loaded incorrectly or does not exist");
+ }
+ };
+
+ /**
+ * Unmute the audio
+ * @this {jaws.Audio}
+ */
+ jaws.Audio.prototype.unmute = function() {
+ if (this.audio instanceof Audio) {
+ this.audio.mute = false;
+ } else {
+ jaws.log.error("jaws.Audio.unmute: Either 'audio' was loaded incorrectly or does not exist");
+ }
+ };
+
+ /**
+ * Seeks to a position in audio
+ * @param {type} value
+ * @this {jaws.Audio}
+ */
+ jaws.Audio.prototype.seekTo = function(value) {
+ if (this.audio instanceof Audio) {
+ if (jaws.isNumber(value)) {
+ if (value <= this.audio.duration) {
+ this.audio.currentTime = value;
+ } else {
+ this.audio.currentTime = this.audio.duration;
+ }
+ }
+ } else {
+ jaws.log.warn("jaws.Audio.seekTo: Either 'audio' was loaded incorrectly or does not exist");
+ }
+ };
+
+ /**
+ * Sets the volume of the audio
+ * @param {type} value The new volume within the range 0.0 to 1.0
+ * @this {jaws.Audio}
+ */
+ jaws.Audio.prototype.setVolume = function(value) {
+ if (this.audio instanceof Audio) {
+ if (jaws.isNumber(value) && value <= 1.0 && value >= 0) {
+ this.audio.volume = value;
+ }
+ } else {
+ jaws.log.warn("jaws.Audio: jaws.setVolume: Either 'audio' was loaded incorrectly or does not exist");
+ }
+ };
+
+ /**
+ * Returns if 'audio' is actually an Audio object
+ */
+ jaws.Audio.prototype.isLoaded = function() {
+ return (this.audio instanceof Audio);
+ };
+
+ /**
+ * Returns a String containing value properties
+ * @this {jaws.Audio}
+ * @returns {String}
+ */
+ jaws.Audio.prototype.toString = function() {
+ var properties = "[Audio ";
+ if (this.audio instanceof Audio) {
+ properties += this.audio.src + ", ";
+ properties += this.audio.currentTime + ", ";
+ properties += this.audio.duration + ", ";
+ properties += this.audio.volume + " ]";
+ } else {
+ properties += null + " ]";
+ }
+ return properties;
+ };
+
+ /**
+ * Returns an object created with values from 'this' properties
+ * @this {jaws.Audio}
+ * @returns {object}
+ */
+ jaws.Audio.prototype.attributes = function() {
+ var object = this.options;
+ object["_constructor"] = this._constructor || "jaws.Audio";
+
+ if (this.audio instanceof Audio) {
+ object["audio"] = this.audio.src;
+ object["loop"] = this.loop;
+ object["muted"] = this.audio.muted;
+ object["volume"] = this.audio.volume;
+ } else {
+ object["audio"] = null;
+ }
+
+ if (this.hasOwnProperty("autoplay"))
+ object["autoplay"] = this.autoplay;
+
+ return object;
+ };
+
+ /**
+ * Return the properties of the current object as a JSON-encoded string
+ * @this {jaws.Audio}
+ * @returns {string} The properties of the jaws.Audio object as a JSON-encoded string
+ */
+ jaws.Audio.prototype.toJSON = function() {
+ return JSON.stringify(this.attributes());
+ };
+
+ return jaws;
+})(jaws || {});
+
+// Support CommonJS require()
+if (typeof module !== "undefined" && ('exports' in module)) {
+ module.exports = jaws.Audio;
+} \ No newline at end of file