UNPKG

sound-manager

Version:
286 lines (235 loc) 7.6 kB
import { createSound, } from '../Sound/createSound'; import { doToOneOrMany, } from '../functions/doToOneOrMany'; import { getFrozenObject, } from '../functions/getFrozenObject'; import { ICollectionSubmanager, } from './ICollectionSubmanager'; import { ICreateSoundOptions, } from '../Sound/ICreateSoundOptions'; import { createGroup, } from '../Group/createGroup'; import { IGroup, } from '../Group/IGroup'; import { IGroupsMap, } from './IGroupsMap'; import { IGroupOptions, } from '../Group/IGroupOptions'; import { ISound, } from '../Sound/ISound'; import { ISoundsMap, } from '../Group/ISoundsMap'; import { nameOrAllKeys, } from '../functions/nameOrAllKeys'; import { shallowFlattenArray, } from '../functions/shallowFlattenArray'; import { assert, assertValid, } from 'ts-assertions'; export class CollectionSubmanager implements ICollectionSubmanager { /* Node collection */ private __groups: IGroupsMap = getFrozenObject(); get groups() { return this.__groups; } // @ts-ignore private readonly __getManagerVolume: () => number; constructor( { getManagerVolume, groups, }: { getManagerVolume: () => number, groups?: IGroupsMap, }, ) { this.__getManagerVolume = assertValid<() => number>( typeof getManagerVolume === 'function', 'The getManagerVolume argument to the CollectionSubmanager constructor was invalid.', ); this.__initializeGroups(groups); } private readonly __initializeGroups = (groups?: IGroupsMap) => { /* Add the 'default' group. */ this.__initializeDefaultGroup(); if (groups) { this.__groups = getFrozenObject(this.__groups, groups); } }; private readonly __initializeDefaultGroup = () => { this.addGroup('default'); return this; }; public readonly addGroup = (name: string, options: IGroupOptions = {}) => { const group = createGroup(options); this.addGroups({ [name]: group }); return group; }; public readonly addGroups = (groups: IGroupsMap) => { const names = Object.keys(groups); names.forEach((groupName) => { /* Throw if there is already a group with this name. */ assert(!(groupName in this.groups)); }); this.__groups = getFrozenObject(this.groups, groups); return this; }; public readonly hasGroup = (name: string) => ( name in this.groups ); public readonly hasGroups = (names: string[]) => ( names.filter((groupName) => ( !(groupName in this.groups) )).length === 0 ); public readonly getGroup = (name: string) => ( assertValid<IGroup>(this.__groups[name]) ); public readonly getGroups = (names: string[]) => ( names.map((name) => this.getGroup(name)) ); public readonly getAllGroups = () => ( this.getGroups(Object.keys(this.groups)) ); public readonly getGroupsByTag = (tag: string) => ( this.getAllGroups().filter((group) => group.hasTag(tag)) ); public readonly getGroupsByTags = ( tags: string[], matchOneOrAll: 'one' | 'all' = 'one', ) => this.getAllGroups().filter((group) => ( matchOneOrAll === 'all' ? tags.filter(group.hasTag).length === tags.length : tags.filter(group.hasTag).length >= 1 )); public readonly removeGroup = (name: string) => this.removeGroups([ name ]); public readonly removeGroups = (names: string | string[]) => { const arr: string[] = typeof names === 'string' ? [ names, ] : names; const groups = { ...this.groups }; arr.forEach((groupName) => { delete groups[groupName]; }); this.__groups = getFrozenObject(groups); if (!('default' in this.groups)) { /* Re-add a (now-empty) default group. */ this.__initializeDefaultGroup(); } return this; }; public readonly removeAllGroups = () => ( this.removeGroups(Object.keys(this.groups)) ); public readonly getGroupVolume = (name = 'default') => ( this.getGroup(name).getVolume() ); public readonly setGroupVolume = ( value: number, groupName = 'default', ) => { const group = this.getGroup(groupName); group.setVolume(value); return this; }; public readonly addSound = async ( name: string, options: ICreateSoundOptions, groupName = 'default', isPreloading = false, ): Promise<ISound> => { const opts: ICreateSoundOptions = getFrozenObject({ ...options }); this.__registerIntentToAddSound(name, groupName); const sound = await createSound(opts, isPreloading); this.addSounds({ [name]: sound }, groupName); this.__deregisterIntentToAddSound(name, groupName); return sound; }; public readonly hasIntentToAddSound = ( name: string, groupName = 'default', ) => this.getGroup(groupName).hasIntentToAddSound(name); private readonly __registerIntentToAddSound = ( name: string, groupName = 'default', ) => this.getGroup(groupName).registerIntentToAddSound(name); private readonly __deregisterIntentToAddSound = ( name: string, groupName = 'default', ) => this.getGroup(groupName).deregisterIntentToAddSound(name); public readonly addSounds = ( sounds: ISoundsMap, groupName = 'default', ) => this.getGroup(groupName).addSounds(sounds) && this; public readonly hasSound = (name: string, groupName = 'default') => ( this.getGroup(groupName).hasSound(name) ); public readonly getSound = (name: string, groupName = 'default') => ( this.getGroup(groupName).getSound(name) ); public readonly hasSounds = ( names: string[], groupName = 'default', ) => this.getGroup(groupName).hasSounds(names); public readonly getSounds = ( names: string[], groupName = 'default', ) => this.getGroup(groupName).getSounds(names); public readonly getAllSounds = () => shallowFlattenArray( this.getAllGroups().map((group) => group.getAllSounds()) ); public readonly getSoundsByTag = (tag: string) => shallowFlattenArray( this.getAllGroups().map((group) => group.getSoundsByTag(tag)) ); public readonly getSoundsByTags = ( tags: string[], matchOneOrAll: 'one' | 'all' = 'one', ) => shallowFlattenArray( this.getAllGroups().map((group) => ( group.getSoundsByTags(tags, matchOneOrAll) )) ); public readonly removeSound = (name: string, groupName = 'default') => ( this.getGroup(groupName).removeSound(name) && this ); public readonly removeSounds = ( names: string[], groupName = 'default', ) => { assert(Array.isArray(names)); names.forEach((name) => this.removeSound(name, groupName)); return this; }; public readonly removeAllSounds = (groupName?: string) => { const oneOrMany = nameOrAllKeys(groupName, this.groups); doToOneOrMany(this.groups, oneOrMany, 'removeAllSounds'); return this; }; public readonly getSoundVolume = ( name: string, groupName = 'default', ) => this.getGroup(groupName).getSound(name).getVolume(); public readonly setSoundVolume = ( name: string, value: number, groupName = 'default', ) => this.getGroup(groupName).getSound(name).setVolume(value) && this; public readonly updateAllAudioElementsVolume = () => { this.getAllGroups().forEach((grp) => grp.updateAllAudioElementsVolume()); return this; }; }