annotate src/app/services/audio-player/audio-player.service.ts @ 82:1bd1a44f5dd3

Add method for seeking to specific time to the audio player service
author Lucas Thompson <dev@lucas.im>
date Thu, 23 Feb 2017 15:42:59 +0000
parents 6ece58c96868
children dd02ef0d3c93
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@82 47 this.audioElement.load();
dev@37 48 }
dev@37 49
dev@37 50 togglePlaying(): void {
dev@57 51 if (this.audioElement.readyState >= 2) {
dev@57 52 this.isPlaying() ? this.audioElement.pause() : this.audioElement.play();
dev@57 53 this.playingStateChange.next(this.isPlaying());
dev@57 54 }
dev@37 55 }
dev@37 56
dev@37 57 setVolume(value: number): void {
dev@37 58 this.audioElement.volume = value; // TODO check bounds?
dev@37 59 }
dev@37 60
dev@82 61 seekTo(seconds: number): void {
dev@82 62 if (seconds < 0) {
dev@82 63 this.audioElement.currentTime = 0;
dev@82 64 } else if (seconds < this.getDuration()) {
dev@82 65 this.audioElement.currentTime = seconds;
dev@82 66 } else {
dev@82 67 this.audioElement.currentTime = this.getDuration();
dev@82 68 }
dev@82 69 }
dev@82 70
dev@37 71 seekBy(seconds: number): void {
dev@37 72 // TODO some kind of error handling?
dev@37 73 this.audioElement.currentTime += seconds;
dev@37 74 }
dev@37 75
dev@37 76 seekToStart(): void {
dev@37 77 this.audioElement.currentTime = 0;
dev@37 78 }
dev@37 79
dev@37 80 seekToEnd(): void {
dev@37 81 this.audioElement.currentTime = this.getDuration();
dev@37 82 }
dev@37 83
dev@37 84 getDuration(): number {
dev@37 85 return this.audioElement.duration;
dev@37 86 }
dev@37 87 }