snappymail/vendors/buzz/buzz.js
RainLoop Team aa84077ac4 Sound notification
Additional code refactoring
2015-01-27 01:06:00 +04:00

719 lines
No EOL
25 KiB
JavaScript

// ----------------------------------------------------------------------------
// Buzz, a Javascript HTML5 Audio library
// v1.1.8 - Built 2015-01-12 11:08
// Licensed under the MIT license.
// http://buzz.jaysalvat.com/
// ----------------------------------------------------------------------------
// Copyright (C) 2010-2015 Jay Salvat
// http://jaysalvat.com/
// ----------------------------------------------------------------------------
(function(context, factory) {
"use strict";
if (typeof module !== "undefined" && module.exports) {
module.exports = factory();
} else if (typeof define === "function" && define.amd) {
define([], factory);
} else {
context.buzz = factory();
}
})(this, function() {
"use strict";
var AudioContext = window.AudioContext || window.webkitAudioContext;
var buzz = {
audioCtx: window.AudioContext ? new AudioContext() : null,
defaults: {
autoplay: false,
duration: 5e3,
formats: [],
loop: false,
placeholder: "--",
preload: "metadata",
volume: 80,
webAudioApi: false,
document: window.document
},
types: {
mp3: "audio/mpeg",
ogg: "audio/ogg",
wav: "audio/wav",
aac: "audio/aac",
m4a: "audio/x-m4a"
},
sounds: [],
el: document.createElement("audio"),
sound: function(src, options) {
options = options || {};
var doc = options.document || buzz.defaults.document;
var pid = 0, events = [], eventsOnce = {}, supported = buzz.isSupported();
this.load = function() {
if (!supported) {
return this;
}
this.sound.load();
return this;
};
this.play = function() {
if (!supported) {
return this;
}
this.sound.play();
return this;
};
this.togglePlay = function() {
if (!supported) {
return this;
}
if (this.sound.paused) {
this.sound.play();
} else {
this.sound.pause();
}
return this;
};
this.pause = function() {
if (!supported) {
return this;
}
this.sound.pause();
return this;
};
this.isPaused = function() {
if (!supported) {
return null;
}
return this.sound.paused;
};
this.stop = function() {
if (!supported) {
return this;
}
this.setTime(0);
this.sound.pause();
return this;
};
this.isEnded = function() {
if (!supported) {
return null;
}
return this.sound.ended;
};
this.loop = function() {
if (!supported) {
return this;
}
this.sound.loop = "loop";
this.bind("ended.buzzloop", function() {
this.currentTime = 0;
this.play();
});
return this;
};
this.unloop = function() {
if (!supported) {
return this;
}
this.sound.removeAttribute("loop");
this.unbind("ended.buzzloop");
return this;
};
this.mute = function() {
if (!supported) {
return this;
}
this.sound.muted = true;
return this;
};
this.unmute = function() {
if (!supported) {
return this;
}
this.sound.muted = false;
return this;
};
this.toggleMute = function() {
if (!supported) {
return this;
}
this.sound.muted = !this.sound.muted;
return this;
};
this.isMuted = function() {
if (!supported) {
return null;
}
return this.sound.muted;
};
this.setVolume = function(volume) {
if (!supported) {
return this;
}
if (volume < 0) {
volume = 0;
}
if (volume > 100) {
volume = 100;
}
this.volume = volume;
this.sound.volume = volume / 100;
return this;
};
this.getVolume = function() {
if (!supported) {
return this;
}
return this.volume;
};
this.increaseVolume = function(value) {
return this.setVolume(this.volume + (value || 1));
};
this.decreaseVolume = function(value) {
return this.setVolume(this.volume - (value || 1));
};
this.setTime = function(time) {
if (!supported) {
return this;
}
var set = true;
this.whenReady(function() {
if (set === true) {
set = false;
this.sound.currentTime = time;
}
});
return this;
};
this.getTime = function() {
if (!supported) {
return null;
}
var time = Math.round(this.sound.currentTime * 100) / 100;
return isNaN(time) ? buzz.defaults.placeholder : time;
};
this.setPercent = function(percent) {
if (!supported) {
return this;
}
return this.setTime(buzz.fromPercent(percent, this.sound.duration));
};
this.getPercent = function() {
if (!supported) {
return null;
}
var percent = Math.round(buzz.toPercent(this.sound.currentTime, this.sound.duration));
return isNaN(percent) ? buzz.defaults.placeholder : percent;
};
this.setSpeed = function(duration) {
if (!supported) {
return this;
}
this.sound.playbackRate = duration;
return this;
};
this.getSpeed = function() {
if (!supported) {
return null;
}
return this.sound.playbackRate;
};
this.getDuration = function() {
if (!supported) {
return null;
}
var duration = Math.round(this.sound.duration * 100) / 100;
return isNaN(duration) ? buzz.defaults.placeholder : duration;
};
this.getPlayed = function() {
if (!supported) {
return null;
}
return timerangeToArray(this.sound.played);
};
this.getBuffered = function() {
if (!supported) {
return null;
}
return timerangeToArray(this.sound.buffered);
};
this.getSeekable = function() {
if (!supported) {
return null;
}
return timerangeToArray(this.sound.seekable);
};
this.getErrorCode = function() {
if (supported && this.sound.error) {
return this.sound.error.code;
}
return 0;
};
this.getErrorMessage = function() {
if (!supported) {
return null;
}
switch (this.getErrorCode()) {
case 1:
return "MEDIA_ERR_ABORTED";
case 2:
return "MEDIA_ERR_NETWORK";
case 3:
return "MEDIA_ERR_DECODE";
case 4:
return "MEDIA_ERR_SRC_NOT_SUPPORTED";
default:
return null;
}
};
this.getStateCode = function() {
if (!supported) {
return null;
}
return this.sound.readyState;
};
this.getStateMessage = function() {
if (!supported) {
return null;
}
switch (this.getStateCode()) {
case 0:
return "HAVE_NOTHING";
case 1:
return "HAVE_METADATA";
case 2:
return "HAVE_CURRENT_DATA";
case 3:
return "HAVE_FUTURE_DATA";
case 4:
return "HAVE_ENOUGH_DATA";
default:
return null;
}
};
this.getNetworkStateCode = function() {
if (!supported) {
return null;
}
return this.sound.networkState;
};
this.getNetworkStateMessage = function() {
if (!supported) {
return null;
}
switch (this.getNetworkStateCode()) {
case 0:
return "NETWORK_EMPTY";
case 1:
return "NETWORK_IDLE";
case 2:
return "NETWORK_LOADING";
case 3:
return "NETWORK_NO_SOURCE";
default:
return null;
}
};
this.set = function(key, value) {
if (!supported) {
return this;
}
this.sound[key] = value;
return this;
};
this.get = function(key) {
if (!supported) {
return null;
}
return key ? this.sound[key] : this.sound;
};
this.bind = function(types, func) {
if (!supported) {
return this;
}
types = types.split(" ");
var self = this, efunc = function(e) {
func.call(self, e);
};
for (var t = 0; t < types.length; t++) {
var type = types[t], idx = type;
type = idx.split(".")[0];
events.push({
idx: idx,
func: efunc
});
this.sound.addEventListener(type, efunc, true);
}
return this;
};
this.unbind = function(types) {
if (!supported) {
return this;
}
types = types.split(" ");
for (var t = 0; t < types.length; t++) {
var idx = types[t], type = idx.split(".")[0];
for (var i = 0; i < events.length; i++) {
var namespace = events[i].idx.split(".");
if (events[i].idx === idx || namespace[1] && namespace[1] === idx.replace(".", "")) {
this.sound.removeEventListener(type, events[i].func, true);
events.splice(i, 1);
}
}
}
return this;
};
this.bindOnce = function(type, func) {
if (!supported) {
return this;
}
var self = this;
eventsOnce[pid++] = false;
this.bind(type + "." + pid, function() {
if (!eventsOnce[pid]) {
eventsOnce[pid] = true;
func.call(self);
}
self.unbind(type + "." + pid);
});
return this;
};
this.trigger = function(types, detail) {
if (!supported) {
return this;
}
types = types.split(" ");
for (var t = 0; t < types.length; t++) {
var idx = types[t];
for (var i = 0; i < events.length; i++) {
var eventType = events[i].idx.split(".");
if (events[i].idx === idx || eventType[0] && eventType[0] === idx.replace(".", "")) {
var evt = doc.createEvent("HTMLEvents");
evt.initEvent(eventType[0], false, true);
evt.originalEvent = detail;
this.sound.dispatchEvent(evt);
}
}
}
return this;
};
this.fadeTo = function(to, duration, callback) {
if (!supported) {
return this;
}
if (duration instanceof Function) {
callback = duration;
duration = buzz.defaults.duration;
} else {
duration = duration || buzz.defaults.duration;
}
var from = this.volume, delay = duration / Math.abs(from - to), self = this;
this.play();
function doFade() {
setTimeout(function() {
if (from < to && self.volume < to) {
self.setVolume(self.volume += 1);
doFade();
} else if (from > to && self.volume > to) {
self.setVolume(self.volume -= 1);
doFade();
} else if (callback instanceof Function) {
callback.apply(self);
}
}, delay);
}
this.whenReady(function() {
doFade();
});
return this;
};
this.fadeIn = function(duration, callback) {
if (!supported) {
return this;
}
return this.setVolume(0).fadeTo(100, duration, callback);
};
this.fadeOut = function(duration, callback) {
if (!supported) {
return this;
}
return this.fadeTo(0, duration, callback);
};
this.fadeWith = function(sound, duration) {
if (!supported) {
return this;
}
this.fadeOut(duration, function() {
this.stop();
});
sound.play().fadeIn(duration);
return this;
};
this.whenReady = function(func) {
if (!supported) {
return null;
}
var self = this;
if (this.sound.readyState === 0) {
this.bind("canplay.buzzwhenready", function() {
func.call(self);
});
} else {
func.call(self);
}
};
this.addSource = function(src) {
var self = this, source = doc.createElement("source");
source.src = src;
if (buzz.types[getExt(src)]) {
source.type = buzz.types[getExt(src)];
}
this.sound.appendChild(source);
source.addEventListener("error", function(e) {
self.sound.networkState = 3;
self.trigger("sourceerror", e);
});
return source;
};
function timerangeToArray(timeRange) {
var array = [], length = timeRange.length - 1;
for (var i = 0; i <= length; i++) {
array.push({
start: timeRange.start(i),
end: timeRange.end(i)
});
}
return array;
}
function getExt(filename) {
return filename.split(".").pop();
}
if (supported && src) {
for (var i in buzz.defaults) {
if (buzz.defaults.hasOwnProperty(i)) {
if (options[i] === undefined) {
options[i] = buzz.defaults[i];
}
}
}
this.sound = doc.createElement("audio");
if (options.webAudioApi && buzz.audioCtx) {
this.source = buzz.audioCtx.createMediaElementSource(this.sound);
this.source.connect(buzz.audioCtx.destination);
}
if (src instanceof Array) {
for (var j in src) {
if (src.hasOwnProperty(j)) {
this.addSource(src[j]);
}
}
} else if (options.formats.length) {
for (var k in options.formats) {
if (options.formats.hasOwnProperty(k)) {
this.addSource(src + "." + options.formats[k]);
}
}
} else {
this.addSource(src);
}
if (options.loop) {
this.loop();
}
if (options.autoplay) {
this.sound.autoplay = "autoplay";
}
if (options.preload === true) {
this.sound.preload = "auto";
} else if (options.preload === false) {
this.sound.preload = "none";
} else {
this.sound.preload = options.preload;
}
this.setVolume(options.volume);
buzz.sounds.push(this);
}
},
group: function(sounds) {
sounds = argsToArray(sounds, arguments);
this.getSounds = function() {
return sounds;
};
this.add = function(soundArray) {
soundArray = argsToArray(soundArray, arguments);
for (var a = 0; a < soundArray.length; a++) {
sounds.push(soundArray[a]);
}
};
this.remove = function(soundArray) {
soundArray = argsToArray(soundArray, arguments);
for (var a = 0; a < soundArray.length; a++) {
for (var i = 0; i < sounds.length; i++) {
if (sounds[i] === soundArray[a]) {
sounds.splice(i, 1);
break;
}
}
}
};
this.load = function() {
fn("load");
return this;
};
this.play = function() {
fn("play");
return this;
};
this.togglePlay = function() {
fn("togglePlay");
return this;
};
this.pause = function(time) {
fn("pause", time);
return this;
};
this.stop = function() {
fn("stop");
return this;
};
this.mute = function() {
fn("mute");
return this;
};
this.unmute = function() {
fn("unmute");
return this;
};
this.toggleMute = function() {
fn("toggleMute");
return this;
};
this.setVolume = function(volume) {
fn("setVolume", volume);
return this;
};
this.increaseVolume = function(value) {
fn("increaseVolume", value);
return this;
};
this.decreaseVolume = function(value) {
fn("decreaseVolume", value);
return this;
};
this.loop = function() {
fn("loop");
return this;
};
this.unloop = function() {
fn("unloop");
return this;
};
this.setSpeed = function(speed) {
fn("setSpeed", speed);
return this;
};
this.setTime = function(time) {
fn("setTime", time);
return this;
};
this.set = function(key, value) {
fn("set", key, value);
return this;
};
this.bind = function(type, func) {
fn("bind", type, func);
return this;
};
this.unbind = function(type) {
fn("unbind", type);
return this;
};
this.bindOnce = function(type, func) {
fn("bindOnce", type, func);
return this;
};
this.trigger = function(type) {
fn("trigger", type);
return this;
};
this.fade = function(from, to, duration, callback) {
fn("fade", from, to, duration, callback);
return this;
};
this.fadeIn = function(duration, callback) {
fn("fadeIn", duration, callback);
return this;
};
this.fadeOut = function(duration, callback) {
fn("fadeOut", duration, callback);
return this;
};
function fn() {
var args = argsToArray(null, arguments), func = args.shift();
for (var i = 0; i < sounds.length; i++) {
sounds[i][func].apply(sounds[i], args);
}
}
function argsToArray(array, args) {
return array instanceof Array ? array : Array.prototype.slice.call(args);
}
},
all: function() {
return new buzz.group(buzz.sounds);
},
isSupported: function() {
return !!buzz.el.canPlayType;
},
isOGGSupported: function() {
return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/ogg; codecs="vorbis"');
},
isWAVSupported: function() {
return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/wav; codecs="1"');
},
isMP3Supported: function() {
return !!buzz.el.canPlayType && buzz.el.canPlayType("audio/mpeg;");
},
isAACSupported: function() {
return !!buzz.el.canPlayType && (buzz.el.canPlayType("audio/x-m4a;") || buzz.el.canPlayType("audio/aac;"));
},
toTimer: function(time, withHours) {
var h, m, s;
h = Math.floor(time / 3600);
h = isNaN(h) ? "--" : h >= 10 ? h : "0" + h;
m = withHours ? Math.floor(time / 60 % 60) : Math.floor(time / 60);
m = isNaN(m) ? "--" : m >= 10 ? m : "0" + m;
s = Math.floor(time % 60);
s = isNaN(s) ? "--" : s >= 10 ? s : "0" + s;
return withHours ? h + ":" + m + ":" + s : m + ":" + s;
},
fromTimer: function(time) {
var splits = time.toString().split(":");
if (splits && splits.length === 3) {
time = parseInt(splits[0], 10) * 3600 + parseInt(splits[1], 10) * 60 + parseInt(splits[2], 10);
}
if (splits && splits.length === 2) {
time = parseInt(splits[0], 10) * 60 + parseInt(splits[1], 10);
}
return time;
},
toPercent: function(value, total, decimal) {
var r = Math.pow(10, decimal || 0);
return Math.round(value * 100 / total * r) / r;
},
fromPercent: function(percent, total, decimal) {
var r = Math.pow(10, decimal || 0);
return Math.round(total / 100 * percent * r) / r;
}
};
return buzz;
});