dev@397: /** dev@397: * Created by lucast on 02/06/2017. dev@397: */ dev@397: import {Injectable, NgZone} from '@angular/core'; dev@397: import {AudioPlayerService} from '../audio-player/audio-player.service'; dev@397: import {Subscription} from 'rxjs/Subscription'; dev@397: import {OnSeekHandler} from '../../playhead/PlayHeadHelpers'; dev@397: dev@400: export type TaskRemover = () => void; dev@400: type TaskId = number; dev@400: dev@397: @Injectable() dev@397: export class RenderLoopService { dev@397: private playingStateSubscription: Subscription; dev@397: private seekedSubscription: Subscription; dev@400: private tasks: Map; dev@400: private countingId: TaskId; dev@397: dev@397: constructor(private player: AudioPlayerService, dev@397: private zone: NgZone) { dev@400: this.countingId = 0; dev@400: this.tasks = new Map(); dev@397: this.seekedSubscription = this.player.seeked$.subscribe(() => { dev@397: if (!this.player.isPlaying()) { dev@397: this.zone.runOutsideAngular(() => { dev@397: this.runTasks(); dev@397: }); dev@397: } dev@397: }); dev@397: this.playingStateSubscription = this.player.playingStateChange$.subscribe( dev@397: isPlaying => { dev@397: if (isPlaying) { dev@397: this.animate(); dev@397: } dev@397: }); dev@397: } dev@397: dev@400: addPlayingTask(task: OnSeekHandler): TaskRemover { dev@400: const id = this.countingId++; dev@400: this.tasks.set(id, task); dev@400: return () => { dev@400: this.tasks.delete(id); dev@400: }; dev@397: } dev@397: dev@397: private animate(): void { dev@397: this.zone.runOutsideAngular(() => { dev@397: const animateNextFrame = () => { dev@397: if (this.player.isPlaying()) { dev@397: this.runTasks(); dev@397: requestAnimationFrame(animateNextFrame); dev@397: } dev@397: }; dev@397: requestAnimationFrame(animateNextFrame); dev@397: }); dev@397: } dev@397: dev@397: private runTasks(): void { dev@397: const currentTime = this.player.getCurrentTime(); dev@400: for (const task of this.tasks.values()) { dev@397: task(currentTime); dev@397: } dev@397: } dev@397: }