diff --git a/app/src/bridge/components/chromecast/Session.ts b/app/src/bridge/components/chromecast/Session.ts index 16251c7..3f4bcd3 100644 --- a/app/src/bridge/components/chromecast/Session.ts +++ b/app/src/bridge/components/chromecast/Session.ts @@ -130,6 +130,22 @@ export default class Session { this.close(); break; + case "bridge:session/sendReceiverMessage": { + let wasError = false; + try { + this.clientReceiver?.send(message.data.message); + } catch (err) { + wasError = true; + } + + this.sendMessage("shim:session/sendReceiverMessageResponse", { + messageId: message.data.messageId + , wasError + }); + + break; + } + case "bridge:session/impl_addMessageListener": this._impl_addMessageListener(message.data.namespace); break; @@ -140,22 +156,6 @@ export default class Session { , message.data.message , message.data.messageId); break; - - case "bridge:session/impl_setReceiverMuted": - this._impl_setReceiverMuted( - message.data.muted - , message.data.volumeId); - break; - - case "bridge:session/impl_setReceiverVolumeLevel": - this._impl_setReceiverVolumeLevel( - message.data.newLevel - , message.data.volumeId); - break; - - case "bridge:session/impl_stop": - this._impl_stop(message.data.stopId); - break; } } @@ -209,7 +209,7 @@ export default class Session { } this.createChannel(namespace); - this.channelMap.get(namespace)!.send(message); + this.channelMap.get(namespace)?.send(message); } catch (err) { error = true; } @@ -220,66 +220,4 @@ export default class Session { }); } - private _impl_setReceiverMuted(muted: boolean, volumeId: string) { - - let error = false; - - try { - this.clientReceiver!.send({ - type: "SET_VOLUME" - , volume: { muted } - , requestId: 0 - }); - } catch (err) { - error = true; - } - - this.sendMessage("shim:session/impl_setReceiverMuted", { - volumeId - , error - }); - } - - private _impl_setReceiverVolumeLevel(newLevel: number, volumeId: string) { - - let error = false; - - try { - this.clientReceiver!.send({ - type: "SET_VOLUME" - , volume: { level: newLevel } - , requestId: 0 - }); - } catch (err) { - error = true; - } - - this.sendMessage("shim:session/impl_setReceiverVolumeLevel", { - volumeId - , error - }); - } - - private _impl_stop(stopId: string) { - let error = false; - - try { - this.clientReceiver!.send({ - type: "STOP" - , sessionId: this.sessionId - , requestId: 0 - }); - } catch (err) { - error = true; - } - - this.client.close(); - - clearInterval(this.clientHeartbeatIntervalId!); - - this.sendMessage("shim:session/impl_stop", { - stopId - , error - }); - } } diff --git a/app/src/bridge/messaging.ts b/app/src/bridge/messaging.ts index cdd8d08..b52f55e 100644 --- a/app/src/bridge/messaging.ts +++ b/app/src/bridge/messaging.ts @@ -1,9 +1,11 @@ "use strict"; import { ReceiverDevice + , ReceiverMessage , ReceiverSelectionCast , ReceiverSelectionStop - , ReceiverStatus } from "./types"; + , ReceiverStatus + , Volume } from "./types"; type MessageDefinitions = { @@ -15,7 +17,11 @@ type MessageDefinitions = { , displayName: string , statusText: string } - , "shim:session/updateStatus": { volume: any /* Volume */ } + , "shim:session/updateStatus": { volume: Volume } + , "shim:session/sendReceiverMessageResponse": { + messageId: string + , wasError: boolean + } , "shim:session/impl_addMessageListener": { namespace: string , data: string @@ -24,18 +30,6 @@ type MessageDefinitions = { messageId: string , error: boolean } - , "shim:session/impl_setReceiverMuted": { - volumeId: string - , error: boolean - } - , "shim:session/impl_setReceiverVolumeLevel": { - volumeId: string - , error: boolean - } - , "shim:session/impl_stop": { - stopId: string - , error: boolean - } // Bridge session messages , "bridge:session/initialize": { @@ -46,6 +40,11 @@ type MessageDefinitions = { , _id: string } , "bridge:session/close": {} + , "bridge:session/sendReceiverMessage": { + message: ReceiverMessage + , messageId: string + , _id: string + } , "bridge:session/impl_leave": { id: string , _id: string @@ -56,20 +55,6 @@ type MessageDefinitions = { , messageId: string , _id: string } - , "bridge:session/impl_setReceiverMuted": { - muted: boolean - , volumeId: string - , _id: string - } - , "bridge:session/impl_setReceiverVolumeLevel": { - newLevel: number - , volumeId: string - , _id: string - } - , "bridge:session/impl_stop": { - stopId: string; - _id: string; - } , "bridge:session/impl_addMessageListener": { namespace: string; _id: string; diff --git a/app/src/bridge/types.ts b/app/src/bridge/types.ts index 0d1b2f0..253a5ff 100644 --- a/app/src/bridge/types.ts +++ b/app/src/bridge/types.ts @@ -20,6 +20,7 @@ export interface ReceiverStatus { , volume: Volume } + export interface MediaStatus { mediaSessionId: number; supportedMediaCommands: number; @@ -102,3 +103,15 @@ export class Volume { public level: (number | null) = null , public muted: (boolean | null) = null) {} } + + +export type ReceiverMessage = + { 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 } + }; diff --git a/ext/src/messaging.ts b/ext/src/messaging.ts index 3434de3..7d6a2c6 100644 --- a/ext/src/messaging.ts +++ b/ext/src/messaging.ts @@ -1,13 +1,19 @@ "use strict"; import Messenger from "./lib/Messenger"; -import { TypedPort } from "./lib/TypedPort"; +import { TypedPort } from "./lib/TypedPort"; import { BridgeInfo } from "./lib/bridge"; -import { ReceiverDevice, ReceiverStatus } from "./types"; + +import { ReceiverDevice + , ReceiverMessage + , ReceiverStatus } from "./types"; + import { ReceiverSelectorMediaType } from "./background/receiverSelector"; -import { ReceiverSelection, ReceiverSelectionCast, ReceiverSelectionStop } - from "./background/receiverSelector/ReceiverSelector"; +import { ReceiverSelection + , ReceiverSelectionCast + , ReceiverSelectionStop } + from "./background/receiverSelector/ReceiverSelector"; import { Volume } from "./shim/cast/dataClasses"; import { MediaInfo } from "./shim/cast/media"; @@ -74,6 +80,10 @@ type AppMessageDefinitions = { , statusText: string } , "shim:session/updateStatus": { volume: Volume } + , "shim:session/sendReceiverMessageResponse": { + messageId: string + , wasError: boolean + } , "shim:session/impl_addMessageListener": { namespace: string , data: string @@ -82,18 +92,6 @@ type AppMessageDefinitions = { messageId: string , error: boolean } - , "shim:session/impl_setReceiverMuted": { - volumeId: string - , error: boolean - } - , "shim:session/impl_setReceiverVolumeLevel": { - volumeId: string - , error: boolean - } - , "shim:session/impl_stop": { - stopId: string - , error: boolean - } // Bridge session messages , "bridge:session/initialize": { @@ -104,6 +102,11 @@ type AppMessageDefinitions = { , _id: string } , "bridge:session/close": {} + , "bridge:session/sendReceiverMessage": { + message: ReceiverMessage + , messageId: string + , _id: string + } , "bridge:session/impl_leave": { id: string , _id: string @@ -114,20 +117,6 @@ type AppMessageDefinitions = { , messageId: string , _id: string } - , "bridge:session/impl_setReceiverMuted": { - muted: boolean - , volumeId: string - , _id: string - } - , "bridge:session/impl_setReceiverVolumeLevel": { - newLevel: number - , volumeId: string - , _id: string - } - , "bridge:session/impl_stop": { - stopId: string; - _id: string; - } , "bridge:session/impl_addMessageListener": { namespace: string; _id: string; diff --git a/ext/src/shim/cast/Session.ts b/ext/src/shim/cast/Session.ts index 60dcc2a..726338f 100644 --- a/ext/src/shim/cast/Session.ts +++ b/ext/src/shim/cast/Session.ts @@ -3,9 +3,9 @@ import { v4 as uuid } from "uuid"; import logger from "../../lib/logger"; +import { ReceiverMessage } from "../../types"; -import { ListenerObject - , onMessage +import { onMessage , sendMessageResponse } from "../eventMessageChannel"; import { Callbacks @@ -38,11 +38,8 @@ export default class Session { #messageListeners = new Map>(); #updateListeners = new Set(); - #leaveCallbacks = new Map(); #sendMessageCallbacks = new Map(); - #setReceiverMutedCallbacks = new Map(); - #setReceiverVolumeLevelCallbacks = new Map(); - #stopCallbacks = new Map(); + #sendReceiverMessageCallbacks = new Map(); #listener = onMessage(message => { // Filter other session messages @@ -103,6 +100,17 @@ 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; @@ -132,66 +140,6 @@ export default class Session { break; } - - case "shim:session/impl_setReceiverMuted": { - const { volumeId, error } = message.data; - const [ successCallback, errorCallback ] = - this.#setReceiverMutedCallbacks.get(volumeId) ?? []; - - if (error && errorCallback) { - errorCallback(new _Error(ErrorCode.SESSION_ERROR)); - } else if (successCallback) { - successCallback(); - } - - this.#setReceiverMutedCallbacks.delete(volumeId); - - break; - } - - case "shim:session/impl_setReceiverVolumeLevel": { - const { volumeId, error } = message.data; - const [ successCallback, errorCallback ] = - this.#setReceiverVolumeLevelCallbacks - .get(volumeId) ?? []; - - if (error && errorCallback) { - errorCallback(new _Error(ErrorCode.SESSION_ERROR)); - } else if (successCallback) { - successCallback(); - } - - this.#setReceiverVolumeLevelCallbacks.delete(volumeId); - - break; - } - - case "shim:session/impl_stop": { - const { stopId, error } = message.data; - const [ successCallback, errorCallback ] = - this.#stopCallbacks.get(stopId) ?? []; - - // Disconnect from extension messages - this.#listener.disconnect(); - - if (error && errorCallback) { - errorCallback(new _Error(ErrorCode.SESSION_ERROR)); - } else { - this.status = SessionStatus.STOPPED; - - for (const listener of this.#updateListeners) { - listener(false); - } - - if (successCallback) { - successCallback(); - } - } - - this.#stopCallbacks.delete(stopId); - - break; - } } }) @@ -262,23 +210,10 @@ export default class Session { } public leave( - successCallback?: SuccessCallback - , errorCallback?: ErrorCallback): void { + _successCallback?: SuccessCallback + , _errorCallback?: ErrorCallback): void { - const id = uuid(); - - sendMessageResponse({ - subject: "bridge:session/impl_leave" - , data: { - id - , _id: this.#id - } - }); - - this.#leaveCallbacks.set(id, [ - successCallback - , errorCallback - ]); + logger.info("STUB :: Session#leave"); } public loadMedia( @@ -394,21 +329,11 @@ export default class Session { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback) { - const volumeId = uuid(); - - sendMessageResponse({ - subject: "bridge:session/impl_setReceiverMuted" - , data: { - muted - , volumeId - , _id: this.#id - } - }); - - this.#setReceiverMutedCallbacks.set(volumeId, [ - successCallback - , errorCallback - ]); + this.#sendReceiverMessage( + { type: "SET_VOLUME" + , volume: { muted }}) + .then(successCallback) + .catch(errorCallback); } public setReceiverVolumeLevel( @@ -416,44 +341,50 @@ export default class Session { , successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - const volumeId = uuid(); - - sendMessageResponse({ - subject: "bridge:session/impl_setReceiverVolumeLevel" - , data: { - newLevel - , volumeId - , _id: this.#id - } - }); - - this.#setReceiverVolumeLevelCallbacks.set(volumeId, [ - successCallback - , errorCallback - ]); + this.#sendReceiverMessage( + { type: "SET_VOLUME" + , volume: { level: newLevel }}) + .then(successCallback) + .catch(errorCallback); } public stop( successCallback?: SuccessCallback , errorCallback?: ErrorCallback): void { - const stopId = uuid(); - - sendMessageResponse({ - subject: "bridge:session/impl_stop" - , data: { - stopId - , _id: this.#id - } - }); - - this.#stopCallbacks.set(stopId, [ - successCallback - , errorCallback - ]); + this.#sendReceiverMessage( + { type: "STOP" + , sessionId: this.sessionId }) + .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: ReceiverMessage) => { + return new Promise((resolve, reject) => { + 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); } diff --git a/ext/src/types.ts b/ext/src/types.ts index 6147995..3ed29ce 100644 --- a/ext/src/types.ts +++ b/ext/src/types.ts @@ -30,3 +30,14 @@ export interface ReceiverStatus { , userEq: unknown , volume: Volume } + +export type ReceiverMessage = + { 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 } + };