npaw-plugin-adapters
Version:
NPAW's Plugin Adapters
530 lines (438 loc) • 14.8 kB
JavaScript
export default class TritonAdapter {
checkExistsPlayer() {
return typeof this.player !== 'undefined';
}
getVersion() {
return '7.0.1-triton-jsclass';
}
getPlayhead() {
if (this.mediaElement && this.mediaElement.currentTime !== undefined) {
return this.mediaElement.currentTime;
}
return 0;
}
getDroppedFrames() {
return null;
}
getDuration() {
if (this.mediaElement && this.mediaElement.duration !== undefined) {
const duration = this.mediaElement.duration;
if (!isNaN(duration) && duration !== Infinity) {
return duration;
}
}
return null;
}
getBitrate() {
const audioNode = this.player?.MediaElement?.audioNode;
if (audioNode && typeof audioNode.webkitAudioDecodedByteCount !== 'undefined') {
const currentBytes = audioNode.webkitAudioDecodedByteCount;
if (this._lastWebkitAudioBytes !== undefined && currentBytes > this._lastWebkitAudioBytes) {
const deltaBytes = currentBytes - this._lastWebkitAudioBytes;
const pingTime = this.getPlugin()?.fastDataTransform?.response?.pingTime || 5;
const bitrate = Math.round((deltaBytes / pingTime) * 8);
this._lastWebkitAudioBytes = currentBytes;
return bitrate > 0 ? bitrate : null;
}
this._lastWebkitAudioBytes = currentBytes;
}
return null;
}
getThroughput() {
return null;
}
getRendition() {
return null;
}
getIsLive() {
return this.isLive || false;
}
getResource() {
if (this.mediaElement) {
return this.mediaElement.currentSrc || this.mediaElement.src;
}
return undefined;
}
getPlayrate() {
if (this.mediaElement && this.mediaElement.playbackRate !== undefined) {
return this.mediaElement.playbackRate;
}
return 1;
}
getPlayerName() {
return 'Triton Web Player';
}
getPlayerVersion() {
return '2.9';
}
getTitle() {
return this._currentTrackTitle || null;
}
getTitle2() {
return this._currentArtist || null;
}
getLatency() {
return null;
}
_bufferBeginListener() {
if (this.flags.isJoined && !this.flags.isPaused) {
if (this.isLive || !this.isSeeking) {
this._adapterIsBuffering = true;
this.fireBufferBegin({}, false, '_bufferBeginListener');
}
}
}
_bufferEndListener() {
if (this.flags.isBuffering || this._adapterIsBuffering) {
this._adapterIsBuffering = false;
this.fireBufferEnd({}, '_bufferEndListener');
}
}
_joinListener() {
if (!this.flags.isJoined) {
this.fireJoin({}, '_joinListener');
}
}
_resumeListener() {
if (this.flags.isPaused) {
this.fireResume({}, '_resumeListener');
}
}
_stopListener() {
if (this._suppressNextSdkStop) {
this._suppressNextSdkStop = false;
return;
}
this.fireStop({}, '_stopListener');
}
_pauseListener() {
this.firePause({}, '_pauseListener');
}
_errorListener(ev) {
if (this._hasErrorFired) {
return;
}
const code = ev.data?.code || ev.code || 'UNKNOWN_ERROR';
const msg = ev.data?.message || ev.message || 'Playback error occurred';
this._hasErrorFired = true;
this.fireFatalError(code, msg, undefined, undefined, '_errorListener');
this.fireStop({}, '_errorListener');
}
_isNewContent(params) {
if (!this._currentPlayParams) return true;
if (params.station || params.mount) {
const newId = params.station || params.mount;
const oldId = this._currentPlayParams.station || this._currentPlayParams.mount;
return newId !== oldId;
}
if (params.file) {
return params.file !== this._currentPlayParams.file;
}
return true;
}
_cleanupMediaElement() {
if (this.mediaElement) {
if (this._seekingHandler) {
this.mediaElement.removeEventListener('seeking', this._seekingHandler);
}
if (this._playingHandler) {
this.mediaElement.removeEventListener('playing', this._playingHandler);
}
if (this._html5ErrorHandler) {
this.mediaElement.removeEventListener('error', this._html5ErrorHandler);
}
if (this._html5WaitingHandler) {
this.mediaElement.removeEventListener('waiting', this._html5WaitingHandler);
}
if (this._html5CanPlayHandler) {
this.mediaElement.removeEventListener('canplay', this._html5CanPlayHandler);
}
if (this._html5PlayingHandler) {
this.mediaElement.removeEventListener('playing', this._html5PlayingHandler);
}
this.mediaElement = null;
}
}
_tryGetMediaElement() {
if (this.mediaElement) return;
try {
const node = this.player?.MediaPlayer?.mediaElement
|| this.player?.MediaElement?.audioNode;
if (node && node.tagName) {
this._attachMediaElement(node);
return;
}
} catch (_) { /* ignore */ }
try {
const container = document.getElementById('td_container');
if (container) {
const audio = container.querySelector('audio');
if (audio) {
this._attachMediaElement(audio);
}
}
} catch (_) { /* ignore */ }
}
_attachMediaElement(element) {
if (this.mediaElement) return;
this.mediaElement = element;
if (this.isLive === undefined) {
if (this.mediaElement.duration === Infinity) {
this.isLive = true;
} else if (!isNaN(this.mediaElement.duration)) {
this.isLive = false;
}
}
if (this.isLive === false) {
this.mediaElement.addEventListener('seeking', this._seekingHandler);
this.mediaElement.addEventListener('playing', this._playingHandler);
}
this.mediaElement.addEventListener('error', this._html5ErrorHandler);
this.mediaElement.addEventListener('waiting', this._html5WaitingHandler);
this.mediaElement.addEventListener('canplay', this._html5CanPlayHandler);
this.mediaElement.addEventListener('playing', this._html5PlayingHandler);
}
registerListeners() {
this.isSeeking = false;
this.flags = this.flags || {};
this._adapterIsBuffering = false;
this._lastStreamStatus = null;
this._hasErrorFired = false;
this._lastWebkitAudioBytes = undefined;
this._currentPlayParams = null;
this._suppressNextSdkStop = false;
this._currentTrackTitle = null;
this._currentArtist = null;
this._currentAlbum = null;
this._originalPlay = this.player.play.bind(this.player);
this.player.play = (params) => {
if (params) {
const isNewContent = this._isNewContent(params);
if ((this.flags.isStarted || this._npawVideo?.isInitiated) && isNewContent) {
this._suppressNextSdkStop = true;
this._cleanupMediaElement();
this.fireStop({}, 'playWrapper-contentChange');
this._originalStop();
}
if (!this.flags.isStarted) {
this._hasErrorFired = false;
if (params.station || params.mount) {
this.isLive = true;
} else if (params.file) {
this.isLive = false;
}
this._currentPlayParams = { ...params };
this.fireInit({}, 'playWrapper');
this.fireStart({}, 'playWrapper');
}
}
return this._originalPlay(params);
};
this._originalStop = this.player.stop.bind(this.player);
this.player.stop = () => {
if (this.flags.isStarted || this._npawVideo?.isInitiated) {
this._suppressNextSdkStop = true;
this._cleanupMediaElement();
this.fireStop({}, 'stopWrapper');
}
return this._originalStop();
};
this._seekingHandler = () => {
if (this.flags.isStarted && !this.isSeeking && !this.isLive) {
this.isSeeking = true;
this.fireSeekBegin({}, false, 'html5SeekingEvent');
}
};
this._playingHandler = () => {
if (this.isSeeking) {
this.isSeeking = false;
this.fireSeekEnd({}, 'html5PlayingEvent');
}
};
this._html5ErrorHandler = () => {
const error = this.mediaElement?.error;
const networkState = this.mediaElement?.networkState;
if (this._hasErrorFired) {
return;
}
let shouldFireError = false;
let errorCode = '';
let errorMsg = '';
if (error) {
const errorMessages = {
1: 'MEDIA_ERR_ABORTED - Playback aborted by user',
2: 'MEDIA_ERR_NETWORK - Network error while loading media',
3: 'MEDIA_ERR_DECODE - Media decoding error',
4: 'MEDIA_ERR_SRC_NOT_SUPPORTED - Media source not supported or not found'
};
if (error.code === 2 || error.code === 4) {
shouldFireError = true;
errorCode = `HTML5_ERROR_${error.code}`;
errorMsg = error.message || errorMessages[error.code];
}
} else if (networkState === 3) {
shouldFireError = true;
errorCode = 'NETWORK_NO_SOURCE';
errorMsg = 'Media source not accessible';
}
if (shouldFireError) {
this._hasErrorFired = true;
this.fireFatalError(errorCode, errorMsg, undefined, undefined, 'html5ErrorEvent');
this.fireStop({}, 'html5ErrorEvent');
}
};
this._html5WaitingHandler = () => {
if (!this.isSeeking) {
this._bufferBeginListener();
}
};
this._html5CanPlayHandler = () => {
this._bufferEndListener();
};
this._html5PlayingHandler = () => {
this._bufferEndListener();
};
this._playbackStatusHandler = (ev) => {
if (ev.data) {
this.flags = this.flags || {};
if (ev.data.mediaElement && !this.mediaElement
&& ev.data.status !== 'Stopped' && ev.data.status !== 'Ended') {
this._attachMediaElement(ev.data.mediaElement);
}
switch (ev.data.status) {
case 'Buffering':
case 'Loading':
this._bufferBeginListener();
break;
case 'Playing':
this._joinListener();
this._resumeListener();
this._bufferEndListener();
break;
case 'Paused':
this._pauseListener();
break;
case 'Stopped':
case 'Ended':
this._stopListener();
break;
}
}
};
this._streamStatusHandler = (ev) => {
const currentStatus = ev.data?.status;
const previousStatus = this._lastStreamStatus;
this._lastStreamStatus = currentStatus;
if (ev.data && currentStatus === 'Buffering') {
this._bufferBeginListener();
} else if (previousStatus === 'Buffering' && currentStatus !== 'Buffering') {
this._bufferEndListener();
}
};
this._streamStartHandler = () => {
if (!this.mediaElement) {
this._tryGetMediaElement();
}
this._joinListener();
};
this._streamStopHandler = () => {
this._stopListener();
};
this._streamPauseHandler = () => {
this._pauseListener();
};
this._streamResumeHandler = () => {
this._resumeListener();
this._bufferEndListener();
};
this._trackCuePointHandler = (ev) => {
if (ev.data && ev.data.cuePoint) {
const cuePoint = ev.data.cuePoint;
this._currentTrackTitle = cuePoint.cueTitle || null;
this._currentArtist = cuePoint.artistName || null;
this._currentAlbum = cuePoint.albumName || null;
}
};
this._errorHandler = (ev) => {
this._errorListener(ev);
};
this._streamFailHandler = (ev) => {
this._errorListener(ev);
};
this._geoBlockedHandler = () => {
if (!this._hasErrorFired) {
this._hasErrorFired = true;
this.fireFatalError(
'GEO_BLOCKED',
'Stream is geo-blocked in this region',
undefined, undefined, 'geoBlockedEvent'
);
this.fireStop({}, 'geoBlockedEvent');
}
};
this.player.addEventListener('media-playback-status', this._playbackStatusHandler);
this.player.addEventListener('stream-status', this._streamStatusHandler);
this.player.addEventListener('stream-start', this._streamStartHandler);
this.player.addEventListener('stream-stop', this._streamStopHandler);
this.player.addEventListener('stream-pause', this._streamPauseHandler);
this.player.addEventListener('stream-resume', this._streamResumeHandler);
this.player.addEventListener('media-error', this._errorHandler);
this.player.addEventListener('stream-fail', this._streamFailHandler);
this.player.addEventListener('stream-geo-blocked', this._geoBlockedHandler);
this.player.addEventListener('track-cue-point', this._trackCuePointHandler);
}
unregisterListeners() {
if (this._originalPlay && this.player) {
this.player.play = this._originalPlay;
this._originalPlay = null;
}
if (this._originalStop && this.player) {
this.player.stop = this._originalStop;
this._originalStop = null;
}
if (this._playbackStatusHandler) {
this.player.removeEventListener('media-playback-status', this._playbackStatusHandler);
this._playbackStatusHandler = null;
}
if (this._streamStatusHandler) {
this.player.removeEventListener('stream-status', this._streamStatusHandler);
this._streamStatusHandler = null;
}
if (this._streamStartHandler) {
this.player.removeEventListener('stream-start', this._streamStartHandler);
this._streamStartHandler = null;
}
if (this._streamStopHandler) {
this.player.removeEventListener('stream-stop', this._streamStopHandler);
this._streamStopHandler = null;
}
if (this._streamPauseHandler) {
this.player.removeEventListener('stream-pause', this._streamPauseHandler);
this._streamPauseHandler = null;
}
if (this._streamResumeHandler) {
this.player.removeEventListener('stream-resume', this._streamResumeHandler);
this._streamResumeHandler = null;
}
if (this._errorHandler) {
this.player.removeEventListener('media-error', this._errorHandler);
this._errorHandler = null;
}
if (this._streamFailHandler) {
this.player.removeEventListener('stream-fail', this._streamFailHandler);
this._streamFailHandler = null;
}
if (this._geoBlockedHandler) {
this.player.removeEventListener('stream-geo-blocked', this._geoBlockedHandler);
this._geoBlockedHandler = null;
}
if (this._trackCuePointHandler) {
this.player.removeEventListener('track-cue-point', this._trackCuePointHandler);
this._trackCuePointHandler = null;
}
this._cleanupMediaElement();
this._hasErrorFired = false;
this._lastWebkitAudioBytes = undefined;
this._currentPlayParams = null;
}
}