view src/app/services/render-loop/render-loop.service.ts @ 509:041468f553e1 tip master

Merge pull request #57 from LucasThompson/fix/session-stack-max-call-stack Fix accidental recursion in PersistentStack
author Lucas Thompson <LucasThompson@users.noreply.github.com>
date Mon, 27 Nov 2017 11:04:30 +0000
parents e06b62d949de
children
line wrap: on
line source
/**
 * Created by lucast on 02/06/2017.
 */
import {Injectable, NgZone} from '@angular/core';
import {AudioPlayerService} from '../audio-player/audio-player.service';
import {Subscription} from 'rxjs/Subscription';
import {OnSeekHandler} from '../../playhead/PlayHeadHelpers';

export type TaskRemover = () => void;
type TaskId = number;

@Injectable()
export class RenderLoopService {
  private playingStateSubscription: Subscription;
  private seekedSubscription: Subscription;
  private tasks: Map<TaskId, OnSeekHandler>;
  private countingId: TaskId;

  constructor(private player: AudioPlayerService,
              private zone: NgZone) {
    this.countingId = 0;
    this.tasks = new Map();
    this.seekedSubscription = this.player.seeked$.subscribe(() => {
      if (!this.player.isPlaying()) {
        this.zone.runOutsideAngular(() => {
          this.runTasks();
        });
      }
    });
    this.playingStateSubscription = this.player.playingStateChange$.subscribe(
      isPlaying => {
        if (isPlaying) {
          this.animate();
        }
      });
  }

  addPlayingTask(task: OnSeekHandler): TaskRemover {
    const id = this.countingId++;
    this.tasks.set(id, task);
    return () => {
      this.tasks.delete(id);
    };
  }

  private animate(): void {
    this.zone.runOutsideAngular(() => {
      const animateNextFrame = () => {
        if (this.player.isPlaying()) {
          this.runTasks();
          requestAnimationFrame(animateNextFrame);
        }
      };
      requestAnimationFrame(animateNextFrame);
    });
  }

  private runTasks(): void {
    const currentTime = this.player.getCurrentTime();
    for (const task of this.tasks.values()) {
      task(currentTime);
    }
  }
}