forked from miao-moe/QZMusic_PC
feat: 重构页面
This commit is contained in:
@@ -1,13 +1,7 @@
|
||||
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);
|
||||
import { app, ipcMain, BrowserWindow, Menu } from "electron";
|
||||
import { ipcMain, BrowserWindow, app, Menu } from "electron";
|
||||
import { createRequire } from "node:module";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import path from "node:path";
|
||||
import os from "node:os";
|
||||
import net from "node:net";
|
||||
import { spawn } from "node:child_process";
|
||||
createRequire(import.meta.url);
|
||||
const __dirname$1 = path.dirname(fileURLToPath(import.meta.url));
|
||||
process.env.APP_ROOT = path.join(__dirname$1, "..");
|
||||
@@ -16,131 +10,6 @@ const MAIN_DIST = path.join(process.env.APP_ROOT, "dist-electron");
|
||||
const RENDERER_DIST = path.join(process.env.APP_ROOT, "dist");
|
||||
process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL ? path.join(process.env.APP_ROOT, "public") : RENDERER_DIST;
|
||||
let win;
|
||||
class MpvController {
|
||||
// 用于处理 JSON 数据粘包
|
||||
constructor() {
|
||||
__publicField(this, "process", null);
|
||||
__publicField(this, "socket", null);
|
||||
__publicField(this, "socketPath");
|
||||
__publicField(this, "buffer", "");
|
||||
const socketName = `mpv-socket-${Date.now()}`;
|
||||
this.socketPath = process.platform === "win32" ? `\\\\.\\pipe\\${socketName}` : path.join(os.tmpdir(), socketName);
|
||||
}
|
||||
start(binaryPath) {
|
||||
console.log(`[MPV] Starting from: ${binaryPath}`);
|
||||
console.log(`[MPV] IPC Socket: ${this.socketPath}`);
|
||||
this.process = spawn(binaryPath, [
|
||||
"--idle",
|
||||
// 空闲时不退出
|
||||
"--no-video",
|
||||
// 纯音频模式
|
||||
"--keep-open=yes",
|
||||
// 播放结束不退出
|
||||
`--input-ipc-server=${this.socketPath}`
|
||||
// 指定 IPC 监听地址
|
||||
]);
|
||||
this.process.on("error", (err) => {
|
||||
console.error("[MPV] Process Error:", err);
|
||||
});
|
||||
this.process.on("exit", (code) => {
|
||||
var _a;
|
||||
console.log(`[MPV] Process exited with code ${code}`);
|
||||
(_a = this.socket) == null ? void 0 : _a.destroy();
|
||||
});
|
||||
this.connectSocket();
|
||||
}
|
||||
connectSocket(retries = 10) {
|
||||
setTimeout(() => {
|
||||
const socket = net.createConnection(this.socketPath);
|
||||
socket.on("connect", () => {
|
||||
console.log("[MPV] IPC Connected!");
|
||||
this.socket = socket;
|
||||
this.setupObservers();
|
||||
});
|
||||
socket.on("data", (data) => this.handleData(data));
|
||||
socket.on("error", (err) => {
|
||||
if (retries > 0) {
|
||||
this.connectSocket(retries - 1);
|
||||
} else {
|
||||
console.error("[MPV] Failed to connect to IPC socket:", err);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
// 处理接收到的数据 (解决 TCP 数据包粘连或截断问题)
|
||||
handleData(data) {
|
||||
this.buffer += data.toString();
|
||||
const lines = this.buffer.split("\n");
|
||||
this.buffer = lines.pop() || "";
|
||||
lines.forEach((line) => {
|
||||
if (!line.trim()) return;
|
||||
try {
|
||||
const message = JSON.parse(line);
|
||||
console.log(message);
|
||||
this.handleMessage(message);
|
||||
} catch (e) {
|
||||
console.error("[MPV] JSON Parse Error:", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
// 处理解析后的 JSON 消息
|
||||
handleMessage(msg) {
|
||||
if (!win) return;
|
||||
if (msg.event === "property-change") {
|
||||
switch (msg.name) {
|
||||
case "time-pos":
|
||||
win.webContents.send("mpv-time-update", msg.data);
|
||||
break;
|
||||
case "duration":
|
||||
win.webContents.send("mpv-duration", msg.data);
|
||||
break;
|
||||
case "pause":
|
||||
win.webContents.send("mpv-play-state", !msg.data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (msg.event === "end-file") {
|
||||
win.webContents.send("mpv-ended");
|
||||
win.webContents.send("mpv-play-state", false);
|
||||
}
|
||||
}
|
||||
// 初始化监听属性
|
||||
setupObservers() {
|
||||
this.send(["observe_property", 1, "time-pos"]);
|
||||
this.send(["observe_property", 2, "duration"]);
|
||||
this.send(["observe_property", 3, "pause"]);
|
||||
}
|
||||
// 发送命令给 MPV
|
||||
send(command) {
|
||||
if (!this.socket || this.socket.destroyed) return;
|
||||
const payload = JSON.stringify({ command });
|
||||
this.socket.write(payload + "\n");
|
||||
}
|
||||
// === 业务方法 ===
|
||||
load(url, autoPlay) {
|
||||
if (autoPlay) {
|
||||
this.send(["set_property", "pause", false]);
|
||||
this.send(["loadfile", url, "replace"]);
|
||||
} else {
|
||||
this.send(["set_property", "pause", true]);
|
||||
this.send(["loadfile", url, "replace"]);
|
||||
}
|
||||
}
|
||||
play() {
|
||||
this.send(["set_property", "pause", false]);
|
||||
}
|
||||
pause() {
|
||||
this.send(["set_property", "pause", true]);
|
||||
}
|
||||
seek(time) {
|
||||
this.send(["seek", time, "absolute"]);
|
||||
}
|
||||
setVolume(volume) {
|
||||
this.send(["set_property", "volume", volume]);
|
||||
}
|
||||
}
|
||||
const mpv = new MpvController();
|
||||
const mpvExecutablePath = app.isPackaged ? path.join(process.resourcesPath, "core", "mpv.exe") : path.join(process.env.APP_ROOT, "core", "mpv.exe");
|
||||
function createWindow() {
|
||||
win = new BrowserWindow({
|
||||
frame: false,
|
||||
@@ -163,6 +32,7 @@ function createWindow() {
|
||||
} else {
|
||||
win.loadFile(path.join(RENDERER_DIST, "index.html"));
|
||||
}
|
||||
registerZoomShortcuts(win);
|
||||
}
|
||||
ipcMain.on("window-minimize", (event) => {
|
||||
var _a;
|
||||
@@ -171,17 +41,32 @@ ipcMain.on("window-minimize", (event) => {
|
||||
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.on("mpv-load", (_, url, autoPlay = true) => mpv.load(url, autoPlay));
|
||||
ipcMain.on("mpv-play", () => mpv.play());
|
||||
ipcMain.on("mpv-pause", () => mpv.pause());
|
||||
ipcMain.on("mpv-seek", (_, time) => mpv.seek(time));
|
||||
ipcMain.on("mpv-volume", (_, volume) => mpv.setVolume(volume));
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") {
|
||||
app.quit();
|
||||
win = null;
|
||||
}
|
||||
});
|
||||
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();
|
||||
@@ -189,7 +74,6 @@ app.on("activate", () => {
|
||||
});
|
||||
app.whenReady().then(() => {
|
||||
Menu.setApplicationMenu(null);
|
||||
mpv.start(mpvExecutablePath);
|
||||
createWindow();
|
||||
});
|
||||
export {
|
||||
|
||||
Reference in New Issue
Block a user