mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-08 16:49:58 +00:00
164 lines
4.6 KiB
TypeScript
164 lines
4.6 KiB
TypeScript
"use strict";
|
|
|
|
import bridge from "../lib/bridge";
|
|
import logger from "../lib/logger";
|
|
import { Message, Port } from "../messaging";
|
|
|
|
import { TypedEventTarget } from "../lib/TypedEventTarget";
|
|
import { Receiver, ReceiverStatus } from "../types";
|
|
|
|
|
|
interface EventMap {
|
|
"serviceUp": Receiver;
|
|
"serviceDown": { id: string };
|
|
"statusUpdate": { id: string, status: ReceiverStatus };
|
|
}
|
|
|
|
export default new class StatusManager
|
|
extends TypedEventTarget<EventMap> {
|
|
|
|
private bridgePort: (Port | null) = null;
|
|
private receivers = new Map<string, Receiver>();
|
|
|
|
constructor() {
|
|
super();
|
|
|
|
// Bind listeners
|
|
this.onBridgePortMessage = this.onBridgePortMessage.bind(this);
|
|
this.onBridgePortDisconnect = this.onBridgePortDisconnect.bind(this);
|
|
}
|
|
|
|
public async init() {
|
|
if (!this.bridgePort) {
|
|
this.bridgePort = await this.createBridgePort();
|
|
}
|
|
}
|
|
|
|
public *getReceivers() {
|
|
for (const [ , receiver ] of this.receivers) {
|
|
if (receiver.status && receiver.status.application
|
|
&& receiver.status.volume) {
|
|
yield receiver;
|
|
}
|
|
}
|
|
}
|
|
|
|
public async stopReceiverApp(receiver: Receiver) {
|
|
if (!this.bridgePort) {
|
|
return;
|
|
}
|
|
|
|
this.bridgePort.postMessage({
|
|
subject: "bridge:stopReceiverApp"
|
|
, data: { receiver }
|
|
});
|
|
}
|
|
|
|
private async createBridgePort() {
|
|
const bridgePort = await bridge.connect();
|
|
bridgePort.onMessage.addListener(this.onBridgePortMessage);
|
|
bridgePort.onDisconnect.addListener(this.onBridgePortDisconnect);
|
|
|
|
bridgePort.postMessage({
|
|
subject: "bridge:initialize"
|
|
, data: {
|
|
shouldWatchStatus: true
|
|
}
|
|
});
|
|
|
|
return bridgePort;
|
|
}
|
|
|
|
/**
|
|
* Handles incoming bridge status messages, manages the
|
|
* receiver list, and dispatches events.
|
|
*/
|
|
private onBridgePortMessage(message: Message) {
|
|
switch (message.subject) {
|
|
case "main:serviceUp": {
|
|
const { data: receiver } = message;
|
|
this.receivers.set(receiver.id, receiver);
|
|
|
|
this.dispatchEvent(new CustomEvent("serviceUp", {
|
|
detail: receiver
|
|
}));
|
|
|
|
break;
|
|
}
|
|
|
|
case "main:serviceDown": {
|
|
const { data: { id }} = message;
|
|
|
|
if (this.receivers.has(id)) {
|
|
this.receivers.delete(id);
|
|
}
|
|
|
|
this.dispatchEvent(new CustomEvent("serviceDown", {
|
|
detail: { id }
|
|
}));
|
|
|
|
break;
|
|
}
|
|
|
|
case "main:updateReceiverStatus": {
|
|
const { data: { id, status }} = message;
|
|
const receiver = this.receivers.get(id);
|
|
|
|
if (!receiver) {
|
|
throw logger.error(`Could not find receiver (${id}) specified in status message.`);
|
|
}
|
|
|
|
// Merge with existing
|
|
this.receivers.set(id, {
|
|
...receiver
|
|
, status: {
|
|
...receiver.status
|
|
, ...status
|
|
}
|
|
});
|
|
|
|
this.dispatchEvent(new CustomEvent("statusUpdate", {
|
|
detail: { id, status }
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Runs once the status bridge has disconnected. Sends
|
|
* serviceDown messages for all receivers to all shims to
|
|
* update receiver availability, then clears the receiver
|
|
* list.
|
|
*
|
|
* Attempts to reinitialize the status bridge after 10
|
|
* seconds. If it fails immediately, this handler will be
|
|
* triggered again and the timer is reset for another 10
|
|
* seconds.
|
|
*/
|
|
private onBridgePortDisconnect() {
|
|
for (const [ , receiver ] of this.receivers) {
|
|
const serviceDownEvent = new CustomEvent("serviceDown", {
|
|
detail: { id: receiver.id }
|
|
});
|
|
|
|
this.dispatchEvent(serviceDownEvent);
|
|
}
|
|
|
|
// Cleanup
|
|
this.receivers.clear();
|
|
|
|
if (this.bridgePort) {
|
|
this.bridgePort.onDisconnect.removeListener(
|
|
this.onBridgePortDisconnect);
|
|
this.bridgePort.onMessage.removeListener(
|
|
this.onBridgePortMessage);
|
|
|
|
this.bridgePort = null;
|
|
}
|
|
|
|
window.setTimeout(async () => {
|
|
this.bridgePort = await this.createBridgePort();
|
|
}, 10000);
|
|
}
|
|
};
|