sound-manager
Version:
A full-service sound library.
223 lines (180 loc) • 5.34 kB
text/typescript
import {
assert,
assertValid,
} from 'ts-assertions';
import {
getFrozenObject,
} from '../functions/getFrozenObject';
import {
IGroup,
} from './IGroup';
import {
IGroupOptions,
} from './IGroupOptions';
import {
ISound,
} from '../Sound/ISound';
import {
ISoundsMap,
} from './ISoundsMap';
import {
isValidVolume,
} from '../functions/isValidVolume';
import {
BaseNode,
} from '../Node/BaseNode';
import {
NodeTypes,
} from '../enums/NodeTypes';
import {
PanelRegisterableNodeMixin,
} from '../Node/PanelRegisterableNodeMixin';
import {
TaggableNodeMixin,
} from '../Node/TaggableNodeMixin';
export class Group
extends
PanelRegisterableNodeMixin(
TaggableNodeMixin(
BaseNode
))
implements IGroup
{
get type(): NodeTypes.Group {
return NodeTypes.Group;
}
private __sounds: ISoundsMap = getFrozenObject();
get sounds() {
return this.__sounds;
}
constructor(options: IGroupOptions) {
super({ ...options });
const {
sounds,
tags,
volume,
} = options;
if (sounds && typeof sounds === 'object') {
this.addSounds(sounds);
}
if (tags) {
tags.forEach(this.addTag);
}
if (isValidVolume(volume)) {
this.setVolume(volume);
}
}
public readonly setVolume = (value: number) => {
super.setVolume(value);
this.updateAllAudioElementsVolume();
return this;
};
public readonly hasSound = (name: string) => (
name in this.sounds
);
public readonly hasSounds = (names: string[]) => (
!names.find((name) => !this.hasSound(name))
);
public readonly getSound = (name: string) => assertValid<ISound>(
this.sounds[name],
);
public readonly getSounds = (names: string[]) => (
assert(Array.isArray(names)) && names.map((name) => this.getSound(name))
);
public readonly getAllSounds = () => (
this.getSounds(Object.keys(this.sounds))
);
public readonly getSoundsByTag = (tag: string) => (
this.getAllSounds().filter((sound) => sound.hasTag(tag))
);
public readonly getSoundsByTags = (
tags: string[],
matchOneOrAll: 'one' | 'all' = 'one',
) => this.getAllSounds().filter((sound) => (
matchOneOrAll === 'all' ?
tags.filter(sound.hasTag).length === tags.length :
tags.filter(sound.hasTag).length >= 1
));
private readonly __registeredAdditionIntents: Record<string, boolean> = {};
public readonly registerIntentToAddSound = (name: string) => {
assert(!(name in this.__registeredAdditionIntents));
this.__registeredAdditionIntents[name] = true;
return this;
};
public readonly deregisterIntentToAddSound = (name: string) => (
void delete this.__registeredAdditionIntents[name]
);
public readonly hasIntentToAddSound = (name: string) => (
name in this.__registeredAdditionIntents
);
public readonly addSound = (name: string, sound: ISound) => (
this.addSounds({ [name]: sound })
);
public readonly addSounds = (sounds: ISoundsMap) => {
const names = Object.keys(sounds);
const volumeGetter = () => this.getVolume();
names.forEach((soundName) => {
assert(soundName)
assert(!(soundName in this.sounds));
assert(sounds[soundName]);
const sound = sounds[soundName];
sound.getGroupVolume = volumeGetter;
});
this.__sounds = getFrozenObject(this.sounds, sounds);
return this;
};
public readonly removeSound = (name: string) => {
this.removeSounds([ name ]);
return this;
};
public readonly removeSounds = (names: string[]) => {
assert(Array.isArray(names));
const sounds = { ...this.sounds, };
names.forEach((soundName: string) => {
delete sounds[soundName];
});
this.__sounds = getFrozenObject(sounds);
return this;
};
public readonly removeAllSounds = () => (
this.removeSounds(Object.keys(this.sounds))
);
public readonly playSound = (name: string) => this.getSound(name).play();
public readonly playSounds = (names: string[]) => {
assert(Array.isArray(names));
return Promise.all(names.map((name) => this.playSound(name)));
};
public readonly playAllSounds = () => (
this.playSounds(Object.keys(this.sounds))
);
public readonly pauseSound = (name: string) => {
this.getSound(name).pause();
return this;
};
public readonly pauseSounds = (names: string[]) => {
assert(Array.isArray(names));
names.map((name) => this.pauseSound(name));
return this;
};
public readonly pauseAllSounds = () => (
this.pauseSounds(Object.keys(this.sounds))
);
public readonly stopSound = (name: string) => {
this.getSound(name).stop();
return this;
};
public readonly stopSounds = (names: string[]) => {
assert(Array.isArray(names));
names.map((name) => this.stopSound(name));
return this;
};
public readonly stopAllSounds = () => (
this.stopSounds(Object.keys(this.sounds))
);
public readonly updateAllAudioElementsVolume = () => {
this.getAllSounds().forEach((sound) => {
sound.updateAudioElementVolume();
});
return this;
};
}