Better handling of audio events

This commit is contained in:
Chrystian Huot 2019-07-04 12:25:19 -04:00
parent 407627ef6a
commit 6900c55cee

View file

@ -1,6 +1,6 @@
import { EventEmitter, Injectable, OnDestroy } from '@angular/core'; import { EventEmitter, Injectable, OnDestroy } from '@angular/core';
import { MeteorObservable } from 'meteor-rxjs'; import { MeteorObservable } from 'meteor-rxjs';
import { Subject, Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { debounceTime, filter, skip } from 'rxjs/operators'; import { debounceTime, filter, skip } from 'rxjs/operators';
import { RadioAvoids, RadioCall, RadioCalls, RadioEvent, RadioSystem, RadioSystems, RadioTalkgroup } from './radio'; import { RadioAvoids, RadioCall, RadioCalls, RadioEvent, RadioSystem, RadioSystems, RadioTalkgroup } from './radio';
@ -17,7 +17,6 @@ export class AppRadioService implements OnDestroy {
} }
private _audio: HTMLAudioElement; private _audio: HTMLAudioElement;
private _audioEvent: Subject<void> = new Subject();
private _avoids: RadioAvoids = {}; private _avoids: RadioAvoids = {};
@ -40,11 +39,9 @@ export class AppRadioService implements OnDestroy {
}; };
private _subscriptions: { private _subscriptions: {
audio: Subscription[];
liveFeed: Subscription[]; liveFeed: Subscription[];
systems: Subscription[]; systems: Subscription[];
} = { } = {
audio: [],
liveFeed: [], liveFeed: [],
systems: [], systems: [],
}; };
@ -54,7 +51,6 @@ export class AppRadioService implements OnDestroy {
constructor() { constructor() {
this._readAvoids(); this._readAvoids();
this._subscribeAudioEvent();
this._subscribeSystems(); this._subscribeSystems();
} }
@ -180,24 +176,22 @@ export class AppRadioService implements OnDestroy {
if (call.audio) { if (call.audio) {
if (this._call.current) { if (this._call.current) {
this._call.queue.unshift(call); this._call.queue.unshift(call);
this.stop(); this.stop();
} else { } else {
this._call.current = call; this._call.current = call;
this._audio.src = call.audio; this._audio.src = call.audio;
this._audio.load(); this._audio.load();
}
}
this._emitCallEvent();
}
}
} else if (!this._call.current && this._call.queue.length) { } else if (!this._call.current && this._call.queue.length) {
this._call.current = this._call.queue.shift(); this._call.current = this._call.queue.shift();
this._audio.src = this._call.current.audio; this._audio.src = this._call.current.audio;
this._audio.load(); this._audio.load();
this._emitCallEvent();
this._emitQueueEvent();
} }
} }
@ -234,8 +228,10 @@ export class AppRadioService implements OnDestroy {
if (this._call.current) { if (this._call.current) {
this._audio.pause(); this._audio.pause();
this._audio.src = null; this._call.previous = this._call.current;
this._audio.load(); this._call.current = null;
this._emitCallEvent();
} }
} }
@ -284,17 +280,55 @@ export class AppRadioService implements OnDestroy {
private _configureAudio(): void { private _configureAudio(): void {
if (!this._audio) { if (!this._audio) {
let playing = false;
let watchdog = null;
this._audio = new Audio(); this._audio = new Audio();
this._audio.oncanplaythrough = () => this._audio.play(); this._audio.autoplay = true;
this._audio.onabort = () => this._audioEvent.next(); this._audio.onabort =
this._audio.onended = () => this._audioEvent.next(); this._audio.onended =
this._audio.onerror = () => this._audioEvent.next(); this._audio.onerror =
this._audio.onpause = () => this._audioEvent.next(); this._audio.onpause = () => {
this._audio.onstalled = () => this._audioEvent.next(); if (playing) {
playing = false;
this._audio.ontimeupdate = () => this._emitTimeEvent(); if (watchdog) {
clearTimeout(watchdog);
watchdog = null;
}
this.stop();
if (this._call.queue.length) {
this.play();
}
}
};
this._audio.onplay = () => {
playing = true;
this._emitCallEvent();
this._emitQueueEvent();
};
this._audio.ontimeupdate = () => {
if (playing) {
this._emitTimeEvent();
if (watchdog) {
clearTimeout(watchdog);
}
watchdog = setTimeout(() => {
this.stop();
watchdog = null;
}, 5000);
}
};
} }
} }
@ -374,23 +408,6 @@ export class AppRadioService implements OnDestroy {
} }
} }
private _subscribeAudioEvent(): void {
this._subscriptions.audio.push(
this._audioEvent
.pipe(debounceTime(1000))
.subscribe(() => {
if (this._call.current) {
this._call.previous = this._call.current;
this._call.current = null;
this._emitCallEvent();
setTimeout(() => this.play(), 1000);
}
}),
);
}
private _subscribeLiveFeed(): void { private _subscribeLiveFeed(): void {
if (!this._subscriptions.liveFeed.length) { if (!this._subscriptions.liveFeed.length) {
const options = { const options = {
@ -438,10 +455,7 @@ export class AppRadioService implements OnDestroy {
} }
} }
private _subscribeSystems(): Promise<void> { private _subscribeSystems(): void {
let hasInitialize = false;
return new Promise((resolve) => {
if (!this._subscriptions.systems.length) { if (!this._subscriptions.systems.length) {
this._subscriptions.systems.push(MeteorObservable this._subscriptions.systems.push(MeteorObservable
.subscribe('systems') .subscribe('systems')
@ -462,15 +476,9 @@ export class AppRadioService implements OnDestroy {
this._syncAvoids(); this._syncAvoids();
this._writeAvoids(); this._writeAvoids();
if (!hasInitialize) {
hasInitialize = true;
resolve();
}
} }
})); }));
} }
});
} }
private _syncAvoids(): void { private _syncAvoids(): void {
@ -509,7 +517,6 @@ export class AppRadioService implements OnDestroy {
} }
private _unsubscribe(subscriptions: Subscription[] = [ private _unsubscribe(subscriptions: Subscription[] = [
...this._subscriptions.audio,
...this._subscriptions.liveFeed, ...this._subscriptions.liveFeed,
...this._subscriptions.systems, ...this._subscriptions.systems,
]) { ]) {