diff --git a/app/src/bridge/components/chromecast/StatusListener.ts b/app/src/bridge/components/chromecast/StatusListener.ts deleted file mode 100644 index a30b75e..0000000 --- a/app/src/bridge/components/chromecast/StatusListener.ts +++ /dev/null @@ -1,86 +0,0 @@ -"use strict"; - -import { Channel, Client } from "castv2"; -import { EventEmitter } from "events"; - -import { NS_CONNECTION - , NS_HEARTBEAT - , NS_RECEIVER } from "./Session"; - - -/** - * Creates a connection to a receiver device and forwards - * RECEIVER_STATUS updates to the extension. - */ -export default class StatusListener extends EventEmitter { - private client: Client; - private clientReceiver?: Channel; - private clientHeartbeatIntervalId?: NodeJS.Timeout; - - constructor(host: string, port: number) { - super(); - - this.client = new Client(); - this.client.connect({ host, port }, this.onConnect.bind(this)); - - this.client.on("close", () => { - clearInterval(this.clientHeartbeatIntervalId!); - }); - - this.client.on("error", () => { - clearInterval(this.clientHeartbeatIntervalId!); - }); - } - - /** - * Closes status listener connection. - */ - public deregister(): void { - if (this.clientReceiver) { - this.clientReceiver.send({ type: "CLOSE" }); - } - - this.client.close(); - } - - - private onConnect(): void { - const sourceId = "sender-0"; - const destinationId = "receiver-0"; - - const clientConnection = this.client.createChannel( - sourceId, destinationId, NS_CONNECTION, "JSON"); - const clientHeartbeat = this.client.createChannel( - sourceId, destinationId, NS_HEARTBEAT, "JSON"); - const clientReceiver = this.client.createChannel( - sourceId, destinationId, NS_RECEIVER, "JSON"); - - clientReceiver.on("message", data => { - switch (data.type) { - case "CLOSE": { - this.client.close(); - break; - } - - case "RECEIVER_STATUS": { - this.emit("receiverStatus", data.status); - break; - } - case "MEDIA_STATUS": { - this.emit("mediaStatus", data.status); - break; - } - } - }); - - clientConnection.send({ type: "CONNECT" }); - clientHeartbeat.send({ type: "PING" }); - clientReceiver.send({ type: "GET_STATUS", requestId: 1 }); - - this.clientReceiver = clientReceiver; - - this.clientHeartbeatIntervalId = setInterval(() => { - clientHeartbeat.send({ type: "PING" }); - }, 5000); - } -} diff --git a/app/src/bridge/components/discovery.ts b/app/src/bridge/components/discovery.ts index fa41898..812059a 100644 --- a/app/src/bridge/components/discovery.ts +++ b/app/src/bridge/components/discovery.ts @@ -1,5 +1,8 @@ "use strict"; +import { EventEmitter } from "events"; + +import { Channel, Client } from "castv2"; import mdns from "mdns"; import { sendMessage } from "../lib/nativeMessaging"; @@ -7,7 +10,9 @@ import { sendMessage } from "../lib/nativeMessaging"; import { ReceiverStatus } from "../types"; import { Message } from "../messaging"; -import StatusListener from "./chromecast/StatusListener"; +import { NS_CONNECTION + , NS_HEARTBEAT + , NS_RECEIVER } from "./chromecast/Session"; interface CastTxtRecord { @@ -29,28 +34,36 @@ const browser = mdns.createBrowser(mdns.tcp("googlecast"), { }); function onBrowserServiceUp(service: mdns.Service) { - // Ignore without txt record - if (!service.txtRecord) { + // Ignore without txt record / name + if (!service.txtRecord || !service.name) { return; } const txtRecord = service.txtRecord as CastTxtRecord; - sendMessage({ subject: "main:receiverDeviceUp" , data: { receiverDevice: { host: service.addresses[0] , port: service.port - , id: txtRecord.id + , id: service.name , friendlyName: txtRecord.fn } } }); } -function onBrowserServiceDown(_service: mdns.Service) { - // TODO: Fix service down detection +function onBrowserServiceDown(service: mdns.Service) { + // Ignore without name + if (!service.name) { + return; + } + + const txtRecord = service.txtRecord as CastTxtRecord; + sendMessage({ + subject: "main:receiverDeviceDown" + , data: { receiverDeviceId: service.name } + }); } browser.on("serviceUp", onBrowserServiceUp); @@ -73,7 +86,7 @@ export function startDiscovery(options: InitializeOptions) { const statusListeners = new Map(); function onStatusBrowserServiceUp(service: mdns.Service) { - if (!service.txtRecord) { + if (!service.name) { return; } @@ -81,23 +94,110 @@ export function startDiscovery(options: InitializeOptions) { service.addresses[0], service.port); listener.on("receiverStatus", (status: ReceiverStatus) => { + if (!service.name) { + return; + } + sendMessage({ subject: "main:receiverDeviceUpdated" , data: { - receiverDeviceId: service.txtRecord.id + receiverDeviceId: service.name , status } }); }); - statusListeners.set(service.txtRecord.id, listener); + statusListeners.set(service.name, listener); } - function onStatusBrowserServiceDown(_service: mdns.Service) { - // TODO: Fix service down detection + function onStatusBrowserServiceDown(service: mdns.Service) { + if (!service.name) { + return; + } + + const listener = statusListeners.get(service.name); + listener?.deregister(); } } export function stopDiscovery() { browser.stop(); } + + +/** + * Creates a connection to a receiver device and forwards + * RECEIVER_STATUS updates to the extension. + */ + export default class StatusListener extends EventEmitter { + private client: Client; + private clientReceiver?: Channel; + private clientHeartbeatIntervalId?: NodeJS.Timeout; + + constructor(host: string, port: number) { + super(); + + this.client = new Client(); + this.client.connect({ host, port }, this.onConnect.bind(this)); + + this.client.on("close", () => { + clearInterval(this.clientHeartbeatIntervalId!); + }); + + this.client.on("error", () => { + clearInterval(this.clientHeartbeatIntervalId!); + }); + } + + /** + * Closes status listener connection. + */ + public deregister(): void { + if (this.clientReceiver) { + this.clientReceiver.send({ type: "CLOSE" }); + } + + this.client.close(); + } + + + private onConnect(): void { + const sourceId = "sender-0"; + const destinationId = "receiver-0"; + + const clientConnection = this.client.createChannel( + sourceId, destinationId, NS_CONNECTION, "JSON"); + const clientHeartbeat = this.client.createChannel( + sourceId, destinationId, NS_HEARTBEAT, "JSON"); + const clientReceiver = this.client.createChannel( + sourceId, destinationId, NS_RECEIVER, "JSON"); + + clientReceiver.on("message", data => { + switch (data.type) { + case "CLOSE": { + this.client.close(); + break; + } + + case "RECEIVER_STATUS": { + this.emit("receiverStatus", data.status); + break; + } + case "MEDIA_STATUS": { + this.emit("mediaStatus", data.status); + break; + } + } + }); + + clientConnection.send({ type: "CONNECT" }); + clientHeartbeat.send({ type: "PING" }); + clientReceiver.send({ type: "GET_STATUS", requestId: 1 }); + + this.clientReceiver = clientReceiver; + + this.clientHeartbeatIntervalId = setInterval(() => { + clientHeartbeat.send({ type: "PING" }); + }, 5000); + } +}