snappymail/dev/Common/Audio.js

132 lines
3.1 KiB
JavaScript
Raw Permalink Normal View History

2016-06-16 07:36:44 +08:00
import * as Links from 'Common/Links';
import { doc, SettingsGet, fireEvent, addEventsListener } from 'Common/Globals';
2022-06-08 00:46:06 +08:00
import { addObservablesTo } from 'External/ko';
2015-11-15 08:23:16 +08:00
let notificator = null,
player = null,
2022-09-02 17:52:07 +08:00
canPlay = type => !!player?.canPlayType(type).replace('no', ''),
audioCtx = window.AudioContext || window.webkitAudioContext,
play = (url, name) => {
if (player) {
player.src = url;
player.play();
name = name.trim();
fireEvent('audio.start', name.replace(/\.([a-z0-9]{3})$/, '') || 'audio');
}
},
createNewObject = () => {
try {
const player = new Audio;
if (player.canPlayType && player.pause && player.play) {
player.preload = 'none';
player.loop = false;
player.autoplay = false;
player.muted = false;
return player;
}
} catch (e) {
console.error(e);
}
return null;
},
// The AudioContext is not allowed to start.
// It must be resumed (or created) after a user gesture on the page. https://goo.gl/7K7WLu
// Setup listeners to attempt an unlock
unlockEvents = [
'click','dblclick',
'contextmenu',
'auxclick',
'mousedown','mouseup',
'pointerup',
'touchstart','touchend',
'keydown','keyup'
],
unlock = () => {
unlockEvents.forEach(type => doc.removeEventListener(type, unlock, true));
if (audioCtx) {
console.log('AudioContext ' + audioCtx.state);
audioCtx.resume();
}
2022-06-08 00:46:06 +08:00
// setTimeout(()=>SMAudio.playNotification(0,1),1);
};
2016-06-28 04:54:38 +08:00
if (audioCtx) {
audioCtx = audioCtx ? new audioCtx : null;
audioCtx.onstatechange = unlock;
}
unlockEvents.forEach(type => doc.addEventListener(type, unlock, true));
/**
* Browsers can't play without user interaction
*/
export const SMAudio = new class {
2016-09-10 06:38:16 +08:00
constructor() {
player || (player = createNewObject());
2016-08-30 06:10:24 +08:00
this.supported = !!player;
this.supportedMp3 = canPlay('audio/mpeg;');
this.supportedWav = canPlay('audio/wav; codecs="1"');
this.supportedOgg = canPlay('audio/ogg; codecs="vorbis"');
if (player) {
const stopFn = () => this.pause();
addEventsListener(player, ['ended','error'], stopFn);
addEventListener('audio.api.stop', stopFn);
2015-11-15 08:23:16 +08:00
}
2022-06-08 00:46:06 +08:00
addObservablesTo(this, {
notifications: false
});
2015-11-15 08:23:16 +08:00
}
paused() {
return !player || player.paused;
2015-11-15 08:23:16 +08:00
}
stop() {
this.pause();
2015-11-15 08:23:16 +08:00
}
pause() {
2022-09-02 17:52:07 +08:00
player?.pause();
fireEvent('audio.stop');
2015-11-15 08:23:16 +08:00
}
playMp3(url, name) {
this.supportedMp3 && play(url, name);
2015-11-15 08:23:16 +08:00
}
playOgg(url, name) {
this.supportedOgg && play(url, name);
2015-11-15 08:23:16 +08:00
}
playWav(url, name) {
this.supportedWav && play(url, name);
2015-11-15 08:23:16 +08:00
}
2022-06-08 00:46:06 +08:00
/**
* Used with SoundNotification setting
*/
playNotification(force, silent) {
if (force || this.notifications()) {
if ('running' == audioCtx.state && (this.supportedMp3 || this.supportedOgg)) {
notificator = notificator || createNewObject();
if (notificator) {
// SettingsGet('NotificationSound').startsWith('custom@')
2022-06-08 00:46:06 +08:00
notificator.src = Links.staticLink('sounds/'
+ SettingsGet('NotificationSound')
+ (this.supportedMp3 ? '.mp3' : '.ogg'));
notificator.volume = silent ? 0.01 : 1;
notificator.play();
}
} else {
console.log('No audio: ' + audioCtx.state);
2015-11-15 08:23:16 +08:00
}
}
}
};