Move cast API code to cast/sdk/ and create wrapper class

This commit is contained in:
hensm
2022-04-25 15:59:58 +01:00
parent 43f5d325f8
commit 4bccdecaa3
35 changed files with 707 additions and 1188 deletions

View File

@@ -0,0 +1,440 @@
"use strict";
import { v1 as uuid } from "uuid";
import logger from "../../../lib/logger";
import { Volume, Error as _Error } from "../classes";
import {
BreakStatus,
EditTracksInfoRequest,
GetStatusRequest,
LiveSeekableRange,
MediaInfo,
PauseRequest,
PlayRequest,
QueueData,
QueueJumpRequest,
QueueInsertItemsRequest,
QueueItem,
QueueSetPropertiesRequest,
QueueRemoveItemsRequest,
QueueReorderItemsRequest,
QueueUpdateItemsRequest,
SeekRequest,
StopRequest,
VideoInformation,
VolumeRequest
} from "./classes";
import { PlayerState, RepeatMode } from "./enums";
import { ErrorCode } from "../enums";
import { ErrorCallback, SuccessCallback, UpdateListener } from "../../types";
import { SenderMediaMessage } from "../types";
export const NS_MEDIA = "urn:x-cast:com.google.cast.media";
export default class Media {
#id = uuid();
// Timestamp of last status update
_lastUpdateTime = 0;
_updateListeners = new Set<UpdateListener>();
activeTrackIds: Nullable<number[]> = null;
breakStatus?: BreakStatus;
currentTime = 0;
customData: any = null;
idleReason: Nullable<string> = null;
liveSeekableRange?: LiveSeekableRange;
media: Nullable<MediaInfo> = null;
playbackRate = 1;
playerState = PlayerState.IDLE;
repeatMode = RepeatMode.OFF;
supportedMediaCommands: string[] = [];
videoInfo?: VideoInformation;
volume: Volume = new Volume();
// Queues
items: Nullable<QueueItem[]> = null;
currentItemId: Nullable<number> = null;
loadingItemId: Nullable<number> = null;
preloadedItemId: Nullable<number> = null;
queueData?: QueueData;
constructor(
public sessionId: string,
public mediaSessionId: number,
public _sendMediaMessage: (
message: DistributiveOmit<SenderMediaMessage, "requestId">
) => Promise<void>
) {}
addUpdateListener(listener: UpdateListener) {
this._updateListeners.add(listener);
}
removeUpdateListener(listener: UpdateListener) {
this._updateListeners.delete(listener);
}
editTracksInfo(
editTracksInfoRequest: EditTracksInfoRequest,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...editTracksInfoRequest,
type: "EDIT_TRACKS_INFO",
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
getEstimatedBreakClipTime() {
logger.info("STUB :: Media#getEstimatedBreakClipTime");
}
getEstimatedBreakTime() {
logger.info("STUB :: Media#getEstimatedBreakTime");
}
getEstimatedLiveSeekableRange() {
logger.info("STUB :: Media#getEstimatedLiveSeekableRange");
}
/**
* Estimate the current playback position based on the last
* time reported by the receiver and the current playback
* rate.
*/
getEstimatedTime(): number {
if (this.playerState === PlayerState.PLAYING && this._lastUpdateTime) {
let estimatedTime =
this.currentTime + (Date.now() - this._lastUpdateTime) / 1000;
// Enforce valid range
if (estimatedTime < 0) {
estimatedTime = 0;
} else if (
this.media?.duration &&
estimatedTime > this.media.duration
) {
estimatedTime = this.media.duration;
}
return estimatedTime;
}
return this.currentTime;
}
/**
* Request media status from the receiver application. This
* will also trigger any added media update listeners.
*/
getStatus(
getStatusRequest = new GetStatusRequest(),
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...getStatusRequest,
type: "MEDIA_GET_STATUS",
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
pause(
pauseRequest = new PauseRequest(),
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...pauseRequest,
type: "PAUSE",
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
play(
playRequest = new PlayRequest(),
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...playRequest,
type: "PLAY",
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
queueAppendItem(
item: QueueItem,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...new QueueInsertItemsRequest([item]),
type: "QUEUE_INSERT",
sessionId: this.sessionId,
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
queueInsertItems(
queueInsertItemsRequest: QueueInsertItemsRequest,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...queueInsertItemsRequest,
type: "QUEUE_INSERT",
sessionId: this.sessionId,
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
queueJumpToItem(
itemId: number,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
if (this.items?.find(item => item.itemId === itemId)) {
const jumpRequest = new QueueJumpRequest();
jumpRequest.currentItemId = itemId;
this._sendMediaMessage({
...jumpRequest,
type: "QUEUE_UPDATE",
sessionId: this.sessionId,
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
}
queueMoveItemToNewIndex(
itemId: number,
newIndex: number,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
// Return early if not in queue
if (!this.items) {
return;
}
const itemIndex = this.items.findIndex(item => item.itemId === itemId);
if (itemIndex !== -1) {
// New index must not be negative
if (newIndex < 0) {
if (errorCallback) {
errorCallback(new _Error(ErrorCode.INVALID_PARAMETER));
}
} else if (newIndex == itemIndex) {
if (successCallback) {
successCallback();
}
}
} else {
if (newIndex > itemIndex) {
newIndex++;
}
const reorderItemsRequest = new QueueReorderItemsRequest([itemId]);
if (newIndex < this.items.length) {
const existingItem = this.items[newIndex];
reorderItemsRequest.insertBefore = existingItem.itemId;
}
this._sendMediaMessage({
...reorderItemsRequest,
type: "QUEUE_REORDER",
sessionId: this.sessionId,
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
}
queueNext(
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
const jumpRequest = new QueueJumpRequest();
jumpRequest.jump = 1;
this._sendMediaMessage({
...jumpRequest,
type: "QUEUE_UPDATE",
sessionId: this.sessionId,
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
queuePrev(
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
const jumpRequest = new QueueJumpRequest();
jumpRequest.jump = -1;
this._sendMediaMessage({
...jumpRequest,
type: "QUEUE_UPDATE",
sessionId: this.sessionId,
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
queueRemoveItem(
itemId: number,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
const item = this.items?.find(item => item.itemId === itemId);
if (item) {
this.queueRemoveItems(
new QueueRemoveItemsRequest([itemId]),
successCallback,
errorCallback
);
}
}
queueRemoveItems(
queueRemoveItemsRequest: QueueRemoveItemsRequest,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...queueRemoveItemsRequest,
mediaSessionId: this.mediaSessionId,
type: "QUEUE_REMOVE",
sessionId: this.sessionId
})
.then(successCallback)
.catch(errorCallback);
}
queueReorderItems(
queueReorderItemsRequest: QueueReorderItemsRequest,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...queueReorderItemsRequest,
mediaSessionId: this.mediaSessionId,
type: "QUEUE_REORDER",
sessionId: this.sessionId
})
.then(successCallback)
.catch(errorCallback);
}
queueSetRepeatMode(
repeatMode: string,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
const setPropertiesRequest = new QueueSetPropertiesRequest();
setPropertiesRequest.repeatMode = repeatMode;
this._sendMediaMessage({
...setPropertiesRequest,
type: "QUEUE_UPDATE",
sessionId: this.sessionId,
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
queueUpdateItems(
queueUpdateItemsRequest: QueueUpdateItemsRequest,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...queueUpdateItemsRequest,
type: "QUEUE_UPDATE",
sessionId: this.sessionId,
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
seek(
seekRequest: SeekRequest,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...seekRequest,
type: "SEEK",
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
setVolume(
volumeRequest: VolumeRequest,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
this._sendMediaMessage({
...volumeRequest,
type: "MEDIA_SET_VOLUME",
mediaSessionId: this.mediaSessionId
})
.then(successCallback)
.catch(errorCallback);
}
stop(
stopRequest?: StopRequest,
successCallback?: SuccessCallback,
errorCallback?: ErrorCallback
) {
if (!stopRequest) {
stopRequest = new StopRequest();
}
this._sendMediaMessage({
...stopRequest,
type: "STOP",
mediaSessionId: this.mediaSessionId
})
.then(() => {
if (successCallback) {
successCallback();
}
})
.catch(errorCallback);
}
supportsCommand(command: string): boolean {
return this.supportedMediaCommands.includes(command);
}
}

View File

@@ -0,0 +1,380 @@
"use strict";
import { Image, Volume } from "../classes";
import {
ContainerType,
HdrType,
HlsSegmentFormat,
HlsVideoSegmentFormat,
MetadataType,
RepeatMode,
ResumeState,
StreamType,
TrackType,
UserAction
} from "./enums";
export class AudiobookChapterMediaMetadata {
bookTitle?: string;
chapterNumber?: number;
chapterTitle?: string;
images?: Image[];
subtitle?: string;
title?: string;
type = MetadataType.AUDIOBOOK_CHAPTER;
}
export class AudiobookContainerMetadata {
authors?: string[];
narrators?: string[];
publisher?: string;
releaseDate?: string;
}
export class Break {
duration?: number;
isEmbedded?: boolean;
isWatched = false;
constructor(
public id: string,
public breakClipIds: string[],
public position: number
) {}
}
export class BreakClip {
clickThroughUrl?: string;
contentId?: string;
contentType?: string;
contentUrl?: string;
customData?: {};
duration?: number;
hlsSegmentFormat?: HlsSegmentFormat;
posterUrl?: string;
title?: string;
vastAdsRequest?: VastAdsRequest;
whenSkippable?: number;
constructor(public id: string) {}
}
export class BreakStatus {
breakClipId?: string;
breakId?: string;
currentBreakClipTime?: number;
currentBreakTime?: number;
whenSkippable?: number;
}
export class ContainerMetadata {
containerDuration?: number;
containerImages?: Image[];
sections?: MediaMetadata[];
title?: string;
constructor(
public containerType: ContainerType = ContainerType.GENERIC_CONTAINER
) {}
}
export class EditTracksInfoRequest {
requestId = 0;
constructor(
public activeTrackIds: Nullable<number[]> = null,
public textTrackStyle: Nullable<string> = null
) {}
}
export class GenericMediaMetadata {
images?: Image[];
metadataType = MetadataType.GENERIC;
releaseDate?: string;
releaseYear?: number;
subtitle?: string;
title?: string;
type = MetadataType.GENERIC;
}
export class GetStatusRequest {
customData: any = null;
}
export class LiveSeekableRange {
constructor(
public start?: number,
public end?: number,
public isMovingWindow?: boolean,
public isLiveDone?: boolean
) {}
}
export class LoadRequest {
activeTrackIds: Nullable<number[]> = null;
atvCredentials?: string;
atvCredentialsType?: string;
autoplay: Nullable<boolean> = true;
currentTime: Nullable<number> = null;
customData: any = null;
media: MediaInfo;
requestId = 0;
sessionId: Nullable<string> = null;
type: "LOAD" = "LOAD";
constructor(mediaInfo: MediaInfo) {
this.media = mediaInfo;
}
}
export type Metadata =
| GenericMediaMetadata
| MovieMediaMetadata
| MusicTrackMediaMetadata
| PhotoMediaMetadata
| TvShowMediaMetadata;
export class MediaInfo {
atvEntity?: string;
breakClips?: BreakClip[];
breaks?: Break[];
customData: any = null;
contentUrl?: string;
duration: Nullable<number> = null;
entity?: string;
hlsSegmentFormat?: HlsSegmentFormat;
hlsVideoSegmentFormat?: HlsVideoSegmentFormat;
metadata: Nullable<Metadata> = null;
startAbsoluteTime?: number;
streamType: string = StreamType.BUFFERED;
textTrackStyle: Nullable<TextTrackStyle> = null;
tracks: Nullable<Track[]> = null;
userActionStates?: UserActionState[];
vmapAdsRequest?: VastAdsRequest;
constructor(public contentId: string, public contentType: string) {}
}
export class MediaMetadata {
queueItemId?: number;
sectionDuration?: number;
sectionStartAbsoluteTime?: number;
sectionStartTimeInContainer?: number;
sectionStartTimeInMedia?: number;
type: MetadataType;
metadataType: MetadataType;
constructor(type: MetadataType) {
this.type = type;
this.metadataType = type;
}
}
export class MovieMediaMetadata {
images?: Image[];
metadataType = MetadataType.MOVIE;
releaseDate?: string;
releaseYear?: number;
studio?: string;
subtitle?: string;
title?: string;
type = MetadataType.MOVIE;
}
export class MusicTrackMediaMetadata {
albumArtist?: string;
albumName?: string;
artist?: string;
artistName?: string;
composer?: string;
discNumber?: number;
images?: Image[];
metadataType = MetadataType.MUSIC_TRACK;
releaseDate?: string;
releaseYear?: number;
songName?: string;
title?: string;
trackNumber?: number;
type = MetadataType.MUSIC_TRACK;
}
export class PauseRequest {
customData: any = null;
}
export class PhotoMediaMetadata {
artist?: string;
creationDateTime?: string;
height?: number;
images?: Image[];
latitude?: number;
location?: string;
longitude?: number;
metadataType = MetadataType.PHOTO;
title?: string;
type = MetadataType.PHOTO;
width?: number;
}
export class PlayRequest {
customData: any = null;
}
export class QueueData {
shuffle = false;
constructor(
public id?: string,
public name?: string,
public description?: string,
public repeatMode?: RepeatMode,
public items?: QueueItem[],
public startIndex?: number,
public startTime?: number
) {}
}
export class QueueInsertItemsRequest {
customData: any = null;
insertBefore: Nullable<number> = null;
requestId: Nullable<number> = null;
sessionId: Nullable<string> = null;
type = "QUEUE_INSERT";
constructor(public items: QueueItem[]) {}
}
export class QueueItem {
activeTrackIds: Nullable<number[]> = null;
autoplay = true;
customData: any = null;
itemId: Nullable<number> = null;
media: MediaInfo;
playbackDuration: Nullable<number> = null;
preloadTime = 0;
startTime = 0;
constructor(mediaInfo: MediaInfo) {
this.media = mediaInfo;
}
}
export class QueueJumpRequest {
type = "QUEUE_UPDATE";
jump: Nullable<number> = null;
currentItemId: Nullable<number> = null;
}
export class QueueLoadRequest {
type = "QUEUE_LOAD";
customData: any = null;
repeatMode: string = RepeatMode.OFF;
startIndex = 0;
constructor(public items: QueueItem[]) {}
}
export class QueueRemoveItemsRequest {
type = "QUEUE_REMOVE";
customData: any = null;
constructor(public itemIds: number[]) {}
}
export class QueueReorderItemsRequest {
customData: any = null;
insertBefore: Nullable<number> = null;
type = "QUEUE_REORDER";
constructor(public itemIds: number[]) {}
}
export class QueueSetPropertiesRequest {
type = "QUEUE_UPDATE";
customData: any = null;
repeatMode: Nullable<string> = null;
}
export class QueueUpdateItemsRequest {
type = "QUEUE_UPDATE";
customData: any = null;
constructor(public items: QueueItem[]) {}
}
export class SeekRequest {
currentTime: Nullable<number> = null;
customData: any = null;
resumeState: Nullable<ResumeState> = null;
}
export class StopRequest {
customData: any = null;
}
export class TextTrackStyle {
backgroundColor: Nullable<string> = null;
customData: any = null;
edgeColor: Nullable<string> = null;
edgeType: Nullable<string> = null;
fontFamily: Nullable<string> = null;
fontGenericFamily: Nullable<string> = null;
fontScale: Nullable<number> = null;
fontStyle: Nullable<string> = null;
foregroundColor: Nullable<string> = null;
windowColor: Nullable<string> = null;
windowRoundedCornerRadius: Nullable<number> = null;
windowType: Nullable<string> = null;
}
export class Track {
customData: any = null;
language: Nullable<string> = null;
name: Nullable<string> = null;
subtype: Nullable<string> = null;
trackContentId: Nullable<string> = null;
trackContentType: Nullable<string> = null;
constructor(public trackId: number, public type: TrackType) {}
}
export class TvShowMediaMetadata {
episode?: number;
episodeNumber?: number;
episodeTitle?: string;
images?: Image[];
metadataType: number = MetadataType.TV_SHOW;
originalAirdate?: string;
releaseYear?: number;
season?: number;
seasonNumber?: number;
seriesTitle?: string;
title?: string;
type = MetadataType.TV_SHOW;
}
export class UserActionState {
customData: any = null;
constructor(public userAction: UserAction) {}
}
export class VastAdsRequest {
adsResponse?: string;
adTagUrl?: string;
}
export class VideoInformation {
constructor(
public width: number,
public height: number,
public hdrType: HdrType
) {}
}
export class VolumeRequest {
customData: any = null;
constructor(public volume: Volume) {}
}

View File

@@ -0,0 +1,139 @@
"use strict";
export enum ContainerType {
GENERIC_CONTAINER,
AUDIOBOOK_CONTAINER
}
export enum HdrType {
SDR = "sdr",
HDR = "hdr",
DV = "dv"
}
export enum HlsSegmentFormat {
AAC = "aac",
AC3 = "ac3",
MP3 = "mp3",
TS = "ts",
TS_AAC = "ts_aac",
E_AC3 = "e_ac3",
FMP4 = "fmp4"
}
export enum HlsVideoSegmentFormat {
MPEG2_TS = "mpeg2_ts",
FMP4 = "fmp4"
}
export enum IdleReason {
CANCELLED = "CANCELLED",
INTERRUPTED = "INTERRUPTED",
FINISHED = "FINISHED",
ERROR = "ERROR"
}
export enum MediaCommand {
PAUSE = "pause",
SEEK = "seek",
STREAM_VOLUME = "stream_volume",
STREAM_MUTE = "stream_mute"
}
export enum MetadataType {
GENERIC,
MOVIE,
TV_SHOW,
MUSIC_TRACK,
PHOTO,
AUDIOBOOK_CHAPTER
}
export enum PlayerState {
IDLE = "IDLE",
PLAYING = "PLAYING",
PAUSED = "PAUSED",
BUFFERING = "BUFFERING"
}
export enum QueueType {
ALBUM = "ALBUM",
PLAYLIST = "PLAYLIST",
AUDIOBOOK = "AUDIOBOOK",
RADIO_STATION = "RADIO_STATION",
PODCAST_SERIES = "PODCAST_SERIES",
TV_SERIES = "TV_SERIES",
VIDEO_PLAYLIST = "VIDEO_PLAYLIST",
LIVE_TV = "LIVETV",
MOVIE = "MOVIE"
}
export enum RepeatMode {
OFF = "REPEAT_OFF",
ALL = "REPEAT_ALL",
SINGLE = "REPEAT_SINGLE",
ALL_AND_SHUFFLE = "REPEAT_ALL_AND_SHUFFLE"
}
export enum ResumeState {
PLAYBACK_START = "PLAYBACK_START",
PLAYBACK_PAUSE = "PLAYBACK_PAUSE"
}
export enum StreamType {
BUFFERED = "BUFFERED",
LIVE = "LIVE",
OTHER = "OTHER"
}
export enum TextTrackEdgeType {
NONE = "NONE",
OUTLINE = "OUTLINE",
DROP_SHADOW = "DROP_SHADOW",
RAISED = "RAISED",
DEPRESSED = "DEPRESSED"
}
export enum TextTrackFontGenericFamily {
SANS_SERIF = "SANS_SERIF",
MONOSPACED_SANS_SERIF = "MONOSPACED_SANS_SERIF",
SERIF = "SERIF",
MONOSPACED_SERIF = "MONOSPACED_SERIF",
CASUAL = "CASUAL",
CURSIVE = "CURSIVE",
SMALL_CAPITALS = "SMALL_CAPITALS"
}
export enum TextTrackFontStyle {
NORMAL = "NORMAL",
BOLD = "BOLD",
BOLD_ITALIC = "BOLD_ITALIC",
ITALIC = "ITALIC"
}
export enum TextTrackType {
SUBTITLES = "SUBTITLES",
CAPTIONS = "CAPTIONS",
DESCRIPTIONS = "DESCRIPTIONS",
CHAPTERS = "CHAPTERS",
METADATA = "METADATA"
}
export enum TextTrackWindowType {
NONE = "NONE",
NORMAL = "NORMAL",
ROUNDED_CORNERS = "ROUNDED_CORNERS"
}
export enum TrackType {
TEXT = "TEXT",
AUDIO = "AUDIO",
VIDEO = "VIDEO"
}
export enum UserAction {
LIKE = "LIKE",
DISLIKE = "DISLIKE",
FOLLOW = "FOLLOW",
UNFOLLOW = "UNFOLLOW"
}

View File

@@ -0,0 +1,140 @@
"use strict";
import Media from "./Media";
import {
ContainerType,
HdrType,
HlsSegmentFormat,
HlsVideoSegmentFormat,
IdleReason,
MediaCommand,
MetadataType,
PlayerState,
QueueType,
RepeatMode,
ResumeState,
StreamType,
TextTrackEdgeType,
TextTrackFontGenericFamily,
TextTrackFontStyle,
TextTrackType,
TextTrackWindowType,
TrackType,
UserAction
} from "./enums";
import {
AudiobookChapterMediaMetadata,
AudiobookContainerMetadata,
Break,
BreakClip,
BreakStatus,
ContainerMetadata,
EditTracksInfoRequest,
GenericMediaMetadata,
GetStatusRequest,
LiveSeekableRange,
LoadRequest,
MediaInfo,
MediaMetadata,
MovieMediaMetadata,
MusicTrackMediaMetadata,
PauseRequest,
PhotoMediaMetadata,
PlayRequest,
QueueData,
QueueInsertItemsRequest,
QueueItem,
QueueJumpRequest,
QueueLoadRequest,
QueueRemoveItemsRequest,
QueueReorderItemsRequest,
QueueSetPropertiesRequest,
QueueUpdateItemsRequest,
SeekRequest,
StopRequest,
TextTrackStyle,
Track,
TvShowMediaMetadata,
UserActionState,
VastAdsRequest,
VideoInformation,
VolumeRequest
} from "./classes";
export default {
DEFAULT_MEDIA_RECEIVER_APP_ID: "CC1AD845",
timeout: {
editTracksInfo: 0,
getStatus: 0,
load: 0,
pause: 0,
play: 0,
queue: 0,
seek: 0,
setVolume: 0,
stop: 0
},
Media,
// Enums
ContainerType,
HdrType,
HlsSegmentFormat,
HlsVideoSegmentFormat,
IdleReason,
MediaCommand,
MetadataType,
PlayerState,
QueueType,
RepeatMode,
ResumeState,
StreamType,
TextTrackEdgeType,
TextTrackFontGenericFamily,
TextTrackFontStyle,
TextTrackType,
TextTrackWindowType,
TrackType,
UserAction,
// Classes
AudiobookChapterMediaMetadata,
AudiobookContainerMetadata,
Break,
BreakClip,
BreakStatus,
ContainerMetadata,
EditTracksInfoRequest,
GenericMediaMetadata,
GetStatusRequest,
LiveSeekableRange,
LoadRequest,
MediaInfo,
MediaMetadata,
MovieMediaMetadata,
MusicTrackMediaMetadata,
PauseRequest,
PhotoMediaMetadata,
PlayRequest,
QueueData,
QueueInsertItemsRequest,
QueueItem,
QueueJumpRequest,
QueueLoadRequest,
QueueRemoveItemsRequest,
QueueReorderItemsRequest,
QueueSetPropertiesRequest,
QueueUpdateItemsRequest,
SeekRequest,
StopRequest,
TextTrackStyle,
Track,
TvShowMediaMetadata,
UserActionState,
VastAdsRequest,
VideoInformation,
VolumeRequest
};