Audio im Background stop

This commit is contained in:
silas 2018-10-01 22:41:59 +02:00
parent c0a977afd7
commit b5da034687
3 changed files with 251 additions and 33 deletions

View File

@ -3167,11 +3167,11 @@ function applyPolyfills() {
}; };
elem.addEventListener("transitionend", transEndLis); elem.addEventListener("transitionend", transEndLis);
elem.addEventListener("transitioncancel", transCancelledLis); elem.addEventListener("transitioncancel", transCancelledLis);
//Fallback
setTimeout(() => {
resolve(false);
}, (time + delay) * 1000);
}); });
//Fallback
setTimeout(() => {
resolve(false);
}, (time+delay)*1000);
//Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch) //Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch)
requestAnimationFrame(function () { requestAnimationFrame(function () {
@ -3208,13 +3208,13 @@ function applyPolyfills() {
elem.addEventListener("transitionend", transEndLis); elem.addEventListener("transitionend", transEndLis);
elem.addEventListener("transitioncancel", transCancelledLis); elem.addEventListener("transitioncancel", transCancelledLis);
if (getComputedStyle(elem).getPropertyValue("opacity") === "1"){ if (getComputedStyle(elem).getPropertyValue("opacity") === "1") {
resolve(false); resolve(false);
} }
//Fallback //Fallback
setTimeout(() => { setTimeout(() => {
resolve(false); resolve(false);
}, (time+delay)*1000); }, (time + delay) * 1000);
//Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch) //Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch)
requestAnimationFrame(function () { requestAnimationFrame(function () {
@ -4812,6 +4812,96 @@ class ScaleHelper {
} }
} }
class AudioChain {
constructor(context, sourceBuffer, chainFunction) {
this.buffer = sourceBuffer;
this.shouldLoop = false;
this.loopStart = null;
this.loopEnd = null;
this.chainFunction = chainFunction;
this.context = context;
this.startTime = null;
this.pauseTime = null;
this.source = null;
}
setBuffer(buffer) {
this.buffer = buffer;
}
setLooping(shouldLoop, loopStart, loopEnd) {
this.shouldLoop = shouldLoop;
if (Helper.isNotNull(loopStart)) {
this.loopStart = loopStart;
}
if (Helper.isNotNull(loopEnd)) {
this.loopEnd = loopEnd;
}
}
async start(delay, offset, duration)
{
let source = this.context.createBufferSource();
source.loop = this.shouldLoop;
if (Helper.isNotNull(this.loopStart)) {
source.loopStart = this.loopStart;
}
if (Helper.isNotNull(this.loopEnd)) {
source.loopEnd = this.loopEnd;
}
source.buffer = this.buffer;
await this.chainFunction(source);
source.start(delay, offset, duration);
this.startTime = (new Date()).getTime();
this.source = source;
}
async stop(delay){
if (Helper.isNotNull(this.source)){
this.pauseTime = ((new Date()).getTime())-this.startTime;
return this.source.stop(delay);
}
return null;
}
async resume(){
console.log("resume-Time:", Helper.nonNull(this.pauseTime, 0)/1000.0);
return this.start(null, Helper.nonNull(this.pauseTime, 0)/1000.0);
}
}
class InitPromise$1
{
static addPromise(promise)
{
if (typeof promise === 'function')
{
let func = promise;
promise = InitPromise$1.mainPromise.then(function(app){
return (func(app));
});
}
InitPromise$1.promises.push(promise);
}
static resolve(app)
{
InitPromise$1.mainResolver(app);
return InitPromise$1.mainPromise.then(function(){
return Promise.all(InitPromise$1.promises);
});
}
}
InitPromise$1.promises = [];
InitPromise$1.mainPromise = new Promise(function(resolver){
InitPromise$1.mainResolver = resolver;
});
class SoundManager { class SoundManager {
static getInstance() { static getInstance() {
if (Helper.isNull(SoundManager.instance)) { if (Helper.isNull(SoundManager.instance)) {
@ -4823,6 +4913,10 @@ class SoundManager {
constructor() { constructor() {
this.channels = {}; this.channels = {};
this.context = new AudioContext(); this.context = new AudioContext();
window.addEventListener("visibilitychange", () => {
this.handleVisibilityChange();
});
} }
set(options, channel) { set(options, channel) {
@ -4867,20 +4961,20 @@ class SoundManager {
if (!this.channels[channel].muted) { if (!this.channels[channel].muted) {
let buffer = await this.channels[channel].loadedPromise; let buffer = await this.channels[channel].loadedPromise;
let source = this.context.createBufferSource(); let source = new AudioChain(this.context, buffer, (sourceNode) => {
let gain = this.context.createGain(); let gain = this.context.createGain();
gain.gain.value = this.channels[channel].volume;
source.buffer = buffer; sourceNode.connect(gain);
source.loop = this.channels[channel].loop; gain.connect(this.context.destination);
gain.gain.value = this.channels[channel].volume; });
source.setBuffer(buffer);
//to prevent gap in mp3-files //to prevent gap in mp3-files
source.loopStart = 0.3; source.setLooping(this.channels[channel].loop, 0.3, buffer.duration-0.3);
source.loopEnd = buffer.duration-0.3;
source.connect(gain); source.start();
gain.connect(this.context.destination);
source.start(0);
this.channels[channel].source = source; this.channels[channel].source = source;
} }
@ -4899,6 +4993,21 @@ class SoundManager {
channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT); channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT);
return this.channels[channel]; return this.channels[channel];
} }
handleVisibilityChange() {
if (document.hidden){
for (let k in this.channels){
this.channels[k].source.stop();
}
}
else{
for (let k in this.channels){
if (!this.channels[k].muted){
this.channels[k].source.resume();
}
}
}
}
} }
SoundManager.CHANNELS = { SoundManager.CHANNELS = {

View File

@ -233,6 +233,96 @@ class ScaleHelper {
} }
} }
class AudioChain {
constructor(context, sourceBuffer, chainFunction) {
this.buffer = sourceBuffer;
this.shouldLoop = false;
this.loopStart = null;
this.loopEnd = null;
this.chainFunction = chainFunction;
this.context = context;
this.startTime = null;
this.pauseTime = null;
this.source = null;
}
setBuffer(buffer) {
this.buffer = buffer;
}
setLooping(shouldLoop, loopStart, loopEnd) {
this.shouldLoop = shouldLoop;
if (Helper.isNotNull(loopStart)) {
this.loopStart = loopStart;
}
if (Helper.isNotNull(loopEnd)) {
this.loopEnd = loopEnd;
}
}
async start(delay, offset, duration)
{
let source = this.context.createBufferSource();
source.loop = this.shouldLoop;
if (Helper.isNotNull(this.loopStart)) {
source.loopStart = this.loopStart;
}
if (Helper.isNotNull(this.loopEnd)) {
source.loopEnd = this.loopEnd;
}
source.buffer = this.buffer;
await this.chainFunction(source);
source.start(delay, offset, duration);
this.startTime = (new Date()).getTime();
this.source = source;
}
async stop(delay){
if (Helper.isNotNull(this.source)){
this.pauseTime = ((new Date()).getTime())-this.startTime;
return this.source.stop(delay);
}
return null;
}
async resume(){
console.log("resume-Time:", Helper.nonNull(this.pauseTime, 0)/1000.0);
return this.start(null, Helper.nonNull(this.pauseTime, 0)/1000.0);
}
}
class InitPromise$1
{
static addPromise(promise)
{
if (typeof promise === 'function')
{
let func = promise;
promise = InitPromise$1.mainPromise.then(function(app){
return (func(app));
});
}
InitPromise$1.promises.push(promise);
}
static resolve(app)
{
InitPromise$1.mainResolver(app);
return InitPromise$1.mainPromise.then(function(){
return Promise.all(InitPromise$1.promises);
});
}
}
InitPromise$1.promises = [];
InitPromise$1.mainPromise = new Promise(function(resolver){
InitPromise$1.mainResolver = resolver;
});
class SoundManager { class SoundManager {
static getInstance() { static getInstance() {
if (Helper.isNull(SoundManager.instance)) { if (Helper.isNull(SoundManager.instance)) {
@ -244,6 +334,10 @@ class SoundManager {
constructor() { constructor() {
this.channels = {}; this.channels = {};
this.context = new AudioContext(); this.context = new AudioContext();
window.addEventListener("visibilitychange", () => {
this.handleVisibilityChange();
});
} }
set(options, channel) { set(options, channel) {
@ -288,20 +382,20 @@ class SoundManager {
if (!this.channels[channel].muted) { if (!this.channels[channel].muted) {
let buffer = await this.channels[channel].loadedPromise; let buffer = await this.channels[channel].loadedPromise;
let source = this.context.createBufferSource(); let source = new AudioChain(this.context, buffer, (sourceNode) => {
let gain = this.context.createGain(); let gain = this.context.createGain();
gain.gain.value = this.channels[channel].volume;
source.buffer = buffer; sourceNode.connect(gain);
source.loop = this.channels[channel].loop; gain.connect(this.context.destination);
gain.gain.value = this.channels[channel].volume; });
source.setBuffer(buffer);
//to prevent gap in mp3-files //to prevent gap in mp3-files
source.loopStart = 0.3; source.setLooping(this.channels[channel].loop, 0.3, buffer.duration-0.3);
source.loopEnd = buffer.duration-0.3;
source.connect(gain); source.start();
gain.connect(this.context.destination);
source.start(0);
this.channels[channel].source = source; this.channels[channel].source = source;
} }
@ -320,6 +414,21 @@ class SoundManager {
channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT); channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT);
return this.channels[channel]; return this.channels[channel];
} }
handleVisibilityChange() {
if (document.hidden){
for (let k in this.channels){
this.channels[k].source.stop();
}
}
else{
for (let k in this.channels){
if (!this.channels[k].muted){
this.channels[k].source.resume();
}
}
}
}
} }
SoundManager.CHANNELS = { SoundManager.CHANNELS = {
@ -393,4 +502,4 @@ class TabbedFragment extends Fragment {
} }
} }
export { DelayPromise, Matomo, RotateHelper, ScaleHelper, SoundManager, TabbedFragment }; export { DelayPromise, Matomo, RotateHelper, ScaleHelper, AudioChain, SoundManager, TabbedFragment };

View File

@ -4155,11 +4155,11 @@ function applyPolyfills() {
}; };
elem.addEventListener("transitionend", transEndLis); elem.addEventListener("transitionend", transEndLis);
elem.addEventListener("transitioncancel", transCancelledLis); elem.addEventListener("transitioncancel", transCancelledLis);
//Fallback
setTimeout(() => {
resolve(false);
}, (time + delay) * 1000);
}); });
//Fallback
setTimeout(() => {
resolve(false);
}, (time+delay)*1000);
//Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch) //Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch)
requestAnimationFrame(function () { requestAnimationFrame(function () {
@ -4196,13 +4196,13 @@ function applyPolyfills() {
elem.addEventListener("transitionend", transEndLis); elem.addEventListener("transitionend", transEndLis);
elem.addEventListener("transitioncancel", transCancelledLis); elem.addEventListener("transitioncancel", transCancelledLis);
if (getComputedStyle(elem).getPropertyValue("opacity") === "1"){ if (getComputedStyle(elem).getPropertyValue("opacity") === "1") {
resolve(false); resolve(false);
} }
//Fallback //Fallback
setTimeout(() => { setTimeout(() => {
resolve(false); resolve(false);
}, (time+delay)*1000); }, (time + delay) * 1000);
//Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch) //Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch)
requestAnimationFrame(function () { requestAnimationFrame(function () {