Files
fx_cast/app/src/bridge/components/discovery.ts
2020-09-02 19:26:58 +01:00

112 lines
3.1 KiB
TypeScript

"use strict";
import mdns from "mdns";
import StatusListener from "./chromecast/StatusListener";
import { ReceiverStatus } from "../types";
import { sendMessage } from "../lib/messaging";
const browser = mdns.createBrowser(mdns.tcp("googlecast"), {
resolverSequence: [
mdns.rst.DNSServiceResolve()
, "DNSServiceGetAddrInfo" in mdns.dns_sd
? mdns.rst.DNSServiceGetAddrInfo()
// Some issues on Linux with IPv6, so restrict to IPv4
: mdns.rst.getaddrinfo({ families: [ 4 ] })
, mdns.rst.makeAddressesUnique()
]
});
function onBrowserServiceUp (service: mdns.Service) {
sendMessage({
subject: "main:/serviceUp"
, data: {
host: service.addresses[0]
, port: service.port
, id: service.txtRecord.id
, friendlyName: service.txtRecord.fn
}
});
}
function onBrowserServiceDown (service: mdns.Service) {
sendMessage({
subject: "main:/serviceDown"
, data: {
id: service.txtRecord.id
}
});
}
browser.on("serviceUp", onBrowserServiceUp);
browser.on("serviceDown", onBrowserServiceDown);
interface InitializeOptions {
shouldWatchStatus?: boolean;
}
export function startDiscovery (options: InitializeOptions) {
if (options.shouldWatchStatus) {
browser.on("serviceUp", onStatusBrowserServiceUp);
browser.on("serviceDown", onStatusBrowserServiceDown);
}
browser.start();
// Receiver status listeners for status mode
const statusListeners = new Map<string, StatusListener>();
function onStatusBrowserServiceUp (service: mdns.Service) {
const { id } = service.txtRecord;
const listener = new StatusListener(
service.addresses[0]
, service.port);
listener.on("receiverStatus", (status: ReceiverStatus) => {
const receiverStatusMessage: any = {
subject: "main:/receiverStatus"
, data: {
id
, status: {
volume: {
level: status.volume.level
, muted: status.volume.muted
}
}
}
};
if (status.applications && status.applications.length) {
const application = status.applications[0];
receiverStatusMessage.data.status.application = {
appId: application.appId
, displayName: application.displayName
, isIdleScreen: application.isIdleScreen
, statusText: application.statusText
};
}
sendMessage(receiverStatusMessage);
});
statusListeners.set(id, listener);
}
function onStatusBrowserServiceDown (service: mdns.Service) {
const { id } = service.txtRecord;
if (statusListeners.has(id)) {
statusListeners.get(id)!.deregister();
statusListeners.delete(id);
}
}
}
export function stopDiscovery () {
browser.stop();
}