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@57
|
50 if (this.audioElement.readyState >= 2) {
|
dev@57
|
51 this.isPlaying() ? this.audioElement.pause() : this.audioElement.play();
|
dev@57
|
52 this.playingStateChange.next(this.isPlaying());
|
dev@57
|
53 }
|
dev@37
|
54 }
|
dev@37
|
55
|
dev@37
|
56 setVolume(value: number): void {
|
dev@37
|
57 this.audioElement.volume = value; // TODO check bounds?
|
dev@37
|
58 }
|
dev@37
|
59
|
dev@37
|
60 seekBy(seconds: number): void {
|
dev@37
|
61 // TODO some kind of error handling?
|
dev@37
|
62 this.audioElement.currentTime += seconds;
|
dev@37
|
63 }
|
dev@37
|
64
|
dev@37
|
65 seekToStart(): void {
|
dev@37
|
66 this.audioElement.currentTime = 0;
|
dev@37
|
67 }
|
dev@37
|
68
|
dev@37
|
69 seekToEnd(): void {
|
dev@37
|
70 this.audioElement.currentTime = this.getDuration();
|
dev@37
|
71 }
|
dev@37
|
72
|
dev@37
|
73 getDuration(): number {
|
dev@37
|
74 return this.audioElement.duration;
|
dev@37
|
75 }
|
dev@37
|
76 }
|