Files
2026-03-25 17:28:35 +01:00

238 lines
7.1 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.WebEventEmitter = void 0;
var _VideoError = require("../types/VideoError.js");
/**
* video.js store interface — optional, used for enhanced buffering info when available.
*/
/**
* WebEventEmitter bridges HTML5 media events to our event system.
* Works with or without a video.js store — video element events are the primary source.
* When a video.js store is connected, it provides enhanced buffering info.
*/
class WebEventEmitter {
_listeners = new Map();
_mediaCleanup = null;
_storeUnsubscribe = null;
_store = null;
_isBuffering = false;
constructor(store, getMedia) {
this.getMedia = getMedia;
// Attach to video element immediately if available
this._attachMediaListeners();
if (store) this.setStore(store);
}
/**
* Connect or disconnect the video.js store (optional enhancement).
*/
setStore(store) {
this._storeUnsubscribe?.();
this._storeUnsubscribe = null;
this._store = store;
}
destroy() {
this._storeUnsubscribe?.();
this._storeUnsubscribe = null;
this._mediaCleanup?.();
this._mediaCleanup = null;
}
_attachMediaListeners() {
const video = this.getMedia();
if (!video) return;
const on = (event, handler) => {
video.addEventListener(event, handler);
return () => video.removeEventListener(event, handler);
};
const cleanups = [];
cleanups.push(on("play", () => {
this._emit("onPlaybackStateChange", {
isPlaying: true,
isBuffering: this._isBuffering
});
}));
cleanups.push(on("pause", () => {
this._emit("onPlaybackStateChange", {
isPlaying: false,
isBuffering: this._isBuffering
});
}));
cleanups.push(on("waiting", () => {
this._isBuffering = true;
this._emit("onBuffer", true);
this._emit("onStatusChange", "loading");
}));
cleanups.push(on("canplay", () => {
this._isBuffering = false;
this._emit("onBuffer", false);
this._emit("onStatusChange", "readyToPlay");
}));
cleanups.push(on("timeupdate", () => {
const buffered = video.buffered;
const lastBuffered = buffered.length > 0 ? buffered.end(buffered.length - 1) : 0;
this._emit("onProgress", {
currentTime: video.currentTime,
bufferDuration: lastBuffered
});
}));
cleanups.push(on("durationchange", () => {
if (video.duration > 0) {
this._emit("onLoad", {
currentTime: video.currentTime,
duration: video.duration,
width: video.videoWidth,
height: video.videoHeight,
orientation: "unknown"
});
}
}));
cleanups.push(on("ended", () => {
this._emit("onEnd");
this._emit("onStatusChange", "idle");
}));
cleanups.push(on("ratechange", () => {
this._emit("onPlaybackRateChange", video.playbackRate);
}));
cleanups.push(on("loadeddata", () => {
this._emit("onReadyToDisplay");
}));
cleanups.push(on("seeked", () => {
this._emit("onSeek", video.currentTime);
}));
cleanups.push(on("volumechange", () => {
this._emit("onVolumeChange", {
volume: video.volume,
muted: video.muted
});
}));
cleanups.push(on("loadstart", () => {
this._emit("onLoadStart", {
sourceType: "network",
source: {
uri: video.currentSrc || video.src,
config: {
uri: video.currentSrc || video.src,
externalSubtitles: []
},
getAssetInformationAsync: async () => ({
duration: video.duration || NaN,
width: video.videoWidth,
height: video.videoHeight,
orientation: "unknown",
bitrate: NaN,
fileSize: -1n,
isHDR: false,
isLive: false
})
}
});
}));
cleanups.push(on("error", () => {
this._emit("onStatusChange", "error");
const err = video.error;
if (!err) {
console.error("Unknown error occurred in player");
return;
}
const codeMap = {
1: "player/asset-not-initialized",
2: "player/not-initialized",
3: "player/invalid-source",
4: "source/unsupported-content-type"
};
this._emit("onError", new _VideoError.VideoError(codeMap[err.code] ?? "unknown/unknown", err.message));
}));
this._mediaCleanup = () => {
cleanups.forEach(fn => fn());
};
}
// --- Listener infrastructure ---
_addListener(event, listener) {
if (!this._listeners.has(event)) {
this._listeners.set(event, new Set());
}
this._listeners.get(event).add(listener);
return {
remove: () => {
this._listeners.get(event)?.delete(listener);
}
};
}
_emit(event, ...args) {
this._listeners.get(event)?.forEach(fn => fn(...args));
}
// --- Listener registration (implements VideoPlayerEventEmitterBase) ---
addOnAudioBecomingNoisyListener(listener) {
return this._addListener("onAudioBecomingNoisy", listener);
}
addOnAudioFocusChangeListener(listener) {
return this._addListener("onAudioFocusChange", listener);
}
addOnBandwidthUpdateListener(listener) {
return this._addListener("onBandwidthUpdate", listener);
}
addOnBufferListener(listener) {
return this._addListener("onBuffer", listener);
}
addOnControlsVisibleChangeListener(listener) {
return this._addListener("onControlsVisibleChange", listener);
}
addOnEndListener(listener) {
return this._addListener("onEnd", listener);
}
addOnExternalPlaybackChangeListener(listener) {
return this._addListener("onExternalPlaybackChange", listener);
}
addOnLoadListener(listener) {
return this._addListener("onLoad", listener);
}
addOnLoadStartListener(listener) {
return this._addListener("onLoadStart", listener);
}
addOnPlaybackStateChangeListener(listener) {
return this._addListener("onPlaybackStateChange", listener);
}
addOnPlaybackRateChangeListener(listener) {
return this._addListener("onPlaybackRateChange", listener);
}
addOnProgressListener(listener) {
return this._addListener("onProgress", listener);
}
addOnReadyToDisplayListener(listener) {
return this._addListener("onReadyToDisplay", listener);
}
addOnSeekListener(listener) {
return this._addListener("onSeek", listener);
}
addOnStatusChangeListener(listener) {
return this._addListener("onStatusChange", listener);
}
addOnTimedMetadataListener(listener) {
return this._addListener("onTimedMetadata", listener);
}
addOnTextTrackDataChangedListener(listener) {
return this._addListener("onTextTrackDataChanged", listener);
}
addOnTrackChangeListener(listener) {
return this._addListener("onTrackChange", listener);
}
addOnVolumeChangeListener(listener) {
return this._addListener("onVolumeChange", listener);
}
clearAllListeners() {
this._listeners.clear();
}
addOnErrorListener(listener) {
return this._addListener("onError", listener);
}
}
exports.WebEventEmitter = WebEventEmitter;
//# sourceMappingURL=WebEventEmitter.js.map