From 1dec5a394589153bacb6971aeb990e0fca8b4644 Mon Sep 17 00:00:00 2001 From: 1600822305 <1600822305@qq.com> Date: Thu, 10 Apr 2025 16:01:28 +0800 Subject: [PATCH] ipc --- packages/shared/IpcChannel.ts | 6 +- src/main/ipc.ts | 106 +++++++++++++++- src/main/services/ASRServerIPC.ts | 114 ------------------ src/renderer/src/services/ASRServerService.ts | 5 +- 4 files changed, 105 insertions(+), 126 deletions(-) delete mode 100644 src/main/services/ASRServerIPC.ts diff --git a/packages/shared/IpcChannel.ts b/packages/shared/IpcChannel.ts index 0fb9b71896..d07a0a5200 100644 --- a/packages/shared/IpcChannel.ts +++ b/packages/shared/IpcChannel.ts @@ -146,9 +146,5 @@ export enum IpcChannel { MiniWindowReload = 'miniwindow-reload', ReduxStateChange = 'redux-state-change', - ReduxStoreReady = 'redux-store-ready', - - // ASR Server - ASR_StartServer = 'start-asr-server', - ASR_StopServer = 'stop-asr-server' + ReduxStoreReady = 'redux-store-ready' } diff --git a/src/main/ipc.ts b/src/main/ipc.ts index e0b5a0f733..47c13b0ef7 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -1,4 +1,6 @@ import fs from 'node:fs' +import { spawn, ChildProcess } from 'node:child_process' +import path from 'node:path' import { isMac, isWin } from '@main/constant' import { getBinaryPath, isBinaryExists, runInstallScript } from '@main/utils/process' @@ -26,11 +28,11 @@ import { TrayService } from './services/TrayService' import { windowService } from './services/WindowService' import { getResourcePath } from './utils' import { decrypt, encrypt } from './utils/aes' -import { registerASRServerIPC } from './services/ASRServerIPC' import { getConfigDir, getFilesDir } from './utils/file' import { compress, decompress } from './utils/zip' - +// 存储ASR服务器进程 +let asrServerProcess: ChildProcess | null = null const fileManager = new FileStorage() const backupManager = new BackupManager() @@ -295,6 +297,102 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { NutstoreService.getDirectoryContents(token, path) ) - // 注册ASR服务器相关的IPC处理程序 - registerASRServerIPC(ipcMain, app) + // 启动ASR服务器 + ipcMain.handle('start-asr-server', async () => { + try { + if (asrServerProcess) { + return { success: true, pid: asrServerProcess.pid } + } + + // 获取服务器文件路径 + console.log('App path:', app.getAppPath()) + // 在开发环境和生产环境中使用不同的路径 + let serverPath = '' + let isExeFile = false + + // 首先检查是否有打包后的exe文件 + const exePath = path.join(app.getAppPath(), 'resources', 'cherry-asr-server.exe') + if (fs.existsSync(exePath)) { + serverPath = exePath + isExeFile = true + console.log('检测到打包后的exe文件:', serverPath) + } else if (process.env.NODE_ENV === 'development') { + // 开发环境 + serverPath = path.join(app.getAppPath(), 'src', 'renderer', 'src', 'assets', 'asr-server', 'server.js') + } else { + // 生产环境 + serverPath = path.join(app.getAppPath(), 'public', 'asr-server', 'server.js') + } + console.log('ASR服务器路径:', serverPath) + + // 检查文件是否存在 + if (!fs.existsSync(serverPath)) { + return { success: false, error: '服务器文件不存在' } + } + + // 启动服务器进程 + if (isExeFile) { + // 如果是exe文件,直接启动 + asrServerProcess = spawn(serverPath, [], { + stdio: 'pipe', + detached: false + }) + } else { + // 如果是js文件,使用node启动 + asrServerProcess = spawn('node', [serverPath], { + stdio: 'pipe', + detached: false + }) + } + + // 处理服务器输出 + asrServerProcess.stdout?.on('data', (data) => { + console.log(`[ASR Server] ${data.toString()}`) + }) + + asrServerProcess.stderr?.on('data', (data) => { + console.error(`[ASR Server Error] ${data.toString()}`) + }) + + // 处理服务器退出 + asrServerProcess.on('close', (code) => { + console.log(`[ASR Server] 进程退出,退出码: ${code}`) + asrServerProcess = null + }) + + // 等待一段时间确保服务器启动 + await new Promise(resolve => setTimeout(resolve, 1000)) + + return { success: true, pid: asrServerProcess.pid } + } catch (error) { + console.error('启动ASR服务器失败:', error) + return { success: false, error: (error as Error).message } + } + }) + + // 停止ASR服务器 + ipcMain.handle('stop-asr-server', async (_event, pid) => { + try { + if (!asrServerProcess) { + return { success: true } + } + + // 检查PID是否匹配 + if (asrServerProcess.pid !== pid) { + console.warn(`请求停止的PID (${pid}) 与当前运行的ASR服务器PID (${asrServerProcess.pid}) 不匹配`) + } + + // 杀死进程 + asrServerProcess.kill() + + // 等待一段时间确保进程已经退出 + await new Promise(resolve => setTimeout(resolve, 500)) + + asrServerProcess = null + return { success: true } + } catch (error) { + console.error('停止ASR服务器失败:', error) + return { success: false, error: (error as Error).message } + } + }) } diff --git a/src/main/services/ASRServerIPC.ts b/src/main/services/ASRServerIPC.ts deleted file mode 100644 index b4c3b85f89..0000000000 --- a/src/main/services/ASRServerIPC.ts +++ /dev/null @@ -1,114 +0,0 @@ -import fs from 'node:fs' -import { spawn, ChildProcess } from 'node:child_process' -import path from 'node:path' -import { IpcMain, App } from 'electron' -import { IpcChannel } from '@shared/IpcChannel' - -// 存储ASR服务器进程 -let asrServerProcess: ChildProcess | null = null - -/** - * 注册ASR服务器相关的IPC处理程序 - * @param ipcMain IPC主进程对象 - * @param app Electron应用对象 - */ -export function registerASRServerIPC(ipcMain: IpcMain, app: App): void { - // 启动ASR服务器 - ipcMain.handle(IpcChannel.ASR_StartServer, async () => { - try { - if (asrServerProcess) { - return { success: true, pid: asrServerProcess.pid } - } - - // 获取服务器文件路径 - console.log('App path:', app.getAppPath()) - // 在开发环境和生产环境中使用不同的路径 - let serverPath = '' - let isExeFile = false - - // 首先检查是否有打包后的exe文件 - const exePath = path.join(app.getAppPath(), 'resources', 'cherry-asr-server.exe') - if (fs.existsSync(exePath)) { - serverPath = exePath - isExeFile = true - console.log('检测到打包后的exe文件:', serverPath) - } else if (process.env.NODE_ENV === 'development') { - // 开发环境 - serverPath = path.join(app.getAppPath(), 'src', 'renderer', 'src', 'assets', 'asr-server', 'server.js') - } else { - // 生产环境 - serverPath = path.join(app.getAppPath(), 'public', 'asr-server', 'server.js') - } - console.log('ASR服务器路径:', serverPath) - - // 检查文件是否存在 - if (!fs.existsSync(serverPath)) { - return { success: false, error: '服务器文件不存在' } - } - - // 启动服务器进程 - if (isExeFile) { - // 如果是exe文件,直接启动 - asrServerProcess = spawn(serverPath, [], { - stdio: 'pipe', - detached: false - }) - } else { - // 如果是js文件,使用node启动 - asrServerProcess = spawn('node', [serverPath], { - stdio: 'pipe', - detached: false - }) - } - - // 处理服务器输出 - asrServerProcess.stdout?.on('data', (data) => { - console.log(`[ASR Server] ${data.toString()}`) - }) - - asrServerProcess.stderr?.on('data', (data) => { - console.error(`[ASR Server Error] ${data.toString()}`) - }) - - // 处理服务器退出 - asrServerProcess.on('close', (code) => { - console.log(`[ASR Server] 进程退出,退出码: ${code}`) - asrServerProcess = null - }) - - // 等待一段时间确保服务器启动 - await new Promise(resolve => setTimeout(resolve, 1000)) - - return { success: true, pid: asrServerProcess.pid } - } catch (error) { - console.error('启动ASR服务器失败:', error) - return { success: false, error: (error as Error).message } - } - }) - - // 停止ASR服务器 - ipcMain.handle(IpcChannel.ASR_StopServer, async (_event, pid) => { - try { - if (!asrServerProcess) { - return { success: true } - } - - // 检查PID是否匹配 - if (asrServerProcess.pid !== pid) { - console.warn(`请求停止的PID (${pid}) 与当前运行的ASR服务器PID (${asrServerProcess.pid}) 不匹配`) - } - - // 杀死进程 - asrServerProcess.kill() - - // 等待一段时间确保进程已经退出 - await new Promise(resolve => setTimeout(resolve, 500)) - - asrServerProcess = null - return { success: true } - } catch (error) { - console.error('停止ASR服务器失败:', error) - return { success: false, error: (error as Error).message } - } - }) -} diff --git a/src/renderer/src/services/ASRServerService.ts b/src/renderer/src/services/ASRServerService.ts index 6cf0afab37..6c8d77757f 100644 --- a/src/renderer/src/services/ASRServerService.ts +++ b/src/renderer/src/services/ASRServerService.ts @@ -1,5 +1,4 @@ import i18n from '@renderer/i18n' -import { IpcChannel } from '@shared/IpcChannel' // 使用window.electron而不是直接导入electron模块 // 这样可以避免__dirname不可用的问题 @@ -24,7 +23,7 @@ class ASRServerService { window.message.loading({ content: i18n.t('settings.asr.server.starting'), key: 'asr-server' }) // 使用IPC调用主进程启动服务器 - const result = await window.electron.ipcRenderer.invoke(IpcChannel.ASR_StartServer) + const result = await window.electron.ipcRenderer.invoke('start-asr-server') if (result.success) { this.isServerRunning = true @@ -66,7 +65,7 @@ class ASRServerService { window.message.loading({ content: i18n.t('settings.asr.server.stopping'), key: 'asr-server' }) // 使用IPC调用主进程停止服务器 - const result = await window.electron.ipcRenderer.invoke(IpcChannel.ASR_StopServer, this.serverProcess) + const result = await window.electron.ipcRenderer.invoke('stop-asr-server', this.serverProcess) if (result.success) { this.isServerRunning = false