From 2ad097c743e44665133bd0195150f06b3a7abd68 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 19 Mar 2023 23:47:55 +0200 Subject: [PATCH] use new dynamic config --- config/defaults.js | 2 +- plugins/crossfade/back.js | 4 +- plugins/crossfade/config.js | 3 + plugins/crossfade/front.js | 218 +++++++++++++++++++----------------- plugins/crossfade/menu.js | 12 +- 5 files changed, 127 insertions(+), 112 deletions(-) create mode 100644 plugins/crossfade/config.js diff --git a/config/defaults.js b/config/defaults.js index bc8b9b70..1c762e2d 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -108,7 +108,7 @@ const defaultConfig = { enabled: false, fadeInDuration: 1500, // ms fadeOutDuration: 5000, // ms - exitMusicBeforeEnd: 10, // s + secondsBeforeEnd: 10, // s fadeScaling: "linear", // 'linear', 'logarithmic' or a positive number in dB }, visualizer: { diff --git a/plugins/crossfade/back.js b/plugins/crossfade/back.js index ee2dc679..0443c95a 100644 --- a/plugins/crossfade/back.js +++ b/plugins/crossfade/back.js @@ -1,7 +1,9 @@ const { ipcMain } = require("electron"); const { Innertube } = require("youtubei.js"); -module.exports = async (win, options) => { +require("./config"); + +module.exports = async () => { const yt = await Innertube.create(); ipcMain.handle("audio-url", async (_, videoID) => { diff --git a/plugins/crossfade/config.js b/plugins/crossfade/config.js new file mode 100644 index 00000000..6db3c562 --- /dev/null +++ b/plugins/crossfade/config.js @@ -0,0 +1,3 @@ +const { PluginConfig } = require("../../config/dynamic"); +const config = new PluginConfig("crossfade", { enableFront: true }); +module.exports = { ...config }; diff --git a/plugins/crossfade/front.js b/plugins/crossfade/front.js index 5494387a..1eddaef1 100644 --- a/plugins/crossfade/front.js +++ b/plugins/crossfade/front.js @@ -1,146 +1,156 @@ -const { ipcRenderer } = require("electron"); -const { Howl } = require("howler"); +const { ipcRenderer } = require('electron'); +const { Howl } = require('howler'); // Extracted from https://github.com/bitfasching/VolumeFader -require("./fader"); +require('./fader'); let transitionAudio; // Howler audio used to fade out the current music let firstVideo = true; let waitForTransition; -const config = require('../../config/defaults').plugins.crossfade; +const defaultConfig = require('../../config/defaults').plugins.crossfade; + +const configProvider = require('./config'); +let config = configProvider.getAll(); + +console.log({ config }); + +configProvider.subscribeAll((newConfig) => { + config = newConfig; +}); + +const configGetNum = (key) => Number(config[key]) || defaultConfig[key]; const getStreamURL = async (videoID) => { - const url = await ipcRenderer.invoke("audio-url", videoID); - return url; + const url = await ipcRenderer.invoke('audio-url', videoID); + return url; }; const getVideoIDFromURL = (url) => { - return new URLSearchParams(url.split("?")?.at(-1)).get("v"); + return new URLSearchParams(url.split('?')?.at(-1)).get('v'); }; const isReadyToCrossfade = () => { - return transitionAudio && transitionAudio.state() === "loaded"; + return transitionAudio && transitionAudio.state() === 'loaded'; }; const watchVideoIDChanges = (cb) => { - navigation.addEventListener("navigate", (event) => { - const currentVideoID = getVideoIDFromURL( - event.currentTarget.currentEntry.url - ); - const nextVideoID = getVideoIDFromURL(event.destination.url); + navigation.addEventListener('navigate', (event) => { + const currentVideoID = getVideoIDFromURL( + event.currentTarget.currentEntry.url, + ); + const nextVideoID = getVideoIDFromURL(event.destination.url); - if ( - nextVideoID && - currentVideoID && - (firstVideo || nextVideoID !== currentVideoID) - ) { - if (isReadyToCrossfade()) { - crossfade(() => { - cb(nextVideoID); - }); - } else { - cb(nextVideoID); - firstVideo = false; - } - } - }); + if ( + nextVideoID && + currentVideoID && + (firstVideo || nextVideoID !== currentVideoID) + ) { + if (isReadyToCrossfade()) { + crossfade(() => { + cb(nextVideoID); + }); + } else { + cb(nextVideoID); + firstVideo = false; + } + } + }); }; const createAudioForCrossfade = async (url) => { - if (transitionAudio) { - transitionAudio.unload(); - } - transitionAudio = new Howl({ - src: url, - html5: true, - volume: 0, - }); - await syncVideoWithTransitionAudio(); + if (transitionAudio) { + transitionAudio.unload(); + } + transitionAudio = new Howl({ + src: url, + html5: true, + volume: 0, + }); + await syncVideoWithTransitionAudio(); }; const syncVideoWithTransitionAudio = async () => { - const video = document.querySelector("video"); - const videoFader = new VolumeFader(video, { - fadeScaling: config.fadeScaling, - fadeDuration: config.fadeInDuration, - }); + const video = document.querySelector('video'); - await transitionAudio.play(); - await transitionAudio.seek(video.currentTime); + const videoFader = new VolumeFader(video, { + fadeScaling: configGetNum('fadeScaling'), + fadeDuration: configGetNum('fadeInDuration'), + }); - video.onseeking = () => { - transitionAudio.seek(video.currentTime); - }; - video.onpause = () => { - transitionAudio.pause(); - }; - video.onplay = async () => { - await transitionAudio.play(); - await transitionAudio.seek(video.currentTime); + await transitionAudio.play(); + await transitionAudio.seek(video.currentTime); - // Fade in - const videoVolume = video.volume; - video.volume = 0; - videoFader.fadeTo(videoVolume); - }; + video.onseeking = () => { + transitionAudio.seek(video.currentTime); + }; + video.onpause = () => { + transitionAudio.pause(); + }; + video.onplay = async () => { + await transitionAudio.play(); + await transitionAudio.seek(video.currentTime); - // Exit just before the end for the transition - const transitionBeforeEnd = () => { - if ( - video.currentTime >= - video.duration - config.exitMusicBeforeEnd && - isReadyToCrossfade() - ) { - video.removeEventListener("timeupdate", transitionBeforeEnd); + // Fade in + const videoVolume = video.volume; + video.volume = 0; + videoFader.fadeTo(videoVolume); + }; - // Go to next video - XXX: does not support "repeat 1" mode - document.querySelector(".next-button").click(); - } - }; - video.ontimeupdate = transitionBeforeEnd; + // Exit just before the end for the transition + const transitionBeforeEnd = () => { + if ( + video.currentTime >= + video.duration - configGetNum('secondsBeforeEnd') && + isReadyToCrossfade() + ) { + video.removeEventListener('timeupdate', transitionBeforeEnd); + + // Go to next video - XXX: does not support "repeat 1" mode + document.querySelector('.next-button').click(); + } + }; + video.ontimeupdate = transitionBeforeEnd; }; const onApiLoaded = () => { - watchVideoIDChanges(async (videoID) => { - await waitForTransition; - const url = await getStreamURL(videoID); - await createAudioForCrossfade(url); - }); + watchVideoIDChanges(async (videoID) => { + await waitForTransition; + const url = await getStreamURL(videoID); + await createAudioForCrossfade(url); + }); }; -const crossfade = (cb) => { - if (!isReadyToCrossfade()) { - cb(); - return; - } +const crossfade = async (cb) => { + if (!isReadyToCrossfade()) { + cb(); + return; + } - let resolveTransition; - waitForTransition = new Promise(function (resolve, reject) { - resolveTransition = resolve; - }); + let resolveTransition; + waitForTransition = new Promise(function (resolve, reject) { + resolveTransition = resolve; + }); - const video = document.querySelector("video"); + const video = document.querySelector('video'); - const fader = new VolumeFader(transitionAudio._sounds[0]._node, { - initialVolume: video.volume, - fadeScaling: config.fadeScaling, - fadeDuration: config.fadeOutDuration, - }); + const fader = new VolumeFader(transitionAudio._sounds[0]._node, { + initialVolume: video.volume, + fadeScaling: configGetNum('fadeScaling'), + fadeDuration: configGetNum('fadeOutDuration'), + }); - // Fade out the music - video.volume = 0; - fader.fadeOut(() => { - resolveTransition(); - cb(); - }); + // Fade out the music + video.volume = 0; + fader.fadeOut(() => { + resolveTransition(); + cb(); + }); }; -module.exports = (options) => { - Object.assign(config, options); - - document.addEventListener("apiLoaded", onApiLoaded, { - once: true, - passive: true, - }); +module.exports = () => { + document.addEventListener('apiLoaded', onApiLoaded, { + once: true, + passive: true, + }); }; diff --git a/plugins/crossfade/menu.js b/plugins/crossfade/menu.js index b5175034..5ee728c7 100644 --- a/plugins/crossfade/menu.js +++ b/plugins/crossfade/menu.js @@ -1,15 +1,15 @@ -const { setOptions } = require("../../config/plugins"); +const config = require("./config"); const defaultOptions = require("../../config/defaults").plugins.crossfade; const prompt = require("custom-electron-prompt"); const promptOptions = require("../../providers/prompt-options"); -module.exports = (win, options) => [ +module.exports = (win) => [ { label: "Advanced", click: async () => { - const newOptions = await promptCrossfadeValues(win, options); - setOptions("crossfade", { ...options, ...newOptions }); + const newOptions = await promptCrossfadeValues(win, config.getAll()); + if (newOptions) config.setAll(newOptions); }, }, ]; @@ -43,7 +43,7 @@ async function promptCrossfadeValues(win, options) { { label: "Crossfade x seconds before end", value: - options.exitMusicBeforeEnd || defaultOptions.exitMusicBeforeEnd, + options.secondsBeforeEnd || defaultOptions.secondsBeforeEnd, inputAttrs: { type: "number", required: true, @@ -66,7 +66,7 @@ async function promptCrossfadeValues(win, options) { return { fadeInDuration: Number(res[0]), fadeOutDuration: Number(res[1]), - exitMusicBeforeEnd: Number(res[2]), + secondsBeforeEnd: Number(res[2]), fadeScaling: res[3], }; }