Files
QZMusic_PC-pre/dist-electron/main.js

249 lines
7.9 KiB
JavaScript
Raw Normal View History

var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
2026-02-02 13:54:31 +08:00
import { ipcMain, BrowserWindow, app, Menu } from "electron";
import { createRequire } from "node:module";
import { fileURLToPath } from "node:url";
import path$1 from "node:path";
import { spawn } from "child_process";
import { Socket } from "net";
import { EventEmitter } from "events";
import path from "path";
class MpvController extends EventEmitter {
constructor(ipcPath) {
super();
__publicField(this, "process", null);
__publicField(this, "socket", null);
__publicField(this, "ipcPath");
__publicField(this, "messageBuffer", "");
this.ipcPath = ipcPath || this.getIpcPath();
}
getIpcPath() {
if (process.platform === "win32") {
return "\\\\.\\pipe\\qzmusic_mpv_socket";
}
return "/tmp/qzmusic_mpv_socket";
}
getMpvPath() {
const appRoot = process.env.APP_ROOT || process.cwd();
if (process.platform === "win32") {
return path.join(appRoot, "core", "mpv.exe");
}
return "mpv";
}
start() {
const mpvPath = this.getMpvPath();
console.log("Starting MPV from:", mpvPath);
this.process = spawn(mpvPath, [
"--idle",
"--force-window=no",
"--no-media-controls",
`--input-ipc-server=${this.ipcPath}`,
"--no-terminal"
]);
this.process.on("error", (err) => {
console.error("Failed to start MPV:", err);
this.emit("error", err);
});
this.process.on("exit", (code, signal) => {
var _a;
console.log(`MPV exited with code ${code} and signal ${signal}`);
this.emit("exit", { code, signal });
(_a = this.socket) == null ? void 0 : _a.destroy();
});
this.tryConnect();
}
tryConnect(retries = 10) {
if (retries <= 0) {
console.error("Could not connect to MPV socket after multiple attempts.");
return;
}
setTimeout(() => {
this.socket = new Socket();
this.socket.on("connect", () => {
console.log("Connected to MPV IPC socket");
this.emit("ready");
this.send(["observe_property", 1, "pause"]);
this.send(["observe_property", 2, "time-pos"]);
this.send(["observe_property", 3, "duration"]);
this.send(["observe_property", 4, "idle-active"]);
this.send(["observe_property", 5, "eof-reached"]);
});
this.socket.on("data", (data) => {
this.handleData(data);
});
this.socket.on("error", (err) => {
var _a;
(_a = this.socket) == null ? void 0 : _a.destroy();
this.tryConnect(retries - 1);
});
this.socket.connect(this.ipcPath);
}, 500);
}
handleData(data) {
const raw = data.toString();
this.messageBuffer += raw;
const messages = this.messageBuffer.split("\n");
this.messageBuffer = messages.pop() || "";
for (const msg of messages) {
if (!msg.trim()) continue;
console.log("[IPC]", msg);
try {
const json = JSON.parse(msg);
this.emit("message", json);
if (json.event) {
this.emit("event", json);
}
} catch (e) {
console.error("Failed to parse MPV message:", msg);
}
}
}
async send(command) {
if (!this.socket || this.socket.destroyed) {
console.warn("MPV socket not connected");
return;
}
const payload = JSON.stringify({ command });
console.log("[MPV TX]", payload);
this.socket.write(payload + "\n");
}
// Convenience methods
async load(url) {
return this.send(["loadfile", url]);
}
async play() {
return this.send(["set_property", "pause", false]);
}
async pause() {
return this.send(["set_property", "pause", true]);
}
async togglePause() {
return this.send(["cycle", "pause"]);
}
async stop() {
return this.send(["stop"]);
}
async setVolume(vol) {
return this.send(["set_property", "volume", vol]);
}
async seek(seconds) {
return this.send(["seek", seconds, "absolute"]);
}
destroy() {
if (this.process) {
console.log("Killing MPV process...");
this.process.kill();
this.process = null;
}
if (this.socket) {
this.socket.destroy();
this.socket = null;
}
}
}
createRequire(import.meta.url);
const __dirname$1 = path$1.dirname(fileURLToPath(import.meta.url));
process.env.APP_ROOT = path$1.join(__dirname$1, "..");
const VITE_DEV_SERVER_URL = process.env["VITE_DEV_SERVER_URL"];
const MAIN_DIST = path$1.join(process.env.APP_ROOT, "dist-electron");
const RENDERER_DIST = path$1.join(process.env.APP_ROOT, "dist");
process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL ? path$1.join(process.env.APP_ROOT, "public") : RENDERER_DIST;
let win;
let mpv;
function createWindow() {
win = new BrowserWindow({
frame: false,
minWidth: 950,
minHeight: 800,
width: 1e3,
height: 800,
icon: path$1.join(process.env.VITE_PUBLIC, "electron-vite.svg"),
webPreferences: {
preload: path$1.join(__dirname$1, "preload.mjs")
// nodeIntegration: false,
// contextIsolation: true,
}
});
win.webContents.on("did-finish-load", () => {
win == null ? void 0 : win.webContents.send("main-process-message", (/* @__PURE__ */ new Date()).toLocaleString());
});
if (VITE_DEV_SERVER_URL) {
win.loadURL(VITE_DEV_SERVER_URL);
} else {
win.loadFile(path$1.join(RENDERER_DIST, "index.html"));
}
2026-02-02 13:54:31 +08:00
registerZoomShortcuts(win);
}
ipcMain.on("window-minimize", (event) => {
var _a;
return (_a = BrowserWindow.fromWebContents(event.sender)) == null ? void 0 : _a.minimize();
});
ipcMain.on("window-maximize", () => (win == null ? void 0 : win.isMaximized()) ? win.unmaximize() : win == null ? void 0 : win.maximize());
ipcMain.on("window-close", () => win == null ? void 0 : win.close());
ipcMain.handle("window-is-maximized", () => (win == null ? void 0 : win.isMaximized()) || false);
ipcMain.handle("mpv-command", async (_, command) => {
if (mpv) {
mpv.send(command);
}
});
ipcMain.handle("mpv-load", (_, url) => mpv == null ? void 0 : mpv.load(url));
ipcMain.handle("mpv-play", () => mpv == null ? void 0 : mpv.play());
ipcMain.handle("mpv-pause", () => mpv == null ? void 0 : mpv.pause());
ipcMain.handle("mpv-toggle-pause", () => mpv == null ? void 0 : mpv.togglePause());
ipcMain.handle("mpv-stop", () => mpv == null ? void 0 : mpv.stop());
ipcMain.handle("mpv-set-volume", (e, vol) => mpv == null ? void 0 : mpv.setVolume(vol));
ipcMain.handle("mpv-seek", (_, time) => mpv == null ? void 0 : mpv.seek(time));
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
win = null;
}
});
app.on("will-quit", () => {
if (mpv) {
mpv.destroy();
}
});
2026-02-02 13:54:31 +08:00
function registerZoomShortcuts(win2) {
win2.webContents.on("before-input-event", (event, input) => {
if (input.control || input.meta) {
if (input.key.toLowerCase() === "=" || input.key === "+") {
let currentZoom = win2.webContents.getZoomFactor();
win2.webContents.setZoomFactor(currentZoom + 0.1);
event.preventDefault();
} else if (input.key === "-" || input.key === "_") {
let currentZoom = win2.webContents.getZoomFactor();
if (currentZoom > 0.5) {
win2.webContents.setZoomFactor(currentZoom - 0.1);
}
event.preventDefault();
} else if (input.key === "0") {
win2.webContents.setZoomFactor(1);
event.preventDefault();
}
}
});
}
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
app.whenReady().then(() => {
Menu.setApplicationMenu(null);
createWindow();
mpv = new MpvController();
mpv.start();
mpv.on("event", (data) => {
if (win && !win.isDestroyed()) {
win.webContents.send("mpv-event", data);
}
});
});
export {
MAIN_DIST,
RENDERER_DIST,
VITE_DEV_SERVER_URL
};