diff --git a/config/defaults.js b/config/defaults.js index d01d059a..bc8b9b70 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -104,6 +104,13 @@ const defaultConfig = { "skip-silences": { onlySkipBeginning: false, }, + "crossfade": { + enabled: false, + fadeInDuration: 1500, // ms + fadeOutDuration: 5000, // ms + exitMusicBeforeEnd: 10, // s + fadeScaling: "linear", // 'linear', 'logarithmic' or a positive number in dB + }, visualizer: { enabled: false, type: "butterchurn", diff --git a/plugins/crossfade/front.js b/plugins/crossfade/front.js index f08d7d87..a00bc2fd 100644 --- a/plugins/crossfade/front.js +++ b/plugins/crossfade/front.js @@ -8,13 +8,7 @@ let transitionAudio; // Howler audio used to fade out the current music let firstVideo = true; let waitForTransition; -// Crossfade options that can be overridden in plugin options -let crossfadeOptions = { - fadeInDuration: 1500, // ms - fadeOutDuration: 5000, // ms - exitMusicBeforeEnd: 10, // s - fadeScaling: "linear", -}; +const defaultOptions = require('../../config/defaults').plugins.crossfade; const getStreamURL = async (videoID) => { const url = await ipcRenderer.invoke("audio-url", videoID); @@ -68,8 +62,8 @@ const createAudioForCrossfade = async (url) => { const syncVideoWithTransitionAudio = async () => { const video = document.querySelector("video"); const videoFader = new VolumeFader(video, { - fadeScaling: crossfadeOptions.fadeScaling, - fadeDuration: crossfadeOptions.fadeInDuration, + fadeScaling: defaultOptions.fadeScaling, + fadeDuration: defaultOptions.fadeInDuration, }); await transitionAudio.play(); @@ -95,7 +89,7 @@ const syncVideoWithTransitionAudio = async () => { const transitionBeforeEnd = () => { if ( video.currentTime >= - video.duration - crossfadeOptions.exitMusicBeforeEnd && + video.duration - defaultOptions.exitMusicBeforeEnd && isReadyToCrossfade() ) { video.removeEventListener("timeupdate", transitionBeforeEnd); @@ -130,8 +124,8 @@ const crossfade = (cb) => { const fader = new VolumeFader(transitionAudio._sounds[0]._node, { initialVolume: video.volume, - fadeScaling: crossfadeOptions.fadeScaling, - fadeDuration: crossfadeOptions.fadeOutDuration, + fadeScaling: defaultOptions.fadeScaling, + fadeDuration: defaultOptions.fadeOutDuration, }); // Fade out the music @@ -143,10 +137,7 @@ const crossfade = (cb) => { }; module.exports = (options) => { - crossfadeOptions = { - ...crossfadeOptions, - options, - }; + Object.assign(defaultOptions, options); document.addEventListener("apiLoaded", onApiLoaded, { once: true, diff --git a/plugins/crossfade/menu.js b/plugins/crossfade/menu.js new file mode 100644 index 00000000..c21a2e14 --- /dev/null +++ b/plugins/crossfade/menu.js @@ -0,0 +1,73 @@ +const { setOptions } = require("../../config/plugins"); +const defaultOptions = require("../../config/defaults").plugins.crossfade; + +const prompt = require("custom-electron-prompt"); +const promptOptions = require("../../providers/prompt-options"); + +module.exports = (win, options) => [ + { + label: "Advanced", + click: async () => { + const newOptions = await promptCrossfadeValues(win, options); + setOptions("crossfade", { ...options, ...newOptions }); + }, + }, +]; + +async function promptCrossfadeValues(win, options) { + const res = await prompt( + { + title: "Crossfade Options", + label: "", + type: "multiInput", + multiInputOptions: [ + { + label: "Fade in duration (ms)", + value: options.fadeInDuration || defaultOptions.fadeInDuration, + inputAttrs: { + type: "number", + required: true, + min: 0, + step: 100, + }, + }, + { + label: "Fade out duration (ms)", + value: options.fadeOutDuration || defaultOptions.fadeOutDuration, + inputAttrs: { + type: "number", + required: true, + min: 0, + step: 100, + }, + }, + { + label: "Crossfade x seconds before end", + value: + options.exitMusicBeforeEnd || defaultOptions.exitMusicBeforeEnd, + inputAttrs: { + type: "number", + required: true, + min: 0, + }, + }, + { + label: "Fade scaling", + selectOptions: { linear: "Linear", exponential: "Exponential" }, + value: options.fadeScaling || defaultOptions.fadeScaling, + }, + ], + resizable: true, + height: 355, + ...promptOptions(), + }, + win, + ).catch(console.error); + if (!res) return undefined; + return { + fadeInDuration: res[0], + fadeOutDuration: res[1], + exitMusicBeforeEnd: res[2], + fadeScaling: res[3], + }; +}