diff --git a/app/src/bridge/components/chromecast/Session.ts b/app/src/bridge/components/chromecast/Session.ts index 3f4bcd3..dc47466 100644 --- a/app/src/bridge/components/chromecast/Session.ts +++ b/app/src/bridge/components/chromecast/Session.ts @@ -138,6 +138,14 @@ export default class Session { wasError = true; } + if (message.data.message.type === "STOP") { + if (this.clientHeartbeatIntervalId) { + clearInterval(this.clientHeartbeatIntervalId); + } + + this.client.close(); + } + this.sendMessage("shim:session/sendReceiverMessageResponse", { messageId: message.data.messageId , wasError diff --git a/ext/src/messaging.ts b/ext/src/messaging.ts index 3ef1e0c..cd54876 100644 --- a/ext/src/messaging.ts +++ b/ext/src/messaging.ts @@ -6,7 +6,7 @@ import { TypedPort } from "./lib/TypedPort"; import { BridgeInfo } from "./lib/bridge"; import { ReceiverDevice - , ReceiverMessage + , SessionReceiverMessage , ReceiverStatus } from "./types"; import { ReceiverSelectorMediaType } from "./background/receiverSelector"; @@ -103,7 +103,7 @@ type AppMessageDefinitions = { } , "bridge:session/close": {} , "bridge:session/sendReceiverMessage": { - message: ReceiverMessage + message: SessionReceiverMessage , messageId: string , _id: string } diff --git a/ext/src/senders/media/index.ts b/ext/src/senders/media/index.ts index 4fca649..1e50bab 100644 --- a/ext/src/senders/media/index.ts +++ b/ext/src/senders/media/index.ts @@ -270,10 +270,7 @@ async function registerMediaElementListeners() { }); mediaElement.addEventListener("ratechange", () => { - // TODO: Fix types - currentMedia._sendMediaMessage("SET_PLAYBACK_RATE", { - playbackRate: mediaElement.playbackRate - } as any); + // TODO: Re-implement this }); mediaElement.addEventListener("volumechange", () => { diff --git a/ext/src/shim/cast/Session.ts b/ext/src/shim/cast/Session.ts index 726338f..93e5492 100644 --- a/ext/src/shim/cast/Session.ts +++ b/ext/src/shim/cast/Session.ts @@ -3,7 +3,7 @@ import { v4 as uuid } from "uuid"; import logger from "../../lib/logger"; -import { ReceiverMessage } from "../../types"; +import { SessionMediaMessage, SessionReceiverMessage } from "../../types"; import { onMessage , sendMessageResponse } from "../eventMessageChannel"; @@ -365,8 +365,12 @@ export default class Session { * receiver device. Promise resolves once the message is sent * or an error occurs. */ - #sendReceiverMessage = (message: ReceiverMessage) => { + #sendReceiverMessage = (message: SessionReceiverMessage) => { return new Promise((resolve, reject) => { + if (!(message as any).requestId) { + (message as any).requestId = 0; + } + const messageId = uuid(); sendMessageResponse({ subject: "bridge:session/sendReceiverMessage" diff --git a/ext/src/shim/cast/media/Media.ts b/ext/src/shim/cast/media/Media.ts index a4057f2..28b6d87 100644 --- a/ext/src/shim/cast/media/Media.ts +++ b/ext/src/shim/cast/media/Media.ts @@ -38,36 +38,7 @@ import { Callbacks , SuccessCallback , UpdateListener } from "../../types"; - -type MediaRequest = - EditTracksInfoRequest - | GetStatusRequest - | PauseRequest - | PlayRequest - | QueueInsertItemsRequest - | QueueJumpRequest - | QueueRemoveItemsRequest - | QueueReorderItemsRequest - | QueueUpdateItemsRequest - | SeekRequest - | StopRequest - | VolumeRequest; - -enum MediaMessageType { - Play = "PLAY" - , Load = "LOAD" - , Pause = "PAUSE" - , Seek = "SEEK" - , Stop = "STOP" - , MediaSetVolume = "MEDIA_SET_VOLUME" - , MediaGetStatus = "MEDIA_GET_STATUS" - , EditTracksInfo = "EDIT_TRACKS_INFO" - , QueueLoad = "QUEUE_LOAD" - , QueueInsert = "QUEUE_INSERT" - , QueueUpdate = "QUEUE_UPDATE" - , QueueRemove = "QUEUE_REMOVE" - , QueueReorder = "QUEUE_REORDER" -} +import { SessionMediaMessage } from "../../../types"; export default class Media { @@ -177,10 +148,10 @@ export default class Media { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - this._sendMediaMessage( - MediaMessageType.EditTracksInfo - , editTracksInfoRequest - , successCallback, errorCallback); + this.#sendMediaMessage( + { type: "EDIT_TRACKS_INFO", ...editTracksInfoRequest }) + .then(successCallback) + .catch(errorCallback); } public getEstimatedBreakClipTime() { @@ -220,10 +191,10 @@ export default class Media { getStatusRequest = new GetStatusRequest(); } - this._sendMediaMessage( - MediaMessageType.MediaGetStatus - , getStatusRequest - , successCallback, errorCallback); + this.#sendMediaMessage( + { type: "MEDIA_GET_STATUS", ...getStatusRequest }) + .then(successCallback) + .catch(errorCallback); } public pause( @@ -235,10 +206,10 @@ export default class Media { pauseRequest = new PauseRequest(); } - this._sendMediaMessage( - MediaMessageType.Pause - , pauseRequest - , successCallback, errorCallback); + this.#sendMediaMessage( + { type: "PAUSE", ...pauseRequest }) + .then(successCallback) + .catch(errorCallback); } public play( @@ -250,10 +221,10 @@ export default class Media { playRequest = new PlayRequest(); } - this._sendMediaMessage( - MediaMessageType.Play - , playRequest - , successCallback, errorCallback); + this.#sendMediaMessage( + { type: "PLAY", ...playRequest }) + .then(successCallback) + .catch(errorCallback); } public queueAppendItem( @@ -261,10 +232,9 @@ export default class Media { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - this._sendMediaMessage( - MediaMessageType.QueueInsert - , new QueueInsertItemsRequest([ item ]) - , successCallback, errorCallback); + this.#sendMediaMessage(new QueueInsertItemsRequest([ item ])) + .then(successCallback) + .catch(errorCallback); } public queueInsertItems( @@ -272,10 +242,10 @@ export default class Media { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - this._sendMediaMessage( - MediaMessageType.QueueInsert - , queueInsertItemsRequest - , successCallback, errorCallback); + this.#sendMediaMessage(queueInsertItemsRequest) + .then(successCallback) + .catch(errorCallback); + } public queueJumpToItem( @@ -287,10 +257,9 @@ export default class Media { const jumpRequest = new QueueJumpRequest(); jumpRequest.currentItemId = itemId; - this._sendMediaMessage( - MediaMessageType.QueueUpdate - , jumpRequest - , successCallback, errorCallback); + this.#sendMediaMessage(jumpRequest) + .then(successCallback) + .catch(errorCallback); } } @@ -327,10 +296,9 @@ export default class Media { reorderItemsRequest.insertBefore = existingItem.itemId; } - this._sendMediaMessage( - MediaMessageType.QueueReorder - , reorderItemsRequest - , successCallback, errorCallback); + this.#sendMediaMessage(reorderItemsRequest) + .then(successCallback) + .catch(errorCallback); } } @@ -341,10 +309,9 @@ export default class Media { const jumpRequest = new QueueJumpRequest(); jumpRequest.jump = 1; - this._sendMediaMessage( - MediaMessageType.QueueUpdate - , jumpRequest - , successCallback, errorCallback); + this.#sendMediaMessage(jumpRequest) + .then(successCallback) + .catch(errorCallback); } public queuePrev( @@ -354,10 +321,9 @@ export default class Media { const jumpRequest = new QueueJumpRequest(); jumpRequest.jump = -1; - this._sendMediaMessage( - MediaMessageType.QueueUpdate - , jumpRequest - , successCallback, errorCallback); + this.#sendMediaMessage(jumpRequest) + .then(successCallback) + .catch(errorCallback); } public queueRemoveItem( @@ -367,11 +333,12 @@ export default class Media { const item = this.items?.find(item => item.itemId === itemId); if (item) { - const removeItemsRequest = new QueueRemoveItemsRequest([ itemId ]); - this._sendMediaMessage( - MediaMessageType.QueueRemove - , removeItemsRequest - , successCallback, errorCallback); + const queueRemoveItemsRequest = + new QueueRemoveItemsRequest([ itemId ]); + + this.#sendMediaMessage(queueRemoveItemsRequest) + .then(successCallback) + .catch(errorCallback); } } @@ -380,10 +347,9 @@ export default class Media { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - this._sendMediaMessage( - MediaMessageType.QueueRemove - , queueRemoveItemsRequest - , successCallback, errorCallback); + this.#sendMediaMessage(queueRemoveItemsRequest) + .then(successCallback) + .catch(errorCallback); } public queueReorderItems( @@ -391,10 +357,9 @@ export default class Media { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - this._sendMediaMessage( - MediaMessageType.QueueReorder - , queueReorderItemsRequest - , successCallback, errorCallback); + this.#sendMediaMessage(queueReorderItemsRequest) + .then(successCallback) + .catch(errorCallback); } public queueSetRepeatMode( @@ -405,10 +370,9 @@ export default class Media { const setPropertiesRequest = new QueueSetPropertiesRequest(); setPropertiesRequest.repeatMode = repeatMode; - this._sendMediaMessage( - MediaMessageType.QueueUpdate - , setPropertiesRequest - , successCallback, errorCallback); + this.#sendMediaMessage(setPropertiesRequest) + .then(successCallback) + .catch(errorCallback); } public queueUpdateItems( @@ -416,10 +380,9 @@ export default class Media { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - this._sendMediaMessage( - MediaMessageType.QueueUpdate - , queueUpdateItemsRequest - , successCallback, errorCallback); + this.#sendMediaMessage(queueUpdateItemsRequest) + .then(successCallback) + .catch(errorCallback); } public removeUpdateListener(listener: UpdateListener) { @@ -431,11 +394,10 @@ export default class Media { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - - this._sendMediaMessage( - MediaMessageType.Seek - , seekRequest - , successCallback, errorCallback); + this.#sendMediaMessage( + { type: "SEEK", ...seekRequest }) + .then(successCallback) + .catch(errorCallback); } public setVolume( @@ -443,11 +405,10 @@ export default class Media { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - - this._sendMediaMessage( - MediaMessageType.MediaSetVolume - , volumeRequest - , successCallback, errorCallback); + this.#sendMediaMessage( + { type: "MEDIA_SET_VOLUME", ...volumeRequest }) + .then(successCallback) + .catch(errorCallback); } public stop( @@ -459,18 +420,17 @@ export default class Media { stopRequest = new StopRequest(); } - this._sendMediaMessage( - MediaMessageType.Stop - , stopRequest - , () => { - this.#isActive = false; - this.#listener.disconnect(); + this.#sendMediaMessage({ + type: "STOP" + , ...stopRequest + }).then(() => { + this.#isActive = false; + this.#listener.disconnect(); - if (successCallback) { - successCallback(); - } - } - , errorCallback); + if (successCallback) { + successCallback(); + } + }).catch(errorCallback); } public supportsCommand(command: string): boolean { @@ -478,48 +438,43 @@ export default class Media { } - public _sendMediaMessage( - messageType: string - , message: MediaRequest - , successCallback?: SuccessCallback - , errorCallback?: ErrorCallback) { + #sendMediaMessage = async (message: SessionMediaMessage) => { + if (!this.media) { + return; + } // TODO: Handle this and other errors better if (!this.#isActive) { - if (errorCallback) { - errorCallback(new _Error(ErrorCode.SESSION_ERROR - , "INVALID_MEDIA_SESSION_ID" - , { - type: "INVALID_REQUEST" - , reason: "INVALID_MEDIA_SESSION_ID" - })); - } + throw new _Error(ErrorCode.SESSION_ERROR + , "INVALID_MEDIA_SESSION_ID" + , { + type: "INVALID_REQUEST" + , reason: "INVALID_MEDIA_SESSION_ID" + }); return; } - // TODO: Fix this - (message as any).type = messageType; + return new Promise((resolve, reject) => { + // TODO: Look at this again + (message as any).mediaSessionId = this.mediaSessionId; + (message as any).requestId = 0; + (message as any).sessionId = this.sessionId; - (message as any).mediaSessionId = this.mediaSessionId; - (message as any).requestId = 0; - (message as any).sessionId = this.sessionId; - (message as any).customData = null; + const messageId = uuid(); - const messageId = uuid(); + this.#sendMediaMessageCallbacks.set(messageId, [ + resolve, reject + ]); - this.#sendMediaMessageCallbacks.set(messageId, [ - successCallback - , errorCallback - ]); - - sendMessageResponse({ - subject: "bridge:media/sendMediaMessage" - , data: { - message - , messageId - , _id: this.#id - } + sendMessageResponse({ + subject: "bridge:media/sendMediaMessage" + , data: { + message + , messageId + , _id: this.#id + } + }); }); } } diff --git a/ext/src/types.ts b/ext/src/types.ts index 3ed29ce..2e07c3c 100644 --- a/ext/src/types.ts +++ b/ext/src/types.ts @@ -2,6 +2,10 @@ import { Volume } from "./shim/cast/dataClasses"; +import { LoadRequest, QueueInsertItemsRequest, QueueJumpRequest + , QueueLoadRequest, QueueRemoveItemsRequest, QueueReorderItemsRequest + , QueueSetPropertiesRequest, QueueUpdateItemsRequest } from "./shim/cast/media"; + export interface ReceiverDevice { host: string @@ -31,13 +35,37 @@ export interface ReceiverStatus { , volume: Volume } -export type ReceiverMessage = + +export type SessionMediaMessage = + { type: "PLAY", customData: (any | null) } + | { type: "PAUSE", customData: (any | null) } + | { type: "SEEK", customData: (any | null) } + | { type: "STOP", customData: (any | null) } + | { type: "MEDIA_GET_STATUS", customData: (any | null) } + | { type: "SET_PLAYBACK_RATE", playbackRate: number } + | { + type: "MEDIA_SET_VOLUME" + , volume: Partial + , customData: (any | null) + } + | { + type: "EDIT_TRACKS_INFO" + , requestId: number + , activeTrackIds?: (number[] | null) + , textTrackStyle?: (string | null) + } + | 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: { level: number } - | { muted: boolean } - }; + | { type: "SET_VOLUME", volume: Partial };