Adds support for zeroconf (Bonjour)
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node-fetch": "^2.6.12",
|
||||
"bonjour-service": "^1.3.0",
|
||||
"classnames": "^2.5.1",
|
||||
"express": "^4.21.2",
|
||||
"express-ws": "^5.0.2",
|
||||
|
||||
@@ -22,6 +22,7 @@ import { WebSocket } from "ws";
|
||||
import { getLinkPreview } from "link-preview-js";
|
||||
import { PlaylistItem, LinkMetadata } from './types';
|
||||
import { FavoritesStore } from "./FavoritesStore";
|
||||
import { Bonjour } from "bonjour-service";
|
||||
|
||||
interface PendingCommand {
|
||||
resolve: (value: any) => void;
|
||||
@@ -48,6 +49,7 @@ export class MediaPlayer {
|
||||
private requestId: number = 1;
|
||||
private dataBuffer: string = '';
|
||||
private metadata: Map<string, LinkMetadata> = new Map();
|
||||
private bonjourInstance: Bonjour | null = null;
|
||||
|
||||
constructor() {
|
||||
this.socket = this.tryRespawnPlayerProcess();
|
||||
@@ -58,6 +60,41 @@ export class MediaPlayer {
|
||||
};
|
||||
}
|
||||
|
||||
public startZeroconfService(port: number) {
|
||||
if (this.bonjourInstance) {
|
||||
console.log("Zeroconf service already running");
|
||||
return;
|
||||
}
|
||||
|
||||
this.bonjourInstance = new Bonjour();
|
||||
|
||||
const service = this.bonjourInstance.publish({
|
||||
name: 'QueueCube Media Server',
|
||||
type: 'queuecube',
|
||||
port: port,
|
||||
txt: {
|
||||
version: '1.0.0',
|
||||
features: 'playlist,favorites,screenshare'
|
||||
}
|
||||
});
|
||||
|
||||
service.on('up', () => {
|
||||
console.log(`Zeroconf service advertised: ${service.name} on port ${port}`);
|
||||
});
|
||||
|
||||
service.on('error', (err: Error) => {
|
||||
console.error('Zeroconf service error:', err);
|
||||
});
|
||||
}
|
||||
|
||||
public stopZeroconfService() {
|
||||
if (this.bonjourInstance) {
|
||||
this.bonjourInstance.destroy();
|
||||
this.bonjourInstance = null;
|
||||
console.log("Zeroconf service stopped");
|
||||
}
|
||||
}
|
||||
|
||||
private tryRespawnPlayerProcess(): Promise<Socket> {
|
||||
const socketFilename = Math.random().toString(36).substring(2, 10);
|
||||
const socketPath = `/tmp/mpv-${socketFilename}`;
|
||||
@@ -89,6 +126,11 @@ export class MediaPlayer {
|
||||
}, 500);
|
||||
});
|
||||
|
||||
this.playerProcess.on("error", (error) => {
|
||||
console.error("Player process error:", error);
|
||||
console.log("Continuing without mpv player...");
|
||||
});
|
||||
|
||||
return socketPromise;
|
||||
}
|
||||
|
||||
|
||||
@@ -295,12 +295,18 @@ app.get("*", (req, res) => {
|
||||
const port = process.env.PORT || 3000;
|
||||
const server = app.listen(port, () => {
|
||||
console.log(`Server is running on port ${port}`);
|
||||
|
||||
// Start zeroconf service advertisement
|
||||
mediaPlayer.startZeroconfService(Number(port));
|
||||
});
|
||||
|
||||
// Add graceful shutdown handling
|
||||
const shutdown = async () => {
|
||||
console.log('Received shutdown signal. Closing server...');
|
||||
|
||||
// Stop zeroconf service
|
||||
mediaPlayer.stopZeroconfService();
|
||||
|
||||
server.close(() => {
|
||||
console.log('Server closed');
|
||||
process.exit(0);
|
||||
|
||||
44
package-lock.json
generated
44
package-lock.json
generated
@@ -21,6 +21,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/node-fetch": "^2.6.12",
|
||||
"bonjour-service": "^1.3.0",
|
||||
"classnames": "^2.5.1",
|
||||
"express": "^4.21.2",
|
||||
"express-ws": "^5.0.2",
|
||||
@@ -1017,6 +1018,11 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@leichtgewicht/ip-codec": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
|
||||
"integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@@ -2153,6 +2159,15 @@
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bonjour-service": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz",
|
||||
"integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"multicast-dns": "^7.2.5"
|
||||
}
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
@@ -2636,6 +2651,17 @@
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/dns-packet": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
|
||||
"integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
|
||||
"dependencies": {
|
||||
"@leichtgewicht/ip-codec": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
@@ -3160,7 +3186,6 @@
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
@@ -4197,6 +4222,18 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/multicast-dns": {
|
||||
"version": "7.2.5",
|
||||
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
|
||||
"integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
|
||||
"dependencies": {
|
||||
"dns-packet": "^5.2.2",
|
||||
"thunky": "^1.0.2"
|
||||
},
|
||||
"bin": {
|
||||
"multicast-dns": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.8",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||
@@ -5145,6 +5182,11 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/thunky": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
|
||||
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
|
||||
Reference in New Issue
Block a user