mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-09 17:19:59 +00:00
Improve session/media bridge messaging
This commit is contained in:
@@ -4,8 +4,9 @@ import bridge from "../lib/bridge";
|
||||
import logger from "../lib/logger";
|
||||
import { TypedEventTarget } from "../lib/TypedEventTarget";
|
||||
|
||||
import messaging, { Message, Port } from "../messaging";
|
||||
import { ReceiverDevice, ReceiverStatus } from "../types";
|
||||
import { Message, Port } from "../messaging";
|
||||
import { ReceiverDevice } from "../types";
|
||||
import { ReceiverStatus } from "../shim/cast/types";
|
||||
|
||||
|
||||
interface EventMap {
|
||||
@@ -124,7 +125,6 @@ export default new class extends TypedEventTarget<EventMap> {
|
||||
if (receiverDevice.status) {
|
||||
receiverDevice.status.isActiveInput = status.isActiveInput;
|
||||
receiverDevice.status.isStandBy = status.isStandBy;
|
||||
receiverDevice.status.userEq = status.userEq;
|
||||
receiverDevice.status.volume = status.volume;
|
||||
|
||||
if (status.applications) {
|
||||
|
||||
@@ -5,9 +5,7 @@ import Messenger from "./lib/Messenger";
|
||||
import { TypedPort } from "./lib/TypedPort";
|
||||
import { BridgeInfo } from "./lib/bridge";
|
||||
|
||||
import { ReceiverDevice
|
||||
, SessionReceiverMessage
|
||||
, ReceiverStatus } from "./types";
|
||||
import { ReceiverDevice } from "./types";
|
||||
|
||||
import { ReceiverSelectorMediaType } from "./background/receiverSelector";
|
||||
import { ReceiverSelection
|
||||
@@ -16,7 +14,10 @@ import { ReceiverSelection
|
||||
from "./background/receiverSelector/ReceiverSelector";
|
||||
|
||||
import { Volume } from "./shim/cast/dataClasses";
|
||||
import { MediaInfo } from "./shim/cast/media";
|
||||
import { MediaStatus
|
||||
, SenderMessage
|
||||
, ReceiverApplication
|
||||
, ReceiverStatus } from "./shim/cast/types";
|
||||
|
||||
|
||||
/**
|
||||
@@ -73,24 +74,19 @@ type ExtMessageDefinitions = {
|
||||
type AppMessageDefinitions = {
|
||||
// Session messages
|
||||
"shim:session/stopped": {}
|
||||
, "shim:session/connected": {
|
||||
sessionId: string
|
||||
, namespaces: Array<{ name: string }>
|
||||
, displayName: string
|
||||
, statusText: string
|
||||
, "shim:session/connected": { application: ReceiverApplication }
|
||||
, "shim:session/updateStatus": { status: ReceiverStatus }
|
||||
, "shim:session/impl_addMessageListener": {
|
||||
namespace: string
|
||||
, message: string
|
||||
}
|
||||
, "shim:session/updateStatus": { volume: Volume }
|
||||
, "shim:session/sendReceiverMessageResponse": {
|
||||
, "shim:session/impl_sendMessage": {
|
||||
messageId: string
|
||||
, wasError: boolean
|
||||
}
|
||||
, "shim:session/impl_addMessageListener": {
|
||||
namespace: string
|
||||
, data: string
|
||||
}
|
||||
, "shim:session/impl_sendMessage": {
|
||||
, "shim:session/impl_sendReceiverMessage": {
|
||||
messageId: string
|
||||
, error: boolean
|
||||
, wasError: boolean
|
||||
}
|
||||
|
||||
// Bridge session messages
|
||||
@@ -102,11 +98,6 @@ type AppMessageDefinitions = {
|
||||
, _id: string
|
||||
}
|
||||
, "bridge:session/close": {}
|
||||
, "bridge:session/sendReceiverMessage": {
|
||||
message: SessionReceiverMessage
|
||||
, messageId: string
|
||||
, _id: string
|
||||
}
|
||||
, "bridge:session/impl_leave": {
|
||||
id: string
|
||||
, _id: string
|
||||
@@ -117,23 +108,19 @@ type AppMessageDefinitions = {
|
||||
, messageId: string
|
||||
, _id: string
|
||||
}
|
||||
, "bridge:session/impl_sendReceiverMessage": {
|
||||
message: SenderMessage
|
||||
, messageId: string
|
||||
, _id: string
|
||||
}
|
||||
, "bridge:session/impl_addMessageListener": {
|
||||
namespace: string;
|
||||
_id: string;
|
||||
}
|
||||
|
||||
// Media messages
|
||||
, "shim:media/update": {
|
||||
currentTime: number
|
||||
, _lastCurrentTime: number
|
||||
, customData: any
|
||||
, playbackRate: number
|
||||
, playerState: string
|
||||
, repeatMode: string
|
||||
, _volumeLevel: number
|
||||
, _volumeMuted: boolean
|
||||
, media: MediaInfo
|
||||
, mediaSessionId: number
|
||||
, "shim:media/updateStatus": {
|
||||
status: MediaStatus
|
||||
}
|
||||
, "shim:media/sendMediaMessageResponse": {
|
||||
messageId: string
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
import logger from "../../lib/logger";
|
||||
import { SessionReceiverMessage } from "../../types";
|
||||
|
||||
import { onMessage
|
||||
, sendMessageResponse } from "../eventMessageChannel";
|
||||
|
||||
import { Callbacks
|
||||
, ErrorCallback
|
||||
import { ErrorCallback
|
||||
, LoadSuccessCallback
|
||||
, MediaListener
|
||||
, MessageListener
|
||||
, SuccessCallback
|
||||
, UpdateListener } from "../types";
|
||||
|
||||
import { SenderMediaMessage, SenderMessage } from "./types";
|
||||
|
||||
import { Error as _Error
|
||||
, Image, Receiver
|
||||
, SenderApplication, Volume } from "./dataClasses";
|
||||
@@ -23,23 +23,29 @@ import { ErrorCode, SessionStatus } from "./enums";
|
||||
|
||||
import { Media
|
||||
, LoadRequest
|
||||
, QueueLoadRequest
|
||||
// Enums
|
||||
, RepeatMode } from "./media";
|
||||
, QueueLoadRequest } from "./media";
|
||||
|
||||
|
||||
type SenderMessageData<T = SenderMessage> =
|
||||
T extends any
|
||||
? Omit<T, "requestId">
|
||||
: never;
|
||||
|
||||
type SessionSuccessCallback = (session: Session) => void;
|
||||
|
||||
export default class Session {
|
||||
#id = uuid();
|
||||
|
||||
#isConnected = false;
|
||||
#successCallback?: SessionSuccessCallback;
|
||||
|
||||
#messageListeners = new Map<string, Set<MessageListener>>();
|
||||
#updateListeners = new Set<UpdateListener>();
|
||||
|
||||
#sendMessageCallbacks = new Map<string, Callbacks>();
|
||||
#sendReceiverMessageCallbacks = new Map<string, Function>();
|
||||
#sendMessageCallbacks =
|
||||
new Map<string, [ SuccessCallback?, ErrorCallback? ]>();
|
||||
#sendReceiverMessageCallbacks =
|
||||
new Map<string, (wasError: boolean) => void>();
|
||||
|
||||
#listener = onMessage(message => {
|
||||
// Filter other session messages
|
||||
@@ -61,38 +67,31 @@ export default class Session {
|
||||
break;
|
||||
}
|
||||
|
||||
case "shim:session/connected": {
|
||||
this.status = SessionStatus.CONNECTED;
|
||||
this.sessionId = message.data.sessionId;
|
||||
this.transportId = message.data.sessionId;
|
||||
this.namespaces = message.data.namespaces;
|
||||
this.displayName = message.data.displayName;
|
||||
this.statusText = message.data.statusText;
|
||||
|
||||
if (this.#successCallback) {
|
||||
this.#successCallback(this);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "shim:session/updateStatus": {
|
||||
const status = message.data;
|
||||
const { status } = message.data;
|
||||
|
||||
if (status.volume) {
|
||||
if (!this.receiver.volume) {
|
||||
const receiverVolume = new Volume(
|
||||
status.volume.level, status.volume.muted);
|
||||
// First status message indicates session creation
|
||||
if (!this.#isConnected && status.applications) {
|
||||
this.#isConnected = true;
|
||||
|
||||
receiverVolume.controlType = status.volume.controlType;
|
||||
receiverVolume.stepInterval =
|
||||
status.volume.stepInterval;
|
||||
} else {
|
||||
this.receiver.volume.level = status.volume.level;
|
||||
this.receiver.volume.muted = status.volume.muted;
|
||||
this.status = SessionStatus.CONNECTED;
|
||||
|
||||
// Update app props
|
||||
const app = status.applications[0];
|
||||
this.sessionId = app.sessionId;
|
||||
this.namespaces = app.namespaces;
|
||||
this.displayName = app.displayName;
|
||||
this.statusText = app.statusText;
|
||||
|
||||
if (this.#successCallback) {
|
||||
this.#successCallback(this);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.receiver.volume = status.volume;
|
||||
|
||||
for (const listener of this.#updateListeners) {
|
||||
listener(true);
|
||||
}
|
||||
@@ -100,25 +99,14 @@ export default class Session {
|
||||
break;
|
||||
}
|
||||
|
||||
case "shim:session/sendReceiverMessageResponse": {
|
||||
const { messageId, wasError } = message.data;
|
||||
const callback =
|
||||
this.#sendReceiverMessageCallbacks.get(messageId);
|
||||
if (callback) {
|
||||
callback(wasError);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case "shim:session/impl_addMessageListener": {
|
||||
const { namespace, data } = message.data;
|
||||
const { namespace, message: newMessage } = message.data;
|
||||
const messageListeners = this.#messageListeners.get(namespace);
|
||||
|
||||
if (messageListeners) {
|
||||
for (const listener of messageListeners) {
|
||||
listener(namespace, data);
|
||||
listener(namespace, newMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,11 +114,11 @@ export default class Session {
|
||||
}
|
||||
|
||||
case "shim:session/impl_sendMessage": {
|
||||
const { messageId, error } = message.data;
|
||||
const { messageId, wasError } = message.data;
|
||||
const [ successCallback, errorCallback ] =
|
||||
this.#sendMessageCallbacks.get(messageId) ?? [];
|
||||
|
||||
if (error && errorCallback) {
|
||||
if (wasError && errorCallback) {
|
||||
errorCallback(new _Error(ErrorCode.SESSION_ERROR));
|
||||
} else if (successCallback) {
|
||||
successCallback();
|
||||
@@ -140,31 +128,69 @@ export default class Session {
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
media: Media[];
|
||||
namespaces: Array<{ name: string }>;
|
||||
senderApps: SenderApplication[];
|
||||
status: SessionStatus;
|
||||
statusText: Nullable<string>;
|
||||
case "shim:session/impl_sendReceiverMessage": {
|
||||
const { messageId, wasError } = message.data;
|
||||
const callback =
|
||||
this.#sendReceiverMessageCallbacks.get(messageId);
|
||||
if (callback) {
|
||||
callback(wasError);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Sends a message to the bridge that is forwarded to the
|
||||
* receiver device. Promise resolves once the message is sent
|
||||
* or an error occurs.
|
||||
*/
|
||||
#sendReceiverMessage = (message: SenderMessageData) => {
|
||||
const messageId = uuid();
|
||||
sendMessageResponse({
|
||||
subject: "bridge:session/impl_sendReceiverMessage"
|
||||
, data: {
|
||||
message: { requestId: 0, ...message }
|
||||
, messageId
|
||||
, _id: this.#id
|
||||
}
|
||||
});
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.#sendReceiverMessageCallbacks.set(messageId
|
||||
, (wasError: boolean) => {
|
||||
|
||||
if (wasError) {
|
||||
reject(new _Error(ErrorCode.SESSION_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private _sendMediaMessage(message: SenderMediaMessage) {
|
||||
this.sendMessage("urn:x-cast:com.google.cast.media", message);
|
||||
}
|
||||
|
||||
media: Media[] = [];
|
||||
namespaces: Array<{ name: string }> = [];
|
||||
senderApps: SenderApplication[] = [];
|
||||
status = SessionStatus.CONNECTED;
|
||||
statusText: Nullable<string> = null;
|
||||
transportId: string;
|
||||
|
||||
constructor(
|
||||
public sessionId: string
|
||||
, public appId: string
|
||||
, public displayName: string
|
||||
, public appImages: Image[]
|
||||
, public receiver: Receiver
|
||||
, _successCallback: SessionSuccessCallback) {
|
||||
constructor(public sessionId: string
|
||||
, public appId: string
|
||||
, public displayName: string
|
||||
, public appImages: Image[]
|
||||
, public receiver: Receiver
|
||||
, _successCallback: SessionSuccessCallback) {
|
||||
|
||||
this.#successCallback = _successCallback;
|
||||
|
||||
this.media = [];
|
||||
this.namespaces = [];
|
||||
this.senderApps = [];
|
||||
this.status = SessionStatus.CONNECTED;
|
||||
this.statusText = null;
|
||||
this.transportId = sessionId || "";
|
||||
|
||||
if (receiver) {
|
||||
@@ -186,9 +212,8 @@ export default class Session {
|
||||
logger.info("STUB :: Session#addMediaListener");
|
||||
}
|
||||
|
||||
addMessageListener(
|
||||
namespace: string
|
||||
, listener: MessageListener) {
|
||||
addMessageListener(namespace: string
|
||||
, listener: MessageListener) {
|
||||
|
||||
if (!this.#messageListeners.has(namespace)) {
|
||||
this.#messageListeners.set(namespace, new Set());
|
||||
@@ -209,28 +234,17 @@ export default class Session {
|
||||
this.#updateListeners.add(listener);
|
||||
}
|
||||
|
||||
leave(
|
||||
_successCallback?: SuccessCallback
|
||||
, _errorCallback?: ErrorCallback): void {
|
||||
leave(_successCallback?: SuccessCallback
|
||||
, _errorCallback?: ErrorCallback): void {
|
||||
|
||||
logger.info("STUB :: Session#leave");
|
||||
}
|
||||
|
||||
loadMedia(
|
||||
loadRequest: LoadRequest
|
||||
, successCallback?: LoadSuccessCallback
|
||||
, errorCallback?: ErrorCallback): void {
|
||||
loadMedia(loadRequest: LoadRequest
|
||||
, successCallback?: LoadSuccessCallback
|
||||
, errorCallback?: ErrorCallback): void {
|
||||
|
||||
this._sendMediaMessage({
|
||||
type: "LOAD"
|
||||
, requestId: 0
|
||||
, media: loadRequest.media
|
||||
, activeTrackIds: loadRequest.activeTrackIds || []
|
||||
, autoplay: loadRequest.autoplay || false
|
||||
, currentTime: loadRequest.currentTime || 0
|
||||
, customData: loadRequest.customData || {}
|
||||
, repeatMode: RepeatMode.OFF
|
||||
});
|
||||
this._sendMediaMessage(loadRequest);
|
||||
|
||||
|
||||
let hasResponded = false;
|
||||
@@ -274,10 +288,9 @@ export default class Session {
|
||||
});
|
||||
}
|
||||
|
||||
queueLoad(
|
||||
_queueLoadRequest: QueueLoadRequest
|
||||
, _successCallback?: LoadSuccessCallback
|
||||
, _errorCallback?: ErrorCallback): void {
|
||||
queueLoad(_queueLoadRequest: QueueLoadRequest
|
||||
, _successCallback?: LoadSuccessCallback
|
||||
, _errorCallback?: ErrorCallback): void {
|
||||
|
||||
logger.info("STUB :: Session#queueLoad");
|
||||
}
|
||||
@@ -285,26 +298,17 @@ export default class Session {
|
||||
removeMediaListener(_mediaListener: MediaListener): void {
|
||||
logger.info("STUB :: Session#removeMediaListener");
|
||||
}
|
||||
|
||||
removeMessageListener(
|
||||
namespace: string
|
||||
, listener: MessageListener): void {
|
||||
|
||||
removeMessageListener(namespace: string, listener: MessageListener): void {
|
||||
this.#messageListeners.get(namespace)?.delete(listener);
|
||||
}
|
||||
|
||||
removeUpdateListener(
|
||||
_namespace: string
|
||||
, listener: UpdateListener): void {
|
||||
|
||||
removeUpdateListener(_namespace: string, listener: UpdateListener): void {
|
||||
this.#updateListeners.delete(listener);
|
||||
}
|
||||
|
||||
sendMessage(
|
||||
namespace: string
|
||||
, message: {} | string
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback): void {
|
||||
sendMessage(namespace: string
|
||||
, message: {} | string
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback): void {
|
||||
|
||||
const messageId = uuid();
|
||||
|
||||
@@ -324,10 +328,9 @@ export default class Session {
|
||||
]);
|
||||
}
|
||||
|
||||
setReceiverMuted(
|
||||
muted: boolean
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
setReceiverMuted(muted: boolean
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendReceiverMessage(
|
||||
{ type: "SET_VOLUME"
|
||||
@@ -336,10 +339,9 @@ export default class Session {
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
setReceiverVolumeLevel(
|
||||
newLevel: number
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback): void {
|
||||
setReceiverVolumeLevel(newLevel: number
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback): void {
|
||||
|
||||
this.#sendReceiverMessage(
|
||||
{ type: "SET_VOLUME"
|
||||
@@ -348,9 +350,8 @@ export default class Session {
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
stop(
|
||||
successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback): void {
|
||||
stop(successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback): void {
|
||||
|
||||
this.#sendReceiverMessage(
|
||||
{ type: "STOP"
|
||||
@@ -358,38 +359,4 @@ export default class Session {
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a message to the bridge that is forwarded to the
|
||||
* receiver device. Promise resolves once the message is sent
|
||||
* or an error occurs.
|
||||
*/
|
||||
#sendReceiverMessage = (message: SessionReceiverMessage) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (!(message as any).requestId) {
|
||||
(message as any).requestId = 0;
|
||||
}
|
||||
|
||||
const messageId = uuid();
|
||||
sendMessageResponse({
|
||||
subject: "bridge:session/sendReceiverMessage"
|
||||
, data: { message, messageId, _id: this.#id }
|
||||
});
|
||||
|
||||
this.#sendReceiverMessageCallbacks.set(
|
||||
messageId, (wasError: boolean) => {
|
||||
if (wasError) {
|
||||
reject(new _Error(ErrorCode.SESSION_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private _sendMediaMessage(message: string | {}) {
|
||||
this.sendMessage("urn:x-cast:com.google.cast.media", message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import { AutoJoinPolicy
|
||||
, SenderPlatform
|
||||
, SessionStatus
|
||||
, VolumeControlType } from "./enums";
|
||||
import messaging from "../../messaging";
|
||||
|
||||
|
||||
export * as media from "./media";
|
||||
|
||||
@@ -1,52 +1,40 @@
|
||||
"use strict";
|
||||
|
||||
import logger from "../../../lib/logger";
|
||||
|
||||
import { v1 as uuid } from "uuid";
|
||||
|
||||
import { BreakStatus
|
||||
, EditTracksInfoRequest
|
||||
, GetStatusRequest
|
||||
, LiveSeekableRange
|
||||
, MediaInfo
|
||||
, PauseRequest
|
||||
, PlayRequest
|
||||
, QueueData
|
||||
, QueueJumpRequest
|
||||
, QueueInsertItemsRequest
|
||||
, QueueItem
|
||||
, QueueSetPropertiesRequest
|
||||
, QueueRemoveItemsRequest
|
||||
, QueueReorderItemsRequest
|
||||
, QueueUpdateItemsRequest
|
||||
, SeekRequest
|
||||
, StopRequest
|
||||
, VideoInformation
|
||||
, VolumeRequest } from "./dataClasses";
|
||||
import logger from "../../../lib/logger";
|
||||
|
||||
import { Volume, Error as _Error } from "../dataClasses";
|
||||
import { BreakStatus, EditTracksInfoRequest, GetStatusRequest, LiveSeekableRange
|
||||
, MediaInfo, PauseRequest, PlayRequest, QueueData, QueueJumpRequest
|
||||
, QueueInsertItemsRequest, QueueItem, QueueSetPropertiesRequest
|
||||
, QueueRemoveItemsRequest, QueueReorderItemsRequest
|
||||
, QueueUpdateItemsRequest, SeekRequest, StopRequest, VideoInformation
|
||||
, VolumeRequest } from "./dataClasses";
|
||||
|
||||
import { PlayerState
|
||||
, RepeatMode } from "./enums";
|
||||
|
||||
import { PlayerState, RepeatMode } from "./enums";
|
||||
import { ErrorCode } from "../enums";
|
||||
|
||||
import { onMessage, sendMessageResponse } from "../../eventMessageChannel";
|
||||
|
||||
import { Callbacks
|
||||
, ErrorCallback
|
||||
import { ErrorCallback
|
||||
, SuccessCallback
|
||||
, UpdateListener } from "../../types";
|
||||
|
||||
import { SessionMediaMessage } from "../../../types";
|
||||
import { SenderMediaMessage } from "../types";
|
||||
|
||||
|
||||
export default class Media {
|
||||
#id = uuid();
|
||||
#isActive = true;
|
||||
|
||||
/**
|
||||
* Timestamp of last status update
|
||||
*/
|
||||
#lastUpdateTime = 0;
|
||||
|
||||
#updateListeners = new Set<UpdateListener>();
|
||||
#sendMediaMessageCallbacks = new Map<string, Callbacks>();
|
||||
#lastCurrentTime = 0;
|
||||
#sendMediaMessageCallbacks =
|
||||
new Map<string, [ SuccessCallback?, ErrorCallback? ]>();
|
||||
|
||||
#listener = onMessage(message => {
|
||||
if ((message as any).data._id !== this.#id) {
|
||||
@@ -54,27 +42,24 @@ export default class Media {
|
||||
}
|
||||
|
||||
switch (message.subject) {
|
||||
case "shim:media/update": {
|
||||
const status = message.data;
|
||||
case "shim:media/updateStatus": {
|
||||
const { status } = message.data;
|
||||
|
||||
// Store current update time
|
||||
this.#lastUpdateTime = Date.now();
|
||||
|
||||
this.currentTime = status.currentTime;
|
||||
this.#lastCurrentTime = status._lastCurrentTime;
|
||||
this.customData = status.customData;
|
||||
this.mediaSessionId = status.mediaSessionId;
|
||||
this.playbackRate = status.playbackRate;
|
||||
this.playerState = status.playerState;
|
||||
this.repeatMode = status.repeatMode;
|
||||
this.volume = status.volume;
|
||||
|
||||
if (status._volumeLevel && status._volumeMuted) {
|
||||
this.volume = new Volume(
|
||||
status._volumeLevel
|
||||
, status._volumeMuted);
|
||||
if (status.customData) {
|
||||
this.customData = status.customData;
|
||||
}
|
||||
|
||||
if (status.media) {
|
||||
this.media = status.media;
|
||||
}
|
||||
if (status.mediaSessionId) {
|
||||
this.mediaSessionId = status.mediaSessionId;
|
||||
this.media = status.media as MediaInfo;
|
||||
}
|
||||
|
||||
// Call update listeners
|
||||
@@ -106,8 +91,8 @@ export default class Media {
|
||||
activeTrackIds: Nullable<number[]> = null;
|
||||
breakStatus?: BreakStatus;
|
||||
currentItemId: Nullable<number> = null;
|
||||
customData: any = null;
|
||||
currentTime = 0;
|
||||
customData: any = null;
|
||||
idleReason: Nullable<string> = null;
|
||||
items: Nullable<QueueItem[]> = null;
|
||||
liveSeekableRange?: LiveSeekableRange;
|
||||
@@ -123,10 +108,9 @@ export default class Media {
|
||||
volume: Volume = new Volume();
|
||||
|
||||
|
||||
constructor(
|
||||
public sessionId: string
|
||||
, public mediaSessionId: number
|
||||
, _internalSessionId: string) {
|
||||
constructor(public sessionId: string
|
||||
, public mediaSessionId: number
|
||||
, _internalSessionId: string) {
|
||||
|
||||
sendMessageResponse({
|
||||
subject: "bridge:media/initialize"
|
||||
@@ -143,10 +127,9 @@ export default class Media {
|
||||
this.#updateListeners.add(listener);
|
||||
}
|
||||
|
||||
editTracksInfo(
|
||||
editTracksInfoRequest: EditTracksInfoRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
editTracksInfo(editTracksInfoRequest: EditTracksInfoRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(
|
||||
{ type: "EDIT_TRACKS_INFO", ...editTracksInfoRequest })
|
||||
@@ -171,8 +154,8 @@ export default class Media {
|
||||
*/
|
||||
getEstimatedTime(): number {
|
||||
if (this.playerState === PlayerState.PLAYING) {
|
||||
let estimatedTime = this.currentTime + (this.playbackRate * (
|
||||
Date.now() - this.#lastCurrentTime) / 1000);
|
||||
let estimatedTime = this.currentTime +
|
||||
((Date.now() - this.#lastUpdateTime) / 1000);
|
||||
|
||||
// Enforce valid range
|
||||
if (estimatedTime < 0) {
|
||||
@@ -192,10 +175,9 @@ export default class Media {
|
||||
* Request media status from the receiver application. This
|
||||
* will also trigger any added media update listeners.
|
||||
*/
|
||||
getStatus(
|
||||
getStatusRequest = new GetStatusRequest()
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
getStatus(getStatusRequest = new GetStatusRequest()
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(
|
||||
{ type: "MEDIA_GET_STATUS", ...getStatusRequest })
|
||||
@@ -203,10 +185,9 @@ export default class Media {
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
pause(
|
||||
pauseRequest = new PauseRequest()
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
pause(pauseRequest = new PauseRequest()
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(
|
||||
{ type: "PAUSE", ...pauseRequest })
|
||||
@@ -214,10 +195,9 @@ export default class Media {
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
play(
|
||||
playRequest = new PlayRequest()
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
play(playRequest = new PlayRequest()
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(
|
||||
{ type: "PLAY", ...playRequest })
|
||||
@@ -225,47 +205,52 @@ export default class Media {
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
queueAppendItem(
|
||||
item: QueueItem
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
queueAppendItem(item: QueueItem
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(new QueueInsertItemsRequest([ item ]))
|
||||
this.#sendMediaMessage(
|
||||
{
|
||||
...new QueueInsertItemsRequest([ item ])
|
||||
, type: "QUEUE_INSERT"
|
||||
})
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
queueInsertItems(
|
||||
queueInsertItemsRequest: QueueInsertItemsRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
queueInsertItems(queueInsertItemsRequest: QueueInsertItemsRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(queueInsertItemsRequest)
|
||||
this.#sendMediaMessage(
|
||||
{
|
||||
...queueInsertItemsRequest
|
||||
, type: "QUEUE_INSERT"
|
||||
})
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
|
||||
}
|
||||
|
||||
queueJumpToItem(
|
||||
itemId: number
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: 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)
|
||||
this.#sendMediaMessage(
|
||||
{ ...jumpRequest, type: "QUEUE_UPDATE" })
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
}
|
||||
|
||||
queueMoveItemToNewIndex(
|
||||
itemId: number
|
||||
, newIndex: number
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
queueMoveItemToNewIndex(itemId: number
|
||||
, newIndex: number
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
// Return early if not in queue
|
||||
if (!this.items) {
|
||||
@@ -295,41 +280,41 @@ export default class Media {
|
||||
reorderItemsRequest.insertBefore = existingItem.itemId;
|
||||
}
|
||||
|
||||
this.#sendMediaMessage(reorderItemsRequest)
|
||||
this.#sendMediaMessage(
|
||||
{ ...reorderItemsRequest, type: "QUEUE_REORDER" })
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
}
|
||||
|
||||
queueNext(
|
||||
successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
queueNext(successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
const jumpRequest = new QueueJumpRequest();
|
||||
jumpRequest.jump = 1;
|
||||
|
||||
this.#sendMediaMessage(jumpRequest)
|
||||
this.#sendMediaMessage(
|
||||
{ ...jumpRequest, type: "QUEUE_UPDATE" })
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
queuePrev(
|
||||
successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
queuePrev(successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
const jumpRequest = new QueueJumpRequest();
|
||||
jumpRequest.jump = -1;
|
||||
|
||||
this.#sendMediaMessage(jumpRequest)
|
||||
this.#sendMediaMessage(
|
||||
{ ...jumpRequest, type: "QUEUE_UPDATE" })
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
queueRemoveItem(
|
||||
itemId: number
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
queueRemoveItem(itemId: number
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
const item = this.items?.find(item => item.itemId === itemId);
|
||||
if (item) {
|
||||
this.queueRemoveItems(
|
||||
@@ -338,45 +323,45 @@ export default class Media {
|
||||
}
|
||||
}
|
||||
|
||||
queueRemoveItems(
|
||||
queueRemoveItemsRequest: QueueRemoveItemsRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
queueRemoveItems(queueRemoveItemsRequest: QueueRemoveItemsRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(queueRemoveItemsRequest)
|
||||
this.#sendMediaMessage(
|
||||
{ ...queueRemoveItemsRequest, type: "QUEUE_REMOVE" })
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
queueReorderItems(
|
||||
queueReorderItemsRequest: QueueReorderItemsRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
queueReorderItems(queueReorderItemsRequest: QueueReorderItemsRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(queueReorderItemsRequest)
|
||||
this.#sendMediaMessage(
|
||||
{ ...queueReorderItemsRequest, type: "QUEUE_REORDER" })
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
queueSetRepeatMode(
|
||||
repeatMode: string
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
queueSetRepeatMode(repeatMode: string
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
const setPropertiesRequest = new QueueSetPropertiesRequest();
|
||||
setPropertiesRequest.repeatMode = repeatMode;
|
||||
|
||||
this.#sendMediaMessage(setPropertiesRequest)
|
||||
this.#sendMediaMessage(
|
||||
{ ...setPropertiesRequest, type: "QUEUE_UPDATE" })
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
queueUpdateItems(
|
||||
queueUpdateItemsRequest: QueueUpdateItemsRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
queueUpdateItems(queueUpdateItemsRequest: QueueUpdateItemsRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(queueUpdateItemsRequest)
|
||||
this.#sendMediaMessage(
|
||||
{ ...queueUpdateItemsRequest, type: "QUEUE_UPDATE" })
|
||||
.then(successCallback)
|
||||
.catch(errorCallback);
|
||||
}
|
||||
@@ -385,10 +370,9 @@ export default class Media {
|
||||
this.#updateListeners.delete(listener);
|
||||
}
|
||||
|
||||
seek(
|
||||
seekRequest: SeekRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
seek(seekRequest: SeekRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(
|
||||
{ type: "SEEK", ...seekRequest })
|
||||
@@ -396,10 +380,9 @@ export default class Media {
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
setVolume(
|
||||
volumeRequest: VolumeRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
setVolume(volumeRequest: VolumeRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
this.#sendMediaMessage(
|
||||
{ type: "MEDIA_SET_VOLUME", ...volumeRequest })
|
||||
@@ -407,10 +390,9 @@ export default class Media {
|
||||
.catch(errorCallback);
|
||||
}
|
||||
|
||||
stop(
|
||||
stopRequest?: StopRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
stop(stopRequest?: StopRequest
|
||||
, successCallback?: SuccessCallback
|
||||
, errorCallback?: ErrorCallback) {
|
||||
|
||||
if (!stopRequest) {
|
||||
stopRequest = new StopRequest();
|
||||
@@ -434,7 +416,11 @@ export default class Media {
|
||||
}
|
||||
|
||||
|
||||
#sendMediaMessage = async (message: SessionMediaMessage) => {
|
||||
#sendMediaMessage = async (
|
||||
// Allow messages without requestId
|
||||
message: Omit<SenderMediaMessage, "requestId">
|
||||
& { requestId?: Nullable<number> }) => {
|
||||
|
||||
if (!this.media) {
|
||||
return;
|
||||
}
|
||||
@@ -465,10 +451,10 @@ export default class Media {
|
||||
|
||||
sendMessageResponse({
|
||||
subject: "bridge:media/sendMediaMessage"
|
||||
, data: {
|
||||
, data: {
|
||||
message
|
||||
, messageId
|
||||
, _id: this.#id
|
||||
, messageId
|
||||
, _id: this.#id
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,8 +8,8 @@ import { ContainerType
|
||||
, HlsVideoSegmentFormat
|
||||
, MetadataType
|
||||
, RepeatMode
|
||||
, StreamType
|
||||
, UserAction } from "./enums";
|
||||
, ResumeState, StreamType
|
||||
, TrackType, UserAction } from "./enums";
|
||||
|
||||
|
||||
export class AudiobookChapterMediaMetadata {
|
||||
@@ -93,12 +93,12 @@ export class EditTracksInfoRequest {
|
||||
|
||||
export class GenericMediaMetadata {
|
||||
images?: Image[];
|
||||
metadataType: number = MetadataType.GENERIC;
|
||||
metadataType = MetadataType.GENERIC;
|
||||
releaseDate?: string;
|
||||
releaseYear?: number;
|
||||
subtitle?: string;
|
||||
title?: string;
|
||||
type: number = MetadataType.GENERIC;
|
||||
type = MetadataType.GENERIC;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ export class LoadRequest {
|
||||
media: MediaInfo;
|
||||
requestId = 0;
|
||||
sessionId: Nullable<string> = null;
|
||||
type = "LOAD";
|
||||
type: "LOAD" = "LOAD";
|
||||
|
||||
constructor(mediaInfo: MediaInfo) {
|
||||
this.media = mediaInfo;
|
||||
@@ -134,7 +134,7 @@ export class LoadRequest {
|
||||
}
|
||||
|
||||
|
||||
type Metadata =
|
||||
export type Metadata =
|
||||
GenericMediaMetadata
|
||||
| MovieMediaMetadata
|
||||
| MusicTrackMediaMetadata
|
||||
@@ -183,13 +183,13 @@ export class MediaMetadata {
|
||||
|
||||
export class MovieMediaMetadata {
|
||||
images?: Image[];
|
||||
metadataType: number = MetadataType.MOVIE;
|
||||
metadataType = MetadataType.MOVIE;
|
||||
releaseDate?: string;
|
||||
releaseYear?: number;
|
||||
studio?: string;
|
||||
subtitle?: string;
|
||||
title?: string;
|
||||
type: number = MetadataType.MOVIE;
|
||||
type = MetadataType.MOVIE;
|
||||
}
|
||||
|
||||
|
||||
@@ -201,13 +201,13 @@ export class MusicTrackMediaMetadata {
|
||||
composer?: string;
|
||||
discNumber?: number;
|
||||
images?: Image[];
|
||||
metadataType: number = MetadataType.MUSIC_TRACK;
|
||||
metadataType = MetadataType.MUSIC_TRACK;
|
||||
releaseDate?: string;
|
||||
releaseYear?: number;
|
||||
songName?: string;
|
||||
title?: string;
|
||||
trackNumber?: number;
|
||||
type: number = MetadataType.MUSIC_TRACK;
|
||||
type = MetadataType.MUSIC_TRACK;
|
||||
}
|
||||
|
||||
|
||||
@@ -224,9 +224,9 @@ export class PhotoMediaMetadata {
|
||||
latitude?: number;
|
||||
location?: string;
|
||||
longitude?: number;
|
||||
metadataType: number = MetadataType.PHOTO;
|
||||
metadataType = MetadataType.PHOTO;
|
||||
title?: string;
|
||||
type: number = MetadataType.PHOTO;
|
||||
type = MetadataType.PHOTO;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ export class QueueUpdateItemsRequest {
|
||||
export class SeekRequest {
|
||||
currentTime: Nullable<number> = null;
|
||||
customData: any = null;
|
||||
resumeState: Nullable<string> = null;
|
||||
resumeState: Nullable<ResumeState> = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -382,7 +382,7 @@ export class Track {
|
||||
|
||||
constructor(
|
||||
public trackId: number
|
||||
, public type: string) {}
|
||||
, public type: TrackType) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -398,7 +398,7 @@ export class TvShowMediaMetadata {
|
||||
seasonNumber?: number;
|
||||
seriesTitle?: string;
|
||||
title?: string;
|
||||
type: number = MetadataType.TV_SHOW;
|
||||
type = MetadataType.TV_SHOW;
|
||||
}
|
||||
|
||||
|
||||
|
||||
157
ext/src/shim/cast/types.ts
Normal file
157
ext/src/shim/cast/types.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Keep in sync with bridge types at:
|
||||
* app/src/bridge/components/chromecast/types.ts
|
||||
*/
|
||||
|
||||
import { Volume } from "./dataClasses";
|
||||
import { MediaInfo, QueueItem } from "./media/dataClasses";
|
||||
import { IdleReason
|
||||
, PlayerState
|
||||
, RepeatMode
|
||||
, ResumeState } from "./media/enums";
|
||||
|
||||
|
||||
export interface MediaStatus {
|
||||
mediaSessionId: number;
|
||||
media?: MediaInfo;
|
||||
playbackRate: number;
|
||||
playerState: PlayerState;
|
||||
idleReason?: IdleReason;
|
||||
currentTime: number;
|
||||
supportedMediaCommands: number;
|
||||
repeatMode: RepeatMode;
|
||||
volume: Volume
|
||||
customData: unknown;
|
||||
}
|
||||
|
||||
export interface ReceiverApplication {
|
||||
appId: string
|
||||
, appType?: string
|
||||
, displayName: string
|
||||
, iconUrl: string
|
||||
, isIdleScreen: boolean
|
||||
, launchedFromCloud: boolean
|
||||
, namespaces: Array<{ name: string }>
|
||||
, sessionId: string
|
||||
, statusText: string
|
||||
, transportId: string
|
||||
, universalAppId: string
|
||||
}
|
||||
|
||||
export interface ReceiverStatus {
|
||||
applications?: ReceiverApplication[]
|
||||
, isActiveInput?: boolean
|
||||
, isStandBy?: boolean
|
||||
, volume: Volume
|
||||
}
|
||||
|
||||
|
||||
interface ReqBase {
|
||||
requestId: number;
|
||||
}
|
||||
|
||||
// NS: urn:x-cast:com.google.cast.receiver
|
||||
export type SenderMessage =
|
||||
ReqBase & { type: "LAUNCH", appId: string }
|
||||
| ReqBase & { type: "STOP", sessionId: string }
|
||||
| ReqBase & { type: "GET_STATUS" }
|
||||
| ReqBase & { type: "GET_APP_AVAILABILITY", appId: string[] }
|
||||
| ReqBase & { type: "SET_VOLUME", volume: Partial<Volume> };
|
||||
|
||||
export type ReceiverMessage =
|
||||
ReqBase & {
|
||||
type: "RECEIVER_STATUS"
|
||||
, status: ReceiverStatus
|
||||
};
|
||||
|
||||
|
||||
interface MediaReqBase extends ReqBase {
|
||||
customData?: unknown;
|
||||
}
|
||||
|
||||
// NS: urn:x-cast:com.google.cast.media
|
||||
export type SenderMediaMessage =
|
||||
| MediaReqBase & { type: "PLAY" }
|
||||
| MediaReqBase & { type: "PAUSE" }
|
||||
| MediaReqBase & { type: "MEDIA_GET_STATUS" }
|
||||
| MediaReqBase & { type: "STOP" }
|
||||
| MediaReqBase & { type: "MEDIA_SET_VOLUME", volume: Partial<Volume> }
|
||||
| MediaReqBase & { type: "SET_PLAYBACK_RATE" , playbackRate: number }
|
||||
| MediaReqBase & {
|
||||
type: "LOAD"
|
||||
, activeTrackIds: Nullable<number[]>
|
||||
, atvCredentials?: string
|
||||
, atvCredentialsType?: string
|
||||
, autoplay: Nullable<boolean>
|
||||
, currentTime: Nullable<number>
|
||||
, customData: any
|
||||
, media: MediaInfo
|
||||
, requestId: number
|
||||
, sessionId: Nullable<string>
|
||||
}
|
||||
| MediaReqBase & {
|
||||
type: "SEEK"
|
||||
, resumeState: Nullable<ResumeState>
|
||||
, currentTime: Nullable<number>
|
||||
}
|
||||
| MediaReqBase & {
|
||||
type: "EDIT_TRACKS_INFO"
|
||||
, activeTrackIds: Nullable<number[]>
|
||||
, textTrackStyle: Nullable<string>
|
||||
}
|
||||
// QueueLoadRequest
|
||||
| MediaReqBase & {
|
||||
type: "QUEUE_LOAD"
|
||||
, items: QueueItem[]
|
||||
, startIndex: number
|
||||
, repeatMode: string
|
||||
, sessionId: Nullable<string>
|
||||
}
|
||||
// QueueInsertItemsRequest
|
||||
| MediaReqBase & {
|
||||
type: "QUEUE_INSERT"
|
||||
, items: QueueItem[]
|
||||
, insertBefore: Nullable<number>
|
||||
, sessionId: Nullable<string>
|
||||
}
|
||||
// QueueUpdateItemsRequest
|
||||
| MediaReqBase & {
|
||||
type: "QUEUE_UPDATE"
|
||||
, items: QueueItem[]
|
||||
, sessionId: Nullable<string>
|
||||
}
|
||||
// QueueJumpRequest
|
||||
| MediaReqBase & {
|
||||
type: "QUEUE_UPDATE"
|
||||
, jump: Nullable<number>
|
||||
, currentItemId: Nullable<number>
|
||||
, sessionId: Nullable<number>
|
||||
}
|
||||
// QueueRemoveItemsRequest
|
||||
| MediaReqBase & {
|
||||
type: "QUEUE_REMOVE"
|
||||
, itemIds: number[]
|
||||
, sessionId: Nullable<string>
|
||||
}
|
||||
// QueueReorderItemsRequest
|
||||
| MediaReqBase & {
|
||||
type: "QUEUE_REORDER"
|
||||
, itemIds: number[]
|
||||
, insertBefore: Nullable<number>
|
||||
, sessionId: Nullable<string>
|
||||
}
|
||||
// QueueSetPropertiesRequest
|
||||
| MediaReqBase & {
|
||||
type: "QUEUE_UPDATE"
|
||||
, repeatMode: Nullable<string>
|
||||
, sessionId: Nullable<string>
|
||||
};
|
||||
|
||||
export type ReceiverMediaMessage =
|
||||
MediaReqBase & { type: "MEDIA_STATUS", status: MediaStatus[] }
|
||||
| MediaReqBase & { type: "INVALID_PLAYER_STATE" }
|
||||
| MediaReqBase & { type: "LOAD_FAILED" }
|
||||
| MediaReqBase & { type: "LOAD_CANCELLED" }
|
||||
| MediaReqBase & { type: "INVALID_REQUEST" };
|
||||
@@ -11,6 +11,3 @@ export type MediaListener = (media: Media) => void;
|
||||
export type MessageListener = (namespace: string, message: string) => void;
|
||||
export type UpdateListener = (isAlive: boolean) => void;
|
||||
export type LoadSuccessCallback = (media: Media) => void;
|
||||
|
||||
export type Callbacks = [ SuccessCallback?, ErrorCallback? ];
|
||||
export type CallbacksMap = Map<string, Callbacks>;
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
import { Volume } from "./shim/cast/dataClasses";
|
||||
|
||||
import { EditTracksInfoRequest, GetStatusRequest, LoadRequest, PauseRequest
|
||||
, PlayRequest, QueueInsertItemsRequest, QueueJumpRequest
|
||||
, QueueLoadRequest, QueueRemoveItemsRequest, QueueReorderItemsRequest
|
||||
, QueueSetPropertiesRequest, QueueUpdateItemsRequest, SeekRequest
|
||||
, StopRequest, VolumeRequest } from "./shim/cast/media";
|
||||
|
||||
import { ReceiverStatus } from "./shim/cast/types";
|
||||
|
||||
export interface ReceiverDevice {
|
||||
host: string
|
||||
@@ -16,49 +9,3 @@ export interface ReceiverDevice {
|
||||
, port: number
|
||||
, status?: ReceiverStatus
|
||||
}
|
||||
|
||||
export interface ReceiverStatus {
|
||||
applications?: Array<{
|
||||
appId: string
|
||||
, appType: string
|
||||
, displayName: string
|
||||
, iconUrl: string
|
||||
, isIdleScreen: boolean
|
||||
, launchedFromCloud: boolean
|
||||
, namespaces: Array<{ name: string }>
|
||||
, sessionId: string
|
||||
, statusText: string
|
||||
, transportId: string
|
||||
, universalAppId: string
|
||||
}>
|
||||
, isActiveInput?: boolean
|
||||
, isStandBy?: boolean
|
||||
, userEq: unknown
|
||||
, volume: Volume
|
||||
}
|
||||
|
||||
|
||||
export type SessionMediaMessage =
|
||||
{ type: "PLAY" } & PlayRequest
|
||||
| { type: "PAUSE" } & PauseRequest
|
||||
| { type: "SEEK" } & SeekRequest
|
||||
| { type: "STOP" } & StopRequest
|
||||
| { type: "MEDIA_GET_STATUS" } & GetStatusRequest
|
||||
| { type: "MEDIA_SET_VOLUME" } & VolumeRequest
|
||||
| { type: "EDIT_TRACKS_INFO" } & EditTracksInfoRequest
|
||||
| { type: "SET_PLAYBACK_RATE", playbackRate: number }
|
||||
| LoadRequest
|
||||
| QueueLoadRequest
|
||||
| QueueInsertItemsRequest
|
||||
| QueueUpdateItemsRequest
|
||||
| QueueJumpRequest
|
||||
| QueueRemoveItemsRequest
|
||||
| QueueReorderItemsRequest
|
||||
| QueueSetPropertiesRequest;
|
||||
|
||||
export type SessionReceiverMessage =
|
||||
{ type: "LAUNCH", appId: string }
|
||||
| { type: "STOP", sessionId: string }
|
||||
| { type: "GET_STATUS" }
|
||||
| { type: "GET_APP_AVAILABILITY", appId: string[] }
|
||||
| { type: "SET_VOLUME", volume: Partial<Volume> };
|
||||
|
||||
Reference in New Issue
Block a user