mirror of
https://github.com/mifi/lossless-cut.git
synced 2024-11-22 10:22:31 +01:00
Only allow a single running instance
Can be overridden by `--allow-multiple-instances` CLI argument closes #1265 closes #527
This commit is contained in:
parent
f3fd5df45b
commit
f09369ee17
@ -221,6 +221,10 @@ See [available settings](https://github.com/mifi/lossless-cut/blob/master/public
|
|||||||
LosslessCut --settings-json '{captureFormat:"jpeg", "keyframeCut":true}'
|
LosslessCut --settings-json '{captureFormat:"jpeg", "keyframeCut":true}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Multiple instances
|
||||||
|
|
||||||
|
By default, only a single running instance of LosslessCut is allowed. If you start a new LosslessCut instance from the command line, it will instead pass the list of files onto the already running instance. You can override this behavior by passing `--allow-multiple-instances` via the command line. Running multiple instances is experimental.
|
||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
See the [developer notes](developer-notes.md).
|
See the [developer notes](developer-notes.md).
|
||||||
|
@ -121,100 +121,123 @@ function updateMenu() {
|
|||||||
menu(app, mainWindow, newVersion);
|
menu(app, mainWindow, newVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openFilesEventually(paths) {
|
||||||
|
if (rendererReady) openFiles(paths);
|
||||||
|
else filesToOpen = paths;
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/electron/electron/issues/3657
|
// https://github.com/electron/electron/issues/3657
|
||||||
// https://github.com/mifi/lossless-cut/issues/357
|
// https://github.com/mifi/lossless-cut/issues/357
|
||||||
// https://github.com/mifi/lossless-cut/issues/639
|
// https://github.com/mifi/lossless-cut/issues/639
|
||||||
// https://github.com/mifi/lossless-cut/issues/591
|
// https://github.com/mifi/lossless-cut/issues/591
|
||||||
function parseCliArgs() {
|
function parseCliArgs(rawArgv = process.argv) {
|
||||||
const ignoreFirstArgs = isDev ? 2 : 1;
|
const ignoreFirstArgs = isDev ? 2 : 1;
|
||||||
// production: First arg is the LosslessCut executable
|
// production: First arg is the LosslessCut executable
|
||||||
// dev: First 2 args are electron and the electron.js
|
// dev: First 2 args are electron and the electron.js
|
||||||
const argsWithoutAppName = process.argv.length > ignoreFirstArgs ? process.argv.slice(ignoreFirstArgs) : [];
|
const argsWithoutAppName = rawArgv.length > ignoreFirstArgs ? rawArgv.slice(ignoreFirstArgs) : [];
|
||||||
|
|
||||||
return yargsParser(argsWithoutAppName);
|
return yargsParser(argsWithoutAppName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
const argv = parseCliArgs();
|
||||||
// initialization and is ready to create browser windows.
|
|
||||||
// Some APIs can only be used after this event occurs.
|
|
||||||
app.on('ready', async () => {
|
|
||||||
// https://github.com/electron/electron/issues/23757
|
|
||||||
// https://github.com/electron/electron/pull/28489
|
|
||||||
// TODO I think this can be removed when we are on electron 12 or 14
|
|
||||||
if (isDev) {
|
|
||||||
electron.protocol.registerFileProtocol('file', (request, callback) => {
|
|
||||||
const pathname = decodeURIComponent(request.url.replace('file:///', ''));
|
|
||||||
callback(pathname);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await configStore.init();
|
if (!argv.allowMultipleInstances && !app.requestSingleInstanceLock()) {
|
||||||
|
|
||||||
const argv = parseCliArgs();
|
|
||||||
logger.info('CLI arguments', argv);
|
|
||||||
// Only if no files to open already (open-file might have already added some files)
|
|
||||||
if (filesToOpen.length === 0) filesToOpen = argv._;
|
|
||||||
const { settingsJson } = argv;
|
|
||||||
|
|
||||||
if (settingsJson != null) {
|
|
||||||
logger.info('initializing settings', settingsJson);
|
|
||||||
Object.entries(JSON5.parse(settingsJson)).forEach(([key, value]) => {
|
|
||||||
configStore.set(key, value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDev) {
|
|
||||||
const { default: installExtension, REACT_DEVELOPER_TOOLS } = require('electron-devtools-installer'); // eslint-disable-line global-require,import/no-extraneous-dependencies
|
|
||||||
|
|
||||||
installExtension(REACT_DEVELOPER_TOOLS)
|
|
||||||
.then(name => logger.info('Added Extension', name))
|
|
||||||
.catch(err => logger.error('Failed to add extension', err));
|
|
||||||
}
|
|
||||||
|
|
||||||
createWindow();
|
|
||||||
updateMenu();
|
|
||||||
|
|
||||||
if (!process.windowsStore && !process.mas) {
|
|
||||||
newVersion = await checkNewVersion();
|
|
||||||
// newVersion = '1.2.3';
|
|
||||||
if (newVersion) updateMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Quit when all windows are closed.
|
|
||||||
app.on('window-all-closed', () => {
|
|
||||||
app.quit();
|
app.quit();
|
||||||
});
|
} else {
|
||||||
|
// On macOS, the system enforces single instance automatically when users try to open a second instance of your app in Finder, and the open-file and open-url events will be emitted for that.
|
||||||
|
// However when users start your app in command line, the system's single instance mechanism will be bypassed, and you have to use this method to ensure single instance.
|
||||||
|
// This can be tested with one terminal: npx electron .
|
||||||
|
// and another terminal: npx electron . path/to/file.mp4
|
||||||
|
app.on('second-instance', (event, commandLine) => {
|
||||||
|
// Someone tried to run a second instance, we should focus our window.
|
||||||
|
if (mainWindow) {
|
||||||
|
if (mainWindow.isMinimized()) mainWindow.restore();
|
||||||
|
mainWindow.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
const argv2 = parseCliArgs(commandLine);
|
||||||
|
if (argv2._) openFilesEventually(argv2._);
|
||||||
|
});
|
||||||
|
|
||||||
|
// This method will be called when Electron has finished
|
||||||
|
// initialization and is ready to create browser windows.
|
||||||
|
// Some APIs can only be used after this event occurs.
|
||||||
|
app.on('ready', async () => {
|
||||||
|
// https://github.com/electron/electron/issues/23757
|
||||||
|
// https://github.com/electron/electron/pull/28489
|
||||||
|
// TODO I think this can be removed when we are on electron 12 or 14
|
||||||
|
if (isDev) {
|
||||||
|
electron.protocol.registerFileProtocol('file', (request, callback) => {
|
||||||
|
const pathname = decodeURIComponent(request.url.replace('file:///', ''));
|
||||||
|
callback(pathname);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await configStore.init();
|
||||||
|
|
||||||
|
logger.info('CLI arguments', argv);
|
||||||
|
// Only if no files to open already (open-file might have already added some files)
|
||||||
|
if (filesToOpen.length === 0) filesToOpen = argv._;
|
||||||
|
const { settingsJson } = argv;
|
||||||
|
|
||||||
|
if (settingsJson != null) {
|
||||||
|
logger.info('initializing settings', settingsJson);
|
||||||
|
Object.entries(JSON5.parse(settingsJson)).forEach(([key, value]) => {
|
||||||
|
configStore.set(key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDev) {
|
||||||
|
const { default: installExtension, REACT_DEVELOPER_TOOLS } = require('electron-devtools-installer'); // eslint-disable-line global-require,import/no-extraneous-dependencies
|
||||||
|
|
||||||
|
installExtension(REACT_DEVELOPER_TOOLS)
|
||||||
|
.then(name => logger.info('Added Extension', name))
|
||||||
|
.catch(err => logger.error('Failed to add extension', err));
|
||||||
|
}
|
||||||
|
|
||||||
app.on('activate', () => {
|
|
||||||
// On OS X it's common to re-create a window in the app when the
|
|
||||||
// dock icon is clicked and there are no other windows open.
|
|
||||||
if (mainWindow === null) {
|
|
||||||
createWindow();
|
createWindow();
|
||||||
}
|
updateMenu();
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('renderer-ready', () => {
|
if (!process.windowsStore && !process.mas) {
|
||||||
rendererReady = true;
|
newVersion = await checkNewVersion();
|
||||||
if (filesToOpen.length > 0) openFiles(filesToOpen);
|
// newVersion = '1.2.3';
|
||||||
});
|
if (newVersion) updateMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Mac OS open with LosslessCut
|
// Quit when all windows are closed.
|
||||||
// Emitted when the user wants to open a file with the application. The open-file event is usually emitted when the application is already open and the OS wants to reuse the application to open the file.
|
app.on('window-all-closed', () => {
|
||||||
app.on('open-file', (event, path) => {
|
app.quit();
|
||||||
if (rendererReady) openFiles([path]);
|
});
|
||||||
else filesToOpen = [path];
|
|
||||||
event.preventDefault(); // recommended in docs https://www.electronjs.org/docs/latest/api/app#event-open-file-macos
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('setAskBeforeClose', (e, val) => {
|
app.on('activate', () => {
|
||||||
askBeforeClose = val;
|
// On OS X it's common to re-create a window in the app when the
|
||||||
});
|
// dock icon is clicked and there are no other windows open.
|
||||||
|
if (mainWindow === null) {
|
||||||
|
createWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.on('setLanguage', (e, language) => {
|
ipcMain.on('renderer-ready', () => {
|
||||||
i18n.changeLanguage(language).then(() => updateMenu()).catch((err) => logger.error('Failed to set language', err));
|
rendererReady = true;
|
||||||
});
|
if (filesToOpen.length > 0) openFiles(filesToOpen);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mac OS open with LosslessCut
|
||||||
|
// Emitted when the user wants to open a file with the application. The open-file event is usually emitted when the application is already open and the OS wants to reuse the application to open the file.
|
||||||
|
app.on('open-file', (event, path) => {
|
||||||
|
openFilesEventually([path]);
|
||||||
|
event.preventDefault(); // recommended in docs https://www.electronjs.org/docs/latest/api/app#event-open-file-macos
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('setAskBeforeClose', (e, val) => {
|
||||||
|
askBeforeClose = val;
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('setLanguage', (e, language) => {
|
||||||
|
i18n.changeLanguage(language).then(() => updateMenu()).catch((err) => logger.error('Failed to set language', err));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function focusWindow() {
|
function focusWindow() {
|
||||||
try {
|
try {
|
||||||
|
Loading…
Reference in New Issue
Block a user