2020-04-17 17:58:10 +02:00
|
|
|
const Store = require('electron-store');
|
2021-02-16 23:44:30 +01:00
|
|
|
const electron = require('electron');
|
|
|
|
const os = require('os');
|
2022-01-01 08:24:19 +01:00
|
|
|
const { join, dirname } = require('path');
|
2021-02-16 23:44:30 +01:00
|
|
|
const { pathExists } = require('fs-extra');
|
|
|
|
|
2022-09-04 16:44:48 +02:00
|
|
|
const logger = require('./logger');
|
|
|
|
|
2021-02-16 23:44:30 +01:00
|
|
|
const { app } = electron;
|
|
|
|
|
2020-04-17 17:58:10 +02:00
|
|
|
|
2022-02-20 10:23:18 +01:00
|
|
|
const defaultKeyBindings = [
|
|
|
|
{ keys: 'plus', action: 'addSegment' },
|
|
|
|
{ keys: 'space', action: 'togglePlayResetSpeed' },
|
|
|
|
{ keys: 'k', action: 'togglePlayNoResetSpeed' },
|
|
|
|
{ keys: 'j', action: 'reducePlaybackRate' },
|
|
|
|
{ keys: 'shift+j', action: 'reducePlaybackRateMore' },
|
|
|
|
{ keys: 'l', action: 'increasePlaybackRate' },
|
|
|
|
{ keys: 'shift+l', action: 'increasePlaybackRateMore' },
|
|
|
|
{ keys: 'z', action: 'timelineToggleComfortZoom' },
|
|
|
|
{ keys: ',', action: 'seekPreviousFrame' },
|
|
|
|
{ keys: '.', action: 'seekNextFrame' },
|
|
|
|
{ keys: 'c', action: 'captureSnapshot' },
|
|
|
|
{ keys: 'i', action: 'setCutStart' },
|
|
|
|
{ keys: 'o', action: 'setCutEnd' },
|
|
|
|
{ keys: 'backspace', action: 'removeCurrentSegment' },
|
|
|
|
{ keys: 'd', action: 'cleanupFilesDialog' },
|
|
|
|
{ keys: 'b', action: 'splitCurrentSegment' },
|
|
|
|
{ keys: 'r', action: 'increaseRotation' },
|
|
|
|
{ keys: 'g', action: 'goToTimecode' },
|
|
|
|
|
|
|
|
{ keys: 'left', action: 'seekBackwards' },
|
|
|
|
{ keys: 'ctrl+left', action: 'seekBackwardsPercent' },
|
|
|
|
{ keys: 'command+left', action: 'seekBackwardsPercent' },
|
|
|
|
{ keys: 'alt+left', action: 'seekBackwardsKeyframe' },
|
|
|
|
{ keys: 'shift+left', action: 'jumpCutStart' },
|
|
|
|
|
|
|
|
{ keys: 'right', action: 'seekForwards' },
|
|
|
|
{ keys: 'ctrl+right', action: 'seekForwardsPercent' },
|
|
|
|
{ keys: 'command+right', action: 'seekForwardsPercent' },
|
|
|
|
{ keys: 'alt+right', action: 'seekForwardsKeyframe' },
|
|
|
|
{ keys: 'shift+right', action: 'jumpCutEnd' },
|
|
|
|
|
implement hotkeys
jumpTimelineStart (ctrl+home)
jumpTimelineEnd (ctrl+end)
reorderSegsByStartTime,
invertAllCutSegments,
createFixedDurationSegments,
createNumSegments,
shuffleSegments,
clearSegments,
toggleSegmentsList,
toggleStreamsSelector,
extractAllStreams,
convertFormatCurrentFile,
convertFormatBatch,
concatBatch,
toggleKeyframeCutMode,
toggleCaptureFormat,
toggleStripAudio,
setStartTimeOffset,
2022-02-20 11:34:10 +01:00
|
|
|
{ keys: 'ctrl+home', action: 'jumpTimelineStart' },
|
|
|
|
{ keys: 'ctrl+end', action: 'jumpTimelineEnd' },
|
|
|
|
|
2022-03-06 14:50:48 +01:00
|
|
|
{ keys: 'up', action: 'jumpPrevSegment' },
|
2022-02-20 10:23:18 +01:00
|
|
|
{ keys: 'ctrl+up', action: 'timelineZoomIn' },
|
|
|
|
{ keys: 'command+up', action: 'timelineZoomIn' },
|
|
|
|
{ keys: 'shift+up', action: 'batchPreviousFile' },
|
|
|
|
|
2022-03-06 14:50:48 +01:00
|
|
|
{ keys: 'down', action: 'jumpNextSegment' },
|
2022-02-20 10:23:18 +01:00
|
|
|
{ keys: 'ctrl+down', action: 'timelineZoomOut' },
|
|
|
|
{ keys: 'command+down', action: 'timelineZoomOut' },
|
|
|
|
{ keys: 'shift+down', action: 'batchNextFile' },
|
|
|
|
|
2022-02-24 13:57:35 +01:00
|
|
|
{ keys: 'shift+enter', action: 'batchOpenSelectedFile' },
|
|
|
|
|
2022-02-20 10:23:18 +01:00
|
|
|
// https://github.com/mifi/lossless-cut/issues/610
|
|
|
|
{ keys: 'ctrl+z', action: 'undo' },
|
|
|
|
{ keys: 'command+z', action: 'undo' },
|
|
|
|
{ keys: 'ctrl+shift+z', action: 'redo' },
|
|
|
|
{ keys: 'command+shift+z', action: 'redo' },
|
|
|
|
|
|
|
|
{ keys: 'enter', action: 'labelCurrentSegment' },
|
|
|
|
|
|
|
|
{ keys: 'e', action: 'export' },
|
2022-02-20 13:12:58 +01:00
|
|
|
{ keys: 'shift+/', action: 'toggleKeyboardShortcuts' },
|
2022-02-20 10:23:18 +01:00
|
|
|
{ keys: 'escape', action: 'closeActiveScreen' },
|
2022-03-01 11:26:20 +01:00
|
|
|
|
|
|
|
{ keys: 'alt+up', action: 'increaseVolume' },
|
|
|
|
{ keys: 'alt+down', action: 'decreaseVolume' },
|
2022-02-20 10:23:18 +01:00
|
|
|
];
|
|
|
|
|
2020-04-17 17:58:10 +02:00
|
|
|
const defaults = {
|
2021-02-16 23:44:30 +01:00
|
|
|
captureFormat: 'jpeg',
|
|
|
|
customOutDir: undefined,
|
|
|
|
keyframeCut: true,
|
|
|
|
autoMerge: false,
|
|
|
|
autoDeleteMergedSegments: true,
|
2022-02-13 15:27:23 +01:00
|
|
|
segmentsToChaptersOnly: false,
|
2022-02-28 08:07:51 +01:00
|
|
|
enableSmartCut: false,
|
2022-01-14 09:57:14 +01:00
|
|
|
timecodeFormat: 'timecodeWithDecimalFraction',
|
2021-02-16 23:44:30 +01:00
|
|
|
invertCutSegments: false,
|
|
|
|
autoExportExtraStreams: true,
|
|
|
|
exportConfirmEnabled: true,
|
|
|
|
askBeforeClose: false,
|
|
|
|
enableAskForImportChapters: true,
|
|
|
|
enableAskForFileOpenAction: true,
|
2021-08-24 16:22:56 +02:00
|
|
|
playbackVolume: 1,
|
2021-02-16 23:44:30 +01:00
|
|
|
autoSaveProjectFile: true,
|
|
|
|
wheelSensitivity: 0.2,
|
|
|
|
language: undefined,
|
|
|
|
ffmpegExperimental: false,
|
|
|
|
preserveMovData: false,
|
|
|
|
movFastStart: true,
|
|
|
|
avoidNegativeTs: 'make_zero',
|
|
|
|
hideNotifications: undefined,
|
|
|
|
autoLoadTimecode: false,
|
|
|
|
segmentsToChapters: false,
|
|
|
|
preserveMetadataOnMerge: false,
|
|
|
|
simpleMode: true,
|
|
|
|
outSegTemplate: undefined,
|
|
|
|
keyboardSeekAccFactor: 1.03,
|
|
|
|
keyboardNormalSeekSpeed: 1,
|
2021-02-18 18:57:53 +01:00
|
|
|
enableTransferTimestamps: true,
|
2021-04-07 18:33:54 +02:00
|
|
|
outFormatLocked: undefined,
|
2021-08-23 18:50:21 +02:00
|
|
|
safeOutputFileName: true,
|
2022-01-11 16:47:33 +01:00
|
|
|
windowBounds: undefined,
|
2022-01-15 14:44:05 +01:00
|
|
|
enableAutoHtml5ify: true,
|
2022-02-20 10:23:18 +01:00
|
|
|
keyBindings: defaultKeyBindings,
|
2022-03-01 07:30:30 +01:00
|
|
|
customFfPath: undefined,
|
2022-03-02 07:04:36 +01:00
|
|
|
storeProjectInWorkingDir: true,
|
2022-08-12 20:54:33 +02:00
|
|
|
enableOverwriteOutput: true,
|
2022-10-19 19:25:41 +02:00
|
|
|
mouseWheelZoomModifierKey: 'ctrl',
|
2020-04-17 17:58:10 +02:00
|
|
|
};
|
|
|
|
|
2021-02-16 23:44:30 +01:00
|
|
|
// For portable app: https://github.com/mifi/lossless-cut/issues/645
|
|
|
|
async function getCustomStoragePath() {
|
|
|
|
try {
|
|
|
|
const isWindows = os.platform() === 'win32';
|
|
|
|
if (!isWindows || process.windowsStore) return undefined;
|
|
|
|
|
2021-12-27 07:35:00 +01:00
|
|
|
// https://github.com/mifi/lossless-cut/issues/645#issuecomment-1001363314
|
|
|
|
// https://stackoverflow.com/questions/46307797/how-to-get-the-original-path-of-a-portable-electron-app
|
2022-01-01 08:24:19 +01:00
|
|
|
// https://github.com/electron-userland/electron-builder/blob/master/docs/configuration/nsis.md
|
|
|
|
const customStorageDir = process.env.PORTABLE_EXECUTABLE_DIR || dirname(app.getPath('exe'));
|
|
|
|
const customConfigPath = join(customStorageDir, 'config.json');
|
|
|
|
if (await pathExists(customConfigPath)) return customStorageDir;
|
2021-02-16 23:44:30 +01:00
|
|
|
return undefined;
|
|
|
|
} catch (err) {
|
2022-09-04 16:44:48 +02:00
|
|
|
logger.error('Failed to get custom storage path', err);
|
2021-02-16 23:44:30 +01:00
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
}
|
2020-04-17 17:58:10 +02:00
|
|
|
|
|
|
|
let store;
|
|
|
|
|
|
|
|
async function init() {
|
2021-02-16 23:44:30 +01:00
|
|
|
const customStoragePath = await getCustomStoragePath();
|
2022-09-04 16:44:48 +02:00
|
|
|
if (customStoragePath) logger.info('customStoragePath', customStoragePath);
|
2021-02-16 23:44:30 +01:00
|
|
|
|
2020-04-17 17:58:10 +02:00
|
|
|
for (let i = 0; i < 5; i += 1) {
|
|
|
|
try {
|
2021-02-16 23:44:30 +01:00
|
|
|
store = new Store({ defaults, cwd: customStoragePath });
|
2020-04-17 17:58:10 +02:00
|
|
|
return;
|
|
|
|
} catch (err) {
|
|
|
|
// eslint-disable-next-line no-await-in-loop
|
|
|
|
await new Promise(r => setTimeout(r, 2000));
|
2022-09-04 16:44:48 +02:00
|
|
|
logger.error('Failed to create config store, retrying', err);
|
2020-04-17 17:58:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error('Timed out while creating config store');
|
|
|
|
}
|
|
|
|
|
|
|
|
function get(key) {
|
|
|
|
return store.get(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
function set(key, val) {
|
|
|
|
if (val === undefined) store.delete(key);
|
|
|
|
else store.set(key, val);
|
|
|
|
}
|
|
|
|
|
2021-04-08 17:37:48 +02:00
|
|
|
function reset(key) {
|
|
|
|
set(key, defaults[key]);
|
|
|
|
}
|
|
|
|
|
2020-04-17 17:58:10 +02:00
|
|
|
module.exports = {
|
|
|
|
init,
|
|
|
|
get,
|
|
|
|
set,
|
2021-04-08 17:37:48 +02:00
|
|
|
reset,
|
2020-04-17 17:58:10 +02:00
|
|
|
};
|