annotate src/app/services/audio-player/audio-player.service.ts @ 52:ec38b85be3ac

Create publicly accessible streams for subscribing to play state change and seeking events.
author Lucas Thompson <dev@lucas.im>
date Wed, 07 Dec 2016 13:54:46 +0000
parents f6e58c2accb0
children 6ece58c96868
rev   line source
dev@37 1 import {Injectable, Inject} from '@angular/core';
dev@52 2 import {Subject} from "rxjs/Subject";
dev@52 3 import {Observable} from "rxjs";
dev@37 4
dev@37 5 @Injectable()
dev@37 6 export class AudioPlayerService {
dev@37 7
dev@52 8 private currentObjectUrl: string;
dev@52 9 private playingStateChange: Subject<boolean>;
dev@52 10 playingStateChange$: Observable<boolean>;
dev@52 11 private seeked: Subject<number>;
dev@52 12 seeked$: Observable<number>;
dev@52 13
dev@37 14 constructor(@Inject(HTMLAudioElement) private audioElement: HTMLAudioElement /* TODO probably shouldn't play audio this way */,
dev@37 15 @Inject('AudioContext') private audioContext: AudioContext) {
dev@52 16 this.currentObjectUrl = '';
dev@52 17 this.playingStateChange = new Subject<boolean>();
dev@52 18 this.playingStateChange$ = this.playingStateChange.asObservable();
dev@52 19 this.seeked = new Subject<number>();
dev@52 20 this.seeked$ = this.seeked.asObservable();
dev@52 21 this.audioElement.addEventListener('ended', () => {
dev@52 22 this.playingStateChange.next(this.isPlaying());
dev@52 23 });
dev@52 24 this.audioElement.addEventListener('seeked', () => {
dev@52 25 this.seeked.next(this.audioElement.currentTime);
dev@52 26 });
dev@37 27 }
dev@37 28
dev@37 29 getCurrentTime(): number {
dev@37 30 return this.audioElement.currentTime;
dev@37 31 }
dev@37 32
dev@37 33 isPlaying(): boolean {
dev@37 34 return !this.audioElement.paused;
dev@37 35 }
dev@37 36
dev@37 37 decodeAudioData(buffer: ArrayBuffer): Promise<AudioBuffer> {
dev@37 38 return new Promise((res, rej) => this.audioContext.decodeAudioData(buffer, res, rej));
dev@37 39 }
dev@37 40
dev@37 41 loadAudioFromUrl(url: string): void {
dev@52 42 if (this.currentObjectUrl)
dev@52 43 URL.revokeObjectURL(this.currentObjectUrl);
dev@52 44 this.currentObjectUrl = url;
dev@37 45 this.audioElement.pause();
dev@37 46 this.audioElement.src = url;
dev@37 47 }
dev@37 48
dev@37 49 togglePlaying(): void {
dev@37 50 this.isPlaying() ? this.audioElement.pause() : this.audioElement.play();
dev@52 51 this.playingStateChange.next(this.isPlaying());
dev@37 52 }
dev@37 53
dev@37 54 setVolume(value: number): void {
dev@37 55 this.audioElement.volume = value; // TODO check bounds?
dev@37 56 }
dev@37 57
dev@37 58 seekBy(seconds: number): void {
dev@37 59 // TODO some kind of error handling?
dev@37 60 this.audioElement.currentTime += seconds;
dev@37 61 }
dev@37 62
dev@37 63 seekToStart(): void {
dev@37 64 this.audioElement.currentTime = 0;
dev@37 65 }
dev@37 66
dev@37 67 seekToEnd(): void {
dev@37 68 this.audioElement.currentTime = this.getDuration();
dev@37 69 }
dev@37 70
dev@37 71 getDuration(): number {
dev@37 72 return this.audioElement.duration;
dev@37 73 }
dev@37 74 }