2026-04-26 10:08:15 -07:00
|
|
|
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
|
2026-04-26 09:46:08 -07:00
|
|
|
const path = require('path');
|
|
|
|
|
const { startServer } = require('./server');
|
|
|
|
|
const { createTray } = require('./tray');
|
|
|
|
|
|
|
|
|
|
const PORT = 9095;
|
2026-04-26 10:40:03 -07:00
|
|
|
const OVERLAY_DIR = app.isPackaged
|
|
|
|
|
? path.join(process.resourcesPath, 'overlay')
|
|
|
|
|
: path.join(__dirname, '..', 'overlay');
|
2026-04-26 09:46:08 -07:00
|
|
|
const YT_MUSIC_URL = 'https://music.youtube.com';
|
|
|
|
|
|
|
|
|
|
let serverHandle = null;
|
|
|
|
|
let mainWindow = null;
|
|
|
|
|
let tray = null;
|
2026-04-26 09:49:20 -07:00
|
|
|
let isQuitting = false;
|
2026-04-26 09:46:08 -07:00
|
|
|
|
|
|
|
|
async function createWindow() {
|
|
|
|
|
mainWindow = new BrowserWindow({
|
|
|
|
|
width: 1280,
|
|
|
|
|
height: 800,
|
|
|
|
|
title: "What's That Music",
|
|
|
|
|
autoHideMenuBar: true,
|
|
|
|
|
webPreferences: {
|
|
|
|
|
preload: path.join(__dirname, 'yt-scraper.js'),
|
|
|
|
|
contextIsolation: true,
|
|
|
|
|
nodeIntegration: false,
|
|
|
|
|
sandbox: false,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-26 10:34:42 -07:00
|
|
|
mainWindow.on('close', (e) => {
|
|
|
|
|
// Bypass beforeunload (YT Music sets one while audio is playing) so the
|
|
|
|
|
// window actually closes when the user clicks X or chooses Quit.
|
|
|
|
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
mainWindow.destroy();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-26 09:46:08 -07:00
|
|
|
mainWindow.on('closed', () => {
|
|
|
|
|
mainWindow = null;
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-26 09:49:20 -07:00
|
|
|
try {
|
|
|
|
|
await mainWindow.loadURL(YT_MUSIC_URL);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error('[wtm] Failed to load YT Music:', err.message);
|
|
|
|
|
}
|
2026-04-26 09:46:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app.whenReady().then(async () => {
|
|
|
|
|
serverHandle = await startServer({ port: PORT, overlayDir: OVERLAY_DIR });
|
|
|
|
|
|
2026-04-26 10:08:15 -07:00
|
|
|
if (serverHandle.port !== PORT) {
|
|
|
|
|
const actual = serverHandle.port;
|
|
|
|
|
await dialog.showMessageBox({
|
|
|
|
|
type: 'info',
|
|
|
|
|
title: 'Port in use',
|
|
|
|
|
message: `Port ${PORT} was in use; using ${actual} instead.`,
|
|
|
|
|
detail: `If you have an OBS browser source pointed at this app, update it to http://localhost:${actual}/`,
|
|
|
|
|
buttons: ['OK'],
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-26 09:46:08 -07:00
|
|
|
ipcMain.on('wtm:state', (_event, payload) => {
|
|
|
|
|
const next = serverHandle.setState(payload || { isPlaying: false });
|
|
|
|
|
if (tray) tray.update({ title: next.title, artist: next.artist });
|
|
|
|
|
});
|
|
|
|
|
|
2026-10-04 11:37:38 -07:00
|
|
|
// Create the tray before the window: the scraper can report a track as soon as
|
|
|
|
|
// the page loads, and state arriving while `tray` is null would be dropped.
|
2026-04-26 09:46:08 -07:00
|
|
|
tray = createTray({
|
2026-04-26 10:08:15 -07:00
|
|
|
port: serverHandle.port,
|
2026-04-26 09:46:08 -07:00
|
|
|
onShow: () => {
|
|
|
|
|
if (!mainWindow) return;
|
|
|
|
|
if (mainWindow.isMinimized()) mainWindow.restore();
|
|
|
|
|
mainWindow.focus();
|
|
|
|
|
},
|
|
|
|
|
onQuit: () => app.quit(),
|
|
|
|
|
});
|
2026-10-04 11:37:38 -07:00
|
|
|
|
|
|
|
|
await createWindow();
|
|
|
|
|
|
2026-04-26 10:12:14 -07:00
|
|
|
}).catch((err) => {
|
|
|
|
|
dialog.showErrorBox('Failed to start', err && err.message ? err.message : String(err));
|
|
|
|
|
app.exit(1);
|
2026-04-26 09:46:08 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.on('window-all-closed', () => {
|
|
|
|
|
app.quit();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.on('before-quit', async (e) => {
|
2026-04-26 09:49:20 -07:00
|
|
|
if (isQuitting) return;
|
|
|
|
|
if (!serverHandle) return;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
isQuitting = true;
|
|
|
|
|
if (tray) { tray.destroy(); tray = null; }
|
|
|
|
|
try { await serverHandle.stop(); } catch (_) {}
|
|
|
|
|
serverHandle = null;
|
|
|
|
|
app.exit(0);
|
2026-04-26 09:46:08 -07:00
|
|
|
});
|