Adds support for zeroconf (Bonjour)

This commit is contained in:
2025-05-30 20:12:53 -07:00
parent 3552c9c476
commit 1bde92b974
4 changed files with 92 additions and 1 deletions

View File

@@ -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",

View File

@@ -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;
}

View File

@@ -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);