mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-11 18:19:58 +00:00
Split status listener handling into class
This commit is contained in:
80
app/src/StatusListener.ts
Normal file
80
app/src/StatusListener.ts
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
import { Channel, Client } from "castv2";
|
||||||
|
import { EventEmitter } from "events";
|
||||||
|
|
||||||
|
const NS_CONNECTION = "urn:x-cast:com.google.cast.tp.connection";
|
||||||
|
const NS_HEARTBEAT = "urn:x-cast:com.google.cast.tp.heartbeat";
|
||||||
|
const NS_RECEIVER = "urn:x-cast:com.google.cast.receiver";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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: number;
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private host: string
|
||||||
|
, private port: number) {
|
||||||
|
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.client = new Client();
|
||||||
|
this.client.connect({ host, port }, this.onConnect.bind(this));
|
||||||
|
|
||||||
|
this.client.on("close", () => {
|
||||||
|
clearInterval(this.clientHeartbeatIntervalId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes status listener connection.
|
||||||
|
*/
|
||||||
|
public deregister (): void {
|
||||||
|
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": {
|
||||||
|
// Send update message
|
||||||
|
this.emit("statusUpdate", 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" });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
115
app/src/main.ts
115
app/src/main.ts
@@ -8,21 +8,15 @@ import path from "path";
|
|||||||
|
|
||||||
import Media from "./Media";
|
import Media from "./Media";
|
||||||
import Session from "./Session";
|
import Session from "./Session";
|
||||||
|
import StatusListener from "./StatusListener";
|
||||||
import * as transforms from "./transforms";
|
import * as transforms from "./transforms";
|
||||||
|
|
||||||
import { Channel, Client } from "castv2";
|
|
||||||
|
|
||||||
import { Message } from "./types";
|
import { Message } from "./types";
|
||||||
|
|
||||||
import { __applicationName
|
import { __applicationName
|
||||||
, __applicationVersion } from "../package.json";
|
, __applicationVersion } from "../package.json";
|
||||||
|
|
||||||
|
|
||||||
const NS_CONNECTION = "urn:x-cast:com.google.cast.tp.connection";
|
|
||||||
const NS_HEARTBEAT = "urn:x-cast:com.google.cast.tp.heartbeat";
|
|
||||||
const NS_RECEIVER = "urn:x-cast:com.google.cast.receiver";
|
|
||||||
|
|
||||||
|
|
||||||
// Increase listener limit
|
// Increase listener limit
|
||||||
events.EventEmitter.defaultMaxListeners = 50;
|
events.EventEmitter.defaultMaxListeners = 50;
|
||||||
|
|
||||||
@@ -188,13 +182,24 @@ async function handleMessage (message: Message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initialize (options: InitializeOptions) {
|
function initialize (options: InitializeOptions) {
|
||||||
|
const statusListeners = new Map<string, StatusListener>();
|
||||||
|
|
||||||
browser.on("serviceUp", (service: dnssd.Service) => {
|
browser.on("serviceUp", (service: dnssd.Service) => {
|
||||||
const address = service.addresses[0];
|
const address = service.addresses[0];
|
||||||
const port = service.port;
|
const port = service.port;
|
||||||
const id = service.txt.id;
|
const id = service.txt.id;
|
||||||
|
|
||||||
if (options.shouldWatchStatus) {
|
if (options.shouldWatchStatus) {
|
||||||
registerStatusListener(address, port, id);
|
const listener = new StatusListener(address, port);
|
||||||
|
|
||||||
|
listener.on("statusUpdate", (status: any) => {
|
||||||
|
sendMessage({
|
||||||
|
subject: "main:/receiverStatusUpdate"
|
||||||
|
, data: { id, status }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
statusListeners.set(id, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
transforms.encode.write({
|
transforms.encode.write({
|
||||||
@@ -210,8 +215,8 @@ function initialize (options: InitializeOptions) {
|
|||||||
browser.on("serviceDown", (service: dnssd.Service) => {
|
browser.on("serviceDown", (service: dnssd.Service) => {
|
||||||
const id = service.txt.id;
|
const id = service.txt.id;
|
||||||
|
|
||||||
if (options.shouldWatchStatus) {
|
if (options.shouldWatchStatus && statusListeners.has(id)) {
|
||||||
deregisterStatusListener(id);
|
statusListeners.get(id).deregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
transforms.encode.write({
|
transforms.encode.write({
|
||||||
@@ -222,93 +227,3 @@ function initialize (options: InitializeOptions) {
|
|||||||
|
|
||||||
browser.start();
|
browser.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface StatusListener {
|
|
||||||
client: Client;
|
|
||||||
clientReceiver: Channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map of client connections
|
|
||||||
const statusListeners = new Map<string, StatusListener>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a connection to a receiver device and forwards
|
|
||||||
* RECEIVER_STATUS updates to the extension.
|
|
||||||
*/
|
|
||||||
function registerStatusListener (
|
|
||||||
host: string
|
|
||||||
, port: number
|
|
||||||
, id: string) {
|
|
||||||
|
|
||||||
const client = new Client();
|
|
||||||
|
|
||||||
const sourceId = "sender-0";
|
|
||||||
const destinationId = "receiver-0";
|
|
||||||
|
|
||||||
let heartbeatIntervalId: number;
|
|
||||||
|
|
||||||
client.connect({ host, port }, () => {
|
|
||||||
const clientConnection = client.createChannel(
|
|
||||||
sourceId, destinationId, NS_CONNECTION, "JSON");
|
|
||||||
const clientHeartbeat = client.createChannel(
|
|
||||||
sourceId, destinationId, NS_HEARTBEAT, "JSON");
|
|
||||||
const clientReceiver = client.createChannel(
|
|
||||||
sourceId, destinationId, NS_RECEIVER, "JSON");
|
|
||||||
|
|
||||||
|
|
||||||
clientReceiver.on("message", data => {
|
|
||||||
switch (data.type) {
|
|
||||||
case "CLOSE": {
|
|
||||||
client.close();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "RECEIVER_STATUS": {
|
|
||||||
// Send update message
|
|
||||||
transforms.encode.write({
|
|
||||||
subject: "main:/receiverStatusUpdate"
|
|
||||||
, data: {
|
|
||||||
id
|
|
||||||
, status: data.status
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
clientConnection.send({ type: "CONNECT" });
|
|
||||||
clientHeartbeat.send({ type: "PING" });
|
|
||||||
clientReceiver.send({ type: "GET_STATUS", requestId: 1 });
|
|
||||||
|
|
||||||
heartbeatIntervalId = setInterval(() => {
|
|
||||||
clientHeartbeat.send({ type: "PING" });
|
|
||||||
});
|
|
||||||
|
|
||||||
statusListeners.set(id, {
|
|
||||||
client
|
|
||||||
, clientReceiver
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("close", () => {
|
|
||||||
clearInterval(heartbeatIntervalId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes status listener connection for a given receiver
|
|
||||||
* device.
|
|
||||||
*/
|
|
||||||
function deregisterStatusListener (id: string) {
|
|
||||||
const { client, clientReceiver } = statusListeners.get(id);
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
clientReceiver.send({ type: "CLOSE" });
|
|
||||||
client.close();
|
|
||||||
|
|
||||||
// Remove from map
|
|
||||||
statusListeners.delete(id);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user