Add logger functions and move player functions to feature

This commit is contained in:
jeffvli 2024-02-12 13:58:50 -08:00
parent adf5fc348a
commit 69f82a9427
3 changed files with 197 additions and 143 deletions

View file

@ -1,7 +1,11 @@
import console from 'console'; import console from 'console';
import { ipcMain } from 'electron'; import { app, ipcMain } from 'electron';
import { getMpvInstance } from '../../../main'; import uniq from 'lodash/uniq';
import MpvAPI from 'node-mpv';
import { getMainWindow, sendToastToRenderer } from '../../../main';
import { PlayerData } from '/@/renderer/store'; import { PlayerData } from '/@/renderer/store';
import { isWindows } from '../../../utils';
import { store } from '../settings';
declare module 'node-mpv'; declare module 'node-mpv';
@ -13,6 +17,150 @@ declare module 'node-mpv';
// }); // });
// } // }
let mpvInstance: MpvAPI | null = null;
const MPV_BINARY_PATH = store.get('mpv_path') as string | undefined;
const isDevelopment = process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true';
const prefetchPlaylistParams = [
'--prefetch-playlist=no',
'--prefetch-playlist=yes',
'--prefetch-playlist',
];
const DEFAULT_MPV_PARAMETERS = (extraParameters?: string[]) => {
const parameters = ['--idle=yes', '--no-config', '--load-scripts=no'];
if (!extraParameters?.some((param) => prefetchPlaylistParams.includes(param))) {
parameters.push('--prefetch-playlist=yes');
}
return parameters;
};
const createMpv = async (data: {
extraParameters?: string[];
properties?: Record<string, any>;
}): Promise<MpvAPI> => {
const { extraParameters, properties } = data;
const params = uniq([...DEFAULT_MPV_PARAMETERS(extraParameters), ...(extraParameters || [])]);
console.log('Setting mpv params: ', params);
const extra = isDevelopment ? '-dev' : '';
const mpv = new MpvAPI(
{
audio_only: true,
auto_restart: false,
binary: MPV_BINARY_PATH || undefined,
socket: isWindows() ? `\\\\.\\pipe\\mpvserver${extra}` : `/tmp/node-mpv${extra}.sock`,
time_update: 1,
},
params,
);
try {
await mpv.start();
} catch (error: { message: string; stack: any } | any) {
console.log('MPV failed to start', error);
} finally {
console.log('Setting MPV properties: ', properties);
await mpv.setMultipleProperties(properties || {});
}
mpv.on('status', (status, ...rest) => {
console.log('MPV Event: status', status.property, status.value, rest);
if (status.property === 'playlist-pos') {
if (status.value === -1) {
mpv?.stop();
}
if (status.value !== 0) {
getMainWindow()?.webContents.send('renderer-player-auto-next');
}
}
});
// Automatically updates the play button when the player is playing
mpv.on('resumed', () => {
console.log('MPV Event: resumed');
getMainWindow()?.webContents.send('renderer-player-play');
});
// Automatically updates the play button when the player is stopped
mpv.on('stopped', () => {
console.log('MPV Event: stopped');
getMainWindow()?.webContents.send('renderer-player-stop');
});
// Automatically updates the play button when the player is paused
mpv.on('paused', () => {
console.log('MPV Event: paused');
getMainWindow()?.webContents.send('renderer-player-pause');
});
// Event output every interval set by time_update, used to update the current time
mpv.on('timeposition', (time: number) => {
getMainWindow()?.webContents.send('renderer-player-current-time', time);
});
mpv.on('quit', () => {
console.log('MPV Event: quit');
});
return mpv;
};
export const getMpvInstance = () => {
return mpvInstance;
};
ipcMain.on('player-set-properties', async (_event, data: Record<string, any>) => {
if (data.length === 0) {
return;
}
if (data.length === 1) {
getMpvInstance()?.setProperty(Object.keys(data)[0], Object.values(data)[0]);
} else {
getMpvInstance()?.setMultipleProperties(data);
}
});
ipcMain.on(
'player-restart',
async (_event, data: { extraParameters?: string[]; properties?: Record<string, any> }) => {
console.log('Initializing MPV with data: ', data);
mpvInstance?.quit();
try {
mpvInstance = await createMpv(data);
} catch (err) {
console.log('init error', err);
sendToastToRenderer({ message: 'Initialization error', type: 'error' });
}
},
);
ipcMain.handle(
'player-initialize',
async (_event, data: { extraParameters?: string[]; properties?: Record<string, any> }) => {
console.log('Initializing MPV with data: ', data);
try {
mpvInstance = await createMpv(data);
} catch (err) {
console.log('init error', err);
sendToastToRenderer({ message: 'Initialization error', type: 'error' });
}
},
);
ipcMain.on('player-quit', async () => {
mpvInstance?.stop();
mpvInstance?.quit();
mpvInstance = null;
});
ipcMain.handle('player-is-running', async () => { ipcMain.handle('player-is-running', async () => {
return getMpvInstance()?.isRunning(); return getMpvInstance()?.isRunning();
}); });
@ -203,3 +351,12 @@ ipcMain.on('player-mute', async (_event, mute: boolean) => {
ipcMain.handle('player-get-time', async (): Promise<number | undefined> => { ipcMain.handle('player-get-time', async (): Promise<number | undefined> => {
return getMpvInstance()?.getTimePosition(); return getMpvInstance()?.getTimePosition();
}); });
app.on('before-quit', () => {
getMpvInstance()?.stop();
getMpvInstance()?.quit();
});
app.on('window-all-closed', () => {
getMpvInstance()?.quit();
});

View file

@ -26,14 +26,19 @@ import {
net, net,
} from 'electron'; } from 'electron';
import electronLocalShortcut from 'electron-localshortcut'; import electronLocalShortcut from 'electron-localshortcut';
import log from 'electron-log'; import log from 'electron-log/main';
import { autoUpdater } from 'electron-updater'; import { autoUpdater } from 'electron-updater';
import uniq from 'lodash/uniq';
import MpvAPI from 'node-mpv';
import { disableMediaKeys, enableMediaKeys } from './features/core/player/media-keys'; import { disableMediaKeys, enableMediaKeys } from './features/core/player/media-keys';
import { store } from './features/core/settings/index'; import { store } from './features/core/settings/index';
import MenuBuilder from './menu'; import MenuBuilder from './menu';
import { hotkeyToElectronAccelerator, isLinux, isMacOS, isWindows, resolveHtmlPath } from './utils'; import {
hotkeyToElectronAccelerator,
isLinux,
isMacOS,
isWindows,
resolveHtmlPath,
createLog,
} from './utils';
import './features'; import './features';
import type { TitleTheme } from '/@/renderer/types'; import type { TitleTheme } from '/@/renderer/types';
@ -433,138 +438,6 @@ const createWindow = async () => {
app.commandLine.appendSwitch('disable-features', 'HardwareMediaKeyHandling,MediaSessionService'); app.commandLine.appendSwitch('disable-features', 'HardwareMediaKeyHandling,MediaSessionService');
const MPV_BINARY_PATH = store.get('mpv_path') as string | undefined;
const prefetchPlaylistParams = [
'--prefetch-playlist=no',
'--prefetch-playlist=yes',
'--prefetch-playlist',
];
const DEFAULT_MPV_PARAMETERS = (extraParameters?: string[]) => {
const parameters = ['--idle=yes', '--no-config', '--load-scripts=no'];
if (!extraParameters?.some((param) => prefetchPlaylistParams.includes(param))) {
parameters.push('--prefetch-playlist=yes');
}
return parameters;
};
let mpvInstance: MpvAPI | null = null;
const createMpv = async (data: {
extraParameters?: string[];
properties?: Record<string, any>;
}): Promise<MpvAPI> => {
const { extraParameters, properties } = data;
const params = uniq([...DEFAULT_MPV_PARAMETERS(extraParameters), ...(extraParameters || [])]);
console.log('Setting mpv params: ', params);
const extra = isDevelopment ? '-dev' : '';
const mpv = new MpvAPI(
{
audio_only: true,
auto_restart: false,
binary: MPV_BINARY_PATH || '',
socket: isWindows() ? `\\\\.\\pipe\\mpvserver${extra}` : `/tmp/node-mpv${extra}.sock`,
time_update: 1,
},
params,
);
try {
await mpv.start();
} catch (error) {
console.log('MPV failed to start', error);
} finally {
console.log('Setting MPV properties: ', properties);
await mpv.setMultipleProperties(properties || {});
}
mpv.on('status', (status, ...rest) => {
console.log('MPV Event: status', status.property, status.value, rest);
if (status.property === 'playlist-pos') {
if (status.value === -1) {
mpv?.stop();
}
if (status.value !== 0) {
getMainWindow()?.webContents.send('renderer-player-auto-next');
}
}
});
// Automatically updates the play button when the player is playing
mpv.on('resumed', () => {
console.log('MPV Event: resumed');
getMainWindow()?.webContents.send('renderer-player-play');
});
// Automatically updates the play button when the player is stopped
mpv.on('stopped', () => {
console.log('MPV Event: stopped');
getMainWindow()?.webContents.send('renderer-player-stop');
});
// Automatically updates the play button when the player is paused
mpv.on('paused', () => {
console.log('MPV Event: paused');
getMainWindow()?.webContents.send('renderer-player-pause');
});
// Event output every interval set by time_update, used to update the current time
mpv.on('timeposition', (time: number) => {
getMainWindow()?.webContents.send('renderer-player-current-time', time);
});
mpv.on('quit', () => {
console.log('MPV Event: quit');
});
return mpv;
};
export const getMpvInstance = () => {
return mpvInstance;
};
ipcMain.on('player-set-properties', async (_event, data: Record<string, any>) => {
if (data.length === 0) {
return;
}
if (data.length === 1) {
getMpvInstance()?.setProperty(Object.keys(data)[0], Object.values(data)[0]);
} else {
getMpvInstance()?.setMultipleProperties(data);
}
});
ipcMain.on(
'player-restart',
async (_event, data: { extraParameters?: string[]; properties?: Record<string, any> }) => {
mpvInstance?.quit();
mpvInstance = await createMpv(data);
},
);
ipcMain.handle(
'player-initialize',
async (_event, data: { extraParameters?: string[]; properties?: Record<string, any> }) => {
console.log('Initializing MPV with data: ', data);
mpvInstance = await createMpv(data);
},
);
ipcMain.on('player-quit', async () => {
mpvInstance?.stop();
mpvInstance?.quit();
mpvInstance = null;
});
// Must duplicate with the one in renderer process settings.store.ts // Must duplicate with the one in renderer process settings.store.ts
enum BindingActions { enum BindingActions {
GLOBAL_SEARCH = 'globalSearch', GLOBAL_SEARCH = 'globalSearch',
@ -647,14 +520,21 @@ ipcMain.on(
}, },
); );
app.on('before-quit', () => { ipcMain.on(
getMpvInstance()?.stop(); 'logger',
getMpvInstance()?.quit(); (
}); _event,
data: {
message: string;
type: 'debug' | 'verbose' | 'success' | 'error' | 'warning' | 'info';
},
) => {
createLog(data);
},
);
app.on('window-all-closed', () => { app.on('window-all-closed', () => {
globalShortcut.unregisterAll(); globalShortcut.unregisterAll();
getMpvInstance()?.quit();
// Respect the OSX convention of having the application in memory even // Respect the OSX convention of having the application in memory even
// after all windows have been closed // after all windows have been closed
if (isMacOS()) { if (isMacOS()) {

View file

@ -2,6 +2,7 @@
import path from 'path'; import path from 'path';
import process from 'process'; import process from 'process';
import { URL } from 'url'; import { URL } from 'url';
import log from 'electron-log/main';
export let resolveHtmlPath: (htmlFileName: string) => string; export let resolveHtmlPath: (htmlFileName: string) => string;
@ -50,3 +51,19 @@ export const hotkeyToElectronAccelerator = (hotkey: string) => {
return accelerator; return accelerator;
}; };
const logInstance = {
debug: log.debug,
error: log.error,
info: log.info,
success: log.info,
verbose: log.verbose,
warning: log.warn,
};
export const createLog = (data: {
message: string;
type: 'debug' | 'verbose' | 'success' | 'error' | 'warning' | 'info';
}) => {
logInstance[data.type](data.message);
};