@warren-bank/fx_cast_bridge 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ var __awaiter =
3
+ (this && this.__awaiter) ||
4
+ function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) {
6
+ return value instanceof P
7
+ ? value
8
+ : new P(function (resolve) {
9
+ resolve(value);
10
+ });
11
+ }
12
+ return new (P || (P = Promise))(function (resolve, reject) {
13
+ function fulfilled(value) {
14
+ try {
15
+ step(generator.next(value));
16
+ } catch (e) {
17
+ reject(e);
18
+ }
19
+ }
20
+ function rejected(value) {
21
+ try {
22
+ step(generator["throw"](value));
23
+ } catch (e) {
24
+ reject(e);
25
+ }
26
+ }
27
+ function step(result) {
28
+ result.done
29
+ ? resolve(result.value)
30
+ : adopt(result.value).then(fulfilled, rejected);
31
+ }
32
+ step(
33
+ (generator = generator.apply(thisArg, _arguments || [])).next()
34
+ );
35
+ });
36
+ };
37
+ var __importDefault =
38
+ (this && this.__importDefault) ||
39
+ function (mod) {
40
+ return mod && mod.__esModule ? mod : { default: mod };
41
+ };
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.run = run;
44
+ const cast_1 = require("./components/cast");
45
+ const discovery_1 = __importDefault(require("./components/cast/discovery"));
46
+ const remote_1 = __importDefault(require("./components/cast/remote"));
47
+ const mediaServer_1 = require("./components/mediaServer");
48
+ const config_json_1 = require("../../config.json");
49
+ process.on("SIGTERM", () =>
50
+ __awaiter(void 0, void 0, void 0, function* () {
51
+ discovery === null || discovery === void 0 ? void 0 : discovery.stop();
52
+ try {
53
+ yield (0, mediaServer_1.stopMediaServer)();
54
+ } catch (err) {
55
+ console.error("Error stopping media server!", err);
56
+ } finally {
57
+ process.exit(1);
58
+ }
59
+ })
60
+ );
61
+ let discovery = null;
62
+ const remotes = new Map();
63
+ function run(messaging) {
64
+ messaging.on("message", message => {
65
+ var _a, _b;
66
+ switch (message.subject) {
67
+ case "bridge:getInfo":
68
+ case "bridge:/getInfo": {
69
+ messaging.send(config_json_1.applicationVersion);
70
+ break;
71
+ }
72
+ case "bridge:startDiscovery": {
73
+ const { shouldWatchStatus } = message.data;
74
+ discovery = new discovery_1.default({
75
+ onDeviceFound(device) {
76
+ messaging.sendMessage({
77
+ subject: "main:deviceUp",
78
+ data: {
79
+ deviceId: device.id,
80
+ deviceInfo: device
81
+ }
82
+ });
83
+ if (shouldWatchStatus) {
84
+ remotes.set(
85
+ device.id,
86
+ new remote_1.default(device.host, {
87
+ port: device.port,
88
+ onReceiverStatusUpdate(status) {
89
+ messaging.sendMessage({
90
+ subject:
91
+ "main:receiverDeviceStatusUpdated",
92
+ data: {
93
+ deviceId: device.id,
94
+ status
95
+ }
96
+ });
97
+ },
98
+ onMediaStatusUpdate(status) {
99
+ if (!status) return;
100
+ messaging.sendMessage({
101
+ subject:
102
+ "main:receiverDeviceMediaStatusUpdated",
103
+ data: {
104
+ deviceId: device.id,
105
+ status
106
+ }
107
+ });
108
+ }
109
+ })
110
+ );
111
+ }
112
+ },
113
+ onDeviceDown(deviceId) {
114
+ var _a;
115
+ messaging.sendMessage({
116
+ subject: "main:deviceDown",
117
+ data: { deviceId }
118
+ });
119
+ if (shouldWatchStatus) {
120
+ if (remotes.has(deviceId)) {
121
+ (_a = remotes.get(deviceId)) === null ||
122
+ _a === void 0
123
+ ? void 0
124
+ : _a.disconnect();
125
+ remotes.delete(deviceId);
126
+ }
127
+ }
128
+ }
129
+ });
130
+ discovery.start();
131
+ break;
132
+ }
133
+ case "bridge:sendReceiverMessage": {
134
+ const { deviceId, message: receiverMessage } = message.data;
135
+ (_a = remotes.get(deviceId)) === null || _a === void 0
136
+ ? void 0
137
+ : _a.sendReceiverMessage(receiverMessage);
138
+ break;
139
+ }
140
+ case "bridge:sendMediaMessage": {
141
+ const { deviceId, message: mediaMessage } = message.data;
142
+ (_b = remotes.get(deviceId)) === null || _b === void 0
143
+ ? void 0
144
+ : _b.sendMediaMessage(mediaMessage);
145
+ break;
146
+ }
147
+ case "bridge:startMediaServer": {
148
+ const { filePath, port } = message.data;
149
+ (0, mediaServer_1.startMediaServer)(messaging, filePath, port);
150
+ break;
151
+ }
152
+ case "bridge:stopMediaServer": {
153
+ (0, mediaServer_1.stopMediaServer)();
154
+ break;
155
+ }
156
+ default: {
157
+ (0, cast_1.handleCastMessage)(messaging, message);
158
+ }
159
+ }
160
+ });
161
+ }
@@ -0,0 +1,154 @@
1
+ // https://github.com/futomi/node-dns-sd
2
+
3
+ const mDnsSd = require('node-dns-sd')
4
+ const ping = require('./ping')
5
+
6
+ const browsers = []
7
+
8
+ mDnsSd.ondata = (packet) => {
9
+ const service = packet_to_service(packet)
10
+ if (!service) return
11
+
12
+ for (const browser of browsers) {
13
+ browser.handleService(service)
14
+ }
15
+ }
16
+
17
+ const packet_to_service = (packet) => {
18
+ if (!packet || !(packet instanceof Object) || !packet.address || !packet.header || !(packet.header instanceof Object) || !packet.header.answers || !Array.isArray(packet.answers) || !(packet.header.answers === packet.answers.length) || !packet.header.additionals || !Array.isArray(packet.additionals) || !(packet.header.additionals === packet.additionals.length))
19
+ return null
20
+
21
+ const service = {
22
+ address: packet.address
23
+ }
24
+
25
+ for (const answer of packet.answers) {
26
+ if (answer && (answer instanceof Object) && answer.name && answer.rdata) {
27
+ service.name = answer.name
28
+ service.fullname = answer.rdata
29
+ break
30
+ }
31
+ }
32
+
33
+ if (!service.name)
34
+ return null
35
+
36
+ for (const xtra of packet.additionals) {
37
+ if ((xtra.name === service.fullname) && xtra.rdata && (xtra.rdata instanceof Object)) {
38
+ if (xtra.type === 'TXT')
39
+ service.txtRecord = xtra.rdata
40
+
41
+ if ((xtra.type === 'SRV') && xtra.rdata.port)
42
+ service.port = xtra.rdata.port
43
+ }
44
+ }
45
+
46
+ if (!service.txtRecord || !service.port)
47
+ return null
48
+
49
+ return service
50
+ }
51
+
52
+ class DnsSdBrowser {
53
+ constructor(filter, hasServiceChanged) {
54
+ this.filter = filter
55
+ this.hasServiceChanged = (typeof hasServiceChanged === 'function') ? hasServiceChanged : null
56
+ this.started = false
57
+ this.events = {}
58
+ this.services = []
59
+
60
+ setInterval(this.pingAllServices.bind(this), 5000)
61
+ }
62
+
63
+ pingAllServices() {
64
+ for (const service of this.services) {
65
+ ping(service.address, service.port, this.handlePing.bind(this))
66
+ }
67
+ }
68
+
69
+ handlePing(pingResult) {
70
+ if (pingResult.alive) return
71
+
72
+ for (let i=0; i < this.services.length; i++) {
73
+ const service = this.services[i]
74
+ if ((service.address === pingResult.hostname) && (service.port === pingResult.port)) {
75
+ this.services.splice(i, 1)
76
+ this.handleEvent('serviceDown', service)
77
+ break
78
+ }
79
+ }
80
+ }
81
+
82
+ on(event, callback) {
83
+ if (!this.events[event])
84
+ this.events[event] = []
85
+
86
+ this.events[event].push(callback)
87
+ }
88
+
89
+ handleService(newService) {
90
+ if (newService.name.indexOf(this.filter) >= 0) {
91
+ let dupl_idx = -1
92
+ let dupl_svc = null
93
+ let has_diff = false
94
+
95
+ for (let i=0; i < this.services.length; i++) {
96
+ const oldService = this.services[i]
97
+ if ((oldService.address === newService.address) && (oldService.port === newService.port)) {
98
+ dupl_idx = i
99
+ dupl_svc = oldService
100
+ has_diff = !!this.hasServiceChanged && this.hasServiceChanged(oldService, newService)
101
+ break
102
+ }
103
+ }
104
+ if (dupl_svc && has_diff) {
105
+ this.services.splice(dupl_idx, 1)
106
+ this.handleEvent('serviceDown', dupl_svc)
107
+ dupl_svc = null
108
+ }
109
+ if (!dupl_svc) {
110
+ this.services.push(newService)
111
+ this.handleEvent('serviceUp', newService)
112
+ }
113
+ }
114
+ }
115
+
116
+ handleEvent(event, service) {
117
+ if (Array.isArray(this.events[event])) {
118
+ for (const callback of this.events[event]) {
119
+ callback(service)
120
+ }
121
+ }
122
+ }
123
+
124
+ start() {
125
+ if (this.started) return
126
+
127
+ this.started = true
128
+
129
+ browsers.push(this)
130
+
131
+ mDnsSd.startMonitoring()
132
+ }
133
+
134
+ stop() {
135
+ if (!this.started) return
136
+
137
+ this.started = false
138
+
139
+ const index = browsers.indexOf(this)
140
+ if (index >= 0)
141
+ browsers.splice(index, 1)
142
+
143
+ if (!browsers.length)
144
+ mDnsSd.stopMonitoring()
145
+ }
146
+ }
147
+
148
+ const createBrowser = (filter, hasServiceChanged) => {
149
+ return new DnsSdBrowser(filter, hasServiceChanged)
150
+ }
151
+
152
+ module.exports = {
153
+ createBrowser
154
+ }
@@ -0,0 +1,20 @@
1
+ const {createConnection} = require('node:net')
2
+
3
+ const ping = (hostname, port, callback, timeout = 3000) => {
4
+ const socket = createConnection(port, hostname)
5
+ const handleSuccess = () => {
6
+ socket.end()
7
+ callback({alive: true, hostname, port})
8
+ }
9
+ const handleFailure = () => {
10
+ socket.destroy()
11
+ callback({alive: false, hostname, port})
12
+ }
13
+
14
+ socket.setTimeout(timeout)
15
+ socket.on('connect', handleSuccess)
16
+ socket.on('timeout', handleFailure)
17
+ socket.on('error', handleFailure)
18
+ }
19
+
20
+ module.exports = ping
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __awaiter =
3
+ (this && this.__awaiter) ||
4
+ function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) {
6
+ return value instanceof P
7
+ ? value
8
+ : new P(function (resolve) {
9
+ resolve(value);
10
+ });
11
+ }
12
+ return new (P || (P = Promise))(function (resolve, reject) {
13
+ function fulfilled(value) {
14
+ try {
15
+ step(generator.next(value));
16
+ } catch (e) {
17
+ reject(e);
18
+ }
19
+ }
20
+ function rejected(value) {
21
+ try {
22
+ step(generator["throw"](value));
23
+ } catch (e) {
24
+ reject(e);
25
+ }
26
+ }
27
+ function step(result) {
28
+ result.done
29
+ ? resolve(result.value)
30
+ : adopt(result.value).then(fulfilled, rejected);
31
+ }
32
+ step(
33
+ (generator = generator.apply(thisArg, _arguments || [])).next()
34
+ );
35
+ });
36
+ };
37
+ var __asyncValues =
38
+ (this && this.__asyncValues) ||
39
+ function (o) {
40
+ if (!Symbol.asyncIterator)
41
+ throw new TypeError("Symbol.asyncIterator is not defined.");
42
+ var m = o[Symbol.asyncIterator],
43
+ i;
44
+ return m
45
+ ? m.call(o)
46
+ : ((o =
47
+ typeof __values === "function"
48
+ ? __values(o)
49
+ : o[Symbol.iterator]()),
50
+ (i = {}),
51
+ verb("next"),
52
+ verb("throw"),
53
+ verb("return"),
54
+ (i[Symbol.asyncIterator] = function () {
55
+ return this;
56
+ }),
57
+ i);
58
+ function verb(n) {
59
+ i[n] =
60
+ o[n] &&
61
+ function (v) {
62
+ return new Promise(function (resolve, reject) {
63
+ (v = o[n](v)), settle(resolve, reject, v.done, v.value);
64
+ });
65
+ };
66
+ }
67
+ function settle(resolve, reject, d, v) {
68
+ Promise.resolve(v).then(function (v) {
69
+ resolve({ value: v, done: d });
70
+ }, reject);
71
+ }
72
+ };
73
+ var __importDefault =
74
+ (this && this.__importDefault) ||
75
+ function (mod) {
76
+ return mod && mod.__esModule ? mod : { default: mod };
77
+ };
78
+ Object.defineProperty(exports, "__esModule", { value: true });
79
+ exports.convertSrtToVtt = convertSrtToVtt;
80
+ const fs_1 = __importDefault(require("fs"));
81
+ function convertSrtToVtt(srtFilePath) {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ var _a, e_1, _b, _c;
84
+ const fileStream = fs_1.default.createReadStream(srtFilePath, {
85
+ encoding: "utf-8"
86
+ });
87
+ let fileContents = "";
88
+ try {
89
+ for (
90
+ var _d = true,
91
+ fileStream_1 = __asyncValues(fileStream),
92
+ fileStream_1_1;
93
+ (fileStream_1_1 = yield fileStream_1.next()),
94
+ (_a = fileStream_1_1.done),
95
+ !_a;
96
+ _d = true
97
+ ) {
98
+ _c = fileStream_1_1.value;
99
+ _d = false;
100
+ let chunk = _c;
101
+ if (!fileContents && chunk[0] === "\uFEFF") {
102
+ chunk = chunk.slice(1);
103
+ }
104
+ fileContents += chunk.replace(/$\r\n/gm, "\n");
105
+ }
106
+ } catch (e_1_1) {
107
+ e_1 = { error: e_1_1 };
108
+ } finally {
109
+ try {
110
+ if (!_d && !_a && (_b = fileStream_1.return))
111
+ yield _b.call(fileStream_1);
112
+ } finally {
113
+ if (e_1) throw e_1.error;
114
+ }
115
+ }
116
+ let vttText = "WEBVTT\n";
117
+ const REGEX_CAPTION =
118
+ /(?:(\d+)\n(\d{2}:\d{2}:\d{2},\d{3} --> \d{2}:\d{2}:\d{2},\d{3}))\n((?:.+)\n?)*/g;
119
+ for (const groups of fileContents.matchAll(REGEX_CAPTION)) {
120
+ const captionIndex = groups[1];
121
+ const captionTime = groups[2];
122
+ const captionText = groups[3];
123
+ vttText += `\n${captionIndex}\n`;
124
+ vttText += `${captionTime.replace(/,/g, ".")}\n`;
125
+ if (captionText) {
126
+ vttText += `${captionText}`;
127
+ }
128
+ }
129
+ return vttText;
130
+ });
131
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebsocketMessenger =
4
+ exports.StdioMessenger =
5
+ exports.Messenger =
6
+ void 0;
7
+ const tiny_typed_emitter_1 = require("tiny-typed-emitter");
8
+ const transforms_1 = require("../transforms");
9
+ class Messenger extends tiny_typed_emitter_1.TypedEmitter {}
10
+ exports.Messenger = Messenger;
11
+ class StdioMessenger extends tiny_typed_emitter_1.TypedEmitter {
12
+ constructor() {
13
+ super();
14
+ this.decodeTransform = new transforms_1.DecodeTransform();
15
+ this.encodeTransform = new transforms_1.EncodeTransform();
16
+ process.stdin.pipe(this.decodeTransform);
17
+ this.encodeTransform.pipe(process.stdout);
18
+ this.decodeTransform.on("error", err =>
19
+ console.error("err (message decode):", err)
20
+ );
21
+ this.encodeTransform.on("error", err =>
22
+ console.error("err (message encode):", err)
23
+ );
24
+ this.decodeTransform.on("data", message => {
25
+ this.emit("message", message);
26
+ });
27
+ }
28
+ sendMessage(message) {
29
+ this.send(message);
30
+ }
31
+ send(data) {
32
+ this.encodeTransform.write(data);
33
+ }
34
+ }
35
+ exports.StdioMessenger = StdioMessenger;
36
+ class WebsocketMessenger extends tiny_typed_emitter_1.TypedEmitter {
37
+ constructor(socket) {
38
+ super();
39
+ this.socket = socket;
40
+ socket.on("message", message => {
41
+ try {
42
+ const parsed = JSON.parse(message);
43
+ this.emit("message", parsed);
44
+ } catch (err) {
45
+ socket.close();
46
+ }
47
+ });
48
+ }
49
+ sendMessage(message) {
50
+ this.send(message);
51
+ }
52
+ send(data) {
53
+ this.socket.send(JSON.stringify(data));
54
+ }
55
+ }
56
+ exports.WebsocketMessenger = WebsocketMessenger;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReceiverDeviceCapabilities = void 0;
4
+ var ReceiverDeviceCapabilities;
5
+ (function (ReceiverDeviceCapabilities) {
6
+ ReceiverDeviceCapabilities[(ReceiverDeviceCapabilities["NONE"] = 0)] =
7
+ "NONE";
8
+ ReceiverDeviceCapabilities[(ReceiverDeviceCapabilities["VIDEO_OUT"] = 1)] =
9
+ "VIDEO_OUT";
10
+ ReceiverDeviceCapabilities[(ReceiverDeviceCapabilities["VIDEO_IN"] = 2)] =
11
+ "VIDEO_IN";
12
+ ReceiverDeviceCapabilities[(ReceiverDeviceCapabilities["AUDIO_OUT"] = 4)] =
13
+ "AUDIO_OUT";
14
+ ReceiverDeviceCapabilities[(ReceiverDeviceCapabilities["AUDIO_IN"] = 8)] =
15
+ "AUDIO_IN";
16
+ ReceiverDeviceCapabilities[
17
+ (ReceiverDeviceCapabilities["MULTIZONE_GROUP"] = 32)
18
+ ] = "MULTIZONE_GROUP";
19
+ })(
20
+ ReceiverDeviceCapabilities ||
21
+ (exports.ReceiverDeviceCapabilities = ReceiverDeviceCapabilities = {})
22
+ );