UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

114 lines (106 loc) 4.02 kB
import {Player} from 'tone/build/esm/source/buffer/Player'; export type OnBeforePlayCallback = (offset: number) => void; export type OnPlaySuccessCallback = () => void; export type OnPlayErrorCallback = (err: unknown) => void; export type OnStopCallback = () => void; export interface PlayerCallbacks { onBeforePlay?: Set<OnBeforePlayCallback>; onPlaySuccess?: Set<OnPlaySuccessCallback>; onPlayError?: Set<OnPlayErrorCallback>; onStop?: Set<OnStopCallback>; } export type PlayerEventName = 'onBeforePlay' | 'onPlaySuccess' | 'onPlayError' | 'onStop'; type CallbackByEventNameGeneric = { [key in PlayerEventName]: OnBeforePlayCallback | OnPlaySuccessCallback | OnPlayErrorCallback | OnStopCallback; }; export interface CallbackByEventName extends CallbackByEventNameGeneric { onBeforePlay: OnBeforePlayCallback; onPlaySuccess: OnPlaySuccessCallback; onPlayError: OnPlayErrorCallback; onStop: OnStopCallback; } export class AudioPlayerCallbacksManagerClass { private static _instance: AudioPlayerCallbacksManagerClass; private constructor() {} static instance() { return (this._instance = this._instance || new AudioPlayerCallbacksManagerClass()); } private _callbacksByPlayer: Map<Player, PlayerCallbacks> = new Map(); registerPlayer(player: Player) { if (this._callbacksByPlayer.get(player)) { return; } this._callbacksByPlayer.set(player, {}); } deregisterPlayer(player: Player) { // in order for deregister to work, // we need to make sure that the player is not registered somewhere else by another node. // so we may instead have the players created here? this._callbacksByPlayer.delete(player); } // onBeforePlay onBeforePlay(player: Player, callback: OnBeforePlayCallback) { this._on(player, 'onBeforePlay', callback); } removeOnBeforePlay(player: Player, callback: OnStopCallback) { this._removeCallback(player, 'onBeforePlay', callback); } runOnBeforePlayCallbacks(player: Player, offset: number) { this._callbacksByPlayer.get(player)?.onBeforePlay?.forEach((callback) => callback(offset)); } // onPlaySuccess onPlaySuccess(player: Player, callback: OnPlaySuccessCallback) { this._on(player, 'onPlaySuccess', callback); } removeOnPlaySuccess(player: Player, callback: OnStopCallback) { this._removeCallback(player, 'onPlaySuccess', callback); } runOnPlaySuccessCallbacks(player: Player) { this._callbacksByPlayer.get(player)?.onPlaySuccess?.forEach((callback) => callback()); } // onPlayError onPlayError(player: Player, callback: OnPlayErrorCallback) { this._on(player, 'onPlayError', callback); } removeOnPlayError(player: Player, callback: OnStopCallback) { this._removeCallback(player, 'onPlayError', callback); } runOnPlayErrorCallbacks(player: Player, err: unknown) { this._callbacksByPlayer.get(player)?.onPlayError?.forEach((callback) => callback(err)); } // onStop onStop(player: Player, callback: OnStopCallback) { this._on(player, 'onStop', callback); } removeOnStop(player: Player, callback: OnStopCallback) { this._removeCallback(player, 'onStop', callback); } runOnStopCallbacks(player: Player) { this._callbacksByPlayer.get(player)?.onStop?.forEach((callback) => callback()); } // generic private _on<E extends PlayerEventName>(player: Player, eventName: E, callback: CallbackByEventName[E]) { let map = this._callbacksByPlayer.get(player); if (!map) { this.registerPlayer(player); map = this._callbacksByPlayer.get(player); } if (!map) { return; } map[eventName] = map[eventName] || (new Set() as any); map[eventName]?.add(callback as any); } private _removeCallback<E extends PlayerEventName>(player: Player, eventName: E, callback: CallbackByEventName[E]) { let map = this._callbacksByPlayer.get(player); if (!map) { this.registerPlayer(player); map = this._callbacksByPlayer.get(player); } if (!map) { return; } map[eventName]?.delete(callback as any); } } export const AudioPlayerCallbacksManager = AudioPlayerCallbacksManagerClass.instance();