playable
Version:
Video player based on HTML5Video
144 lines (118 loc) • 3.52 kB
text/typescript
import { IEventEmitter } from '../../../event-emitter/types';
import { VideoEvent, EngineState } from '../../../../constants';
type RemotePlayerController = cast.framework.RemotePlayerController;
import { IVideoOutput } from '../../types';
export default class StateEngine {
private _eventEmitter: IEventEmitter;
private _currentState: EngineState;
private _isMetadataLoaded: boolean;
private _remotePlayerController: RemotePlayerController;
private _currentVolume: number;
private _currentMute: boolean;
private _output: IVideoOutput;
constructor(
eventEmitter: IEventEmitter,
output: IVideoOutput,
controller: RemotePlayerController,
) {
this._eventEmitter = eventEmitter;
this._remotePlayerController = controller;
this._output = output;
this._currentState = null;
this._isMetadataLoaded = false;
this._bindCallbacks();
this._bindEvents();
}
private _bindCallbacks() {
this._processEventFromVideo = this._processEventFromVideo.bind(this);
}
private _bindEvents() {
const cast = window.cast;
const castEvents = cast.framework.RemotePlayerEventType;
this._remotePlayerController.addEventListener(castEvents.ANY_CHANGE, e => {
this._processEventFromVideo(e);
});
this._remotePlayerController.addEventListener(
castEvents.IS_PAUSED_CHANGED,
e => {
const isPaused = e.value;
this.setState(isPaused ? EngineState.PAUSED : EngineState.PLAYING);
this._processEventFromVideo(e);
},
);
}
private _processEventFromVideo(
event: cast.framework.RemotePlayerChangedEvent,
) {
switch (event.field) {
case 'playerState': {
if (event.value === 'PLAYING') {
this.setState(EngineState.PLAYING);
return;
}
if (event.value === 'PAUSED') {
this.setState(EngineState.PAUSED);
return;
}
if (event.value === null) {
this.setState(EngineState.ENDED);
return;
}
break;
}
case 'volumeLevel':
case 'isMuted':
this._checkVolumeChanges();
break;
case 'mediaInfo':
if (event.value && event.value.duration) {
this._eventEmitter.emitAsync(
VideoEvent.DURATION_UPDATED,
event.value,
);
}
break;
default:
break;
}
}
private _checkVolumeChanges() {
const output = this._output;
const newVolume = Math.floor(output.volume * 100);
if (this._currentVolume !== newVolume) {
this._currentVolume = newVolume;
this._eventEmitter.emitAsync(
VideoEvent.VOLUME_CHANGED,
this._currentVolume,
);
}
if (this._currentMute !== output.isMuted) {
this._currentMute = output.isMuted;
this._eventEmitter.emitAsync(VideoEvent.MUTE_CHANGED, this._currentMute);
}
this._eventEmitter.emitAsync(VideoEvent.SOUND_STATE_CHANGED, {
volume: this._currentVolume,
muted: this._currentMute,
});
}
setState(state: EngineState) {
if (state === this._currentState) {
return;
}
this._eventEmitter.emitAsync(VideoEvent.STATE_CHANGED, {
prevState: this._currentState,
nextState: state,
});
this._eventEmitter.emitAsync(state);
this._currentState = state;
}
get isMetadataLoaded() {
return this._isMetadataLoaded;
}
get state() {
return this._currentState;
}
destroy() {
this._eventEmitter = null;
}
}