bitmovin-player-ui
Version:
Bitmovin Player UI Framework
132 lines (108 loc) • 3.87 kB
text/typescript
import { Event, EventDispatcher } from '../EventDispatcher';
import { PlayerAPI } from 'bitmovin-player';
export interface VolumeSettingChangedArgs {
volume: number;
muted: boolean;
}
/**
* Can be used to centrally manage and control the volume and mute state of the player from multiple components.
*/
export class VolumeController {
private static readonly issuerName = 'ui-volumecontroller';
private readonly events = {
onChanged: new EventDispatcher<VolumeController, VolumeSettingChangedArgs>(),
};
private storedVolume: number;
constructor(private readonly player: PlayerAPI) {
this.storeVolume();
const handler = () => {
this.onChangedEvent();
};
player.on(player.exports.PlayerEvent.SourceLoaded, handler);
player.on(player.exports.PlayerEvent.VolumeChanged, handler);
player.on(player.exports.PlayerEvent.Muted, handler);
player.on(player.exports.PlayerEvent.Unmuted, handler);
}
setVolume(volume: number): void {
this.player.setVolume(volume, VolumeController.issuerName);
}
getVolume(): number {
return this.player.getVolume();
}
setMuted(muted: boolean): void {
if (muted) {
this.player.mute(VolumeController.issuerName);
} else {
this.player.unmute(VolumeController.issuerName);
}
}
toggleMuted(): void {
if (this.isMuted() || this.getVolume() === 0) {
// Unmuting from the mute or zero-volume state recalls the previously saved volume setting. Setting the
// volume automatically unmutes the player in v7.
this.recallVolume();
} else {
this.setMuted(true);
}
}
isMuted(): boolean {
return this.player.isMuted();
}
/**
* Stores (saves) the current volume so it can later be restored with {@link recallVolume}.
*/
storeVolume(): void {
this.storedVolume = this.getVolume();
}
/**
* Recalls (sets) the volume previously stored with {@link storeVolume}.
*/
recallVolume(): void {
this.setMuted(this.storedVolume === 0);
this.setVolume(this.storedVolume);
}
startTransition(): VolumeTransition {
return new VolumeTransition(this);
}
onChangedEvent() {
const playerMuted = this.isMuted();
const playerVolume = this.getVolume();
const uiMuted = playerMuted || playerVolume === 0;
const uiVolume = playerMuted ? 0 : playerVolume;
this.storeVolume();
this.events.onChanged.dispatch(this, { volume: uiVolume, muted: uiMuted });
}
/**
* Gets the event that is fired when the volume settings have changed.
*/
get onChanged(): Event<VolumeController, VolumeSettingChangedArgs> {
return this.events.onChanged.getEvent();
}
}
export class VolumeTransition {
constructor(private controller: VolumeController) {
// Store the volume at the beginning of a volume change so we can recall it later in case we set the volume to
// zero and actually mute the player.
controller.storeVolume();
}
update(volume: number): void {
// Update the volume while transitioning so the user has a "live preview" of the desired target volume
this.controller.setMuted(false);
this.controller.setVolume(volume);
}
finish(volume: number): void {
if (volume === 0) {
// When the volume is zero we essentially mute the volume so we recall the volume from the beginning of the
// transition and mute the player instead. Recalling is necessary to return to the actual audio volume
// when unmuting.
// We must first recall the volume and then mute, because recalling sets the volume on the player
// and setting a player volume > 0 unmutes the player in v7.
this.controller.recallVolume();
this.controller.setMuted(true);
} else {
this.controller.setMuted(false);
this.controller.setVolume(volume);
this.controller.storeVolume();
}
}
}