Skip to content

Commit 2ad097c

Browse files
committed
use new dynamic config
1 parent 648d102 commit 2ad097c

File tree

5 files changed

+137
-122
lines changed

5 files changed

+137
-122
lines changed

config/defaults.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ const defaultConfig = {
108108
enabled: false,
109109
fadeInDuration: 1500, // ms
110110
fadeOutDuration: 5000, // ms
111-
exitMusicBeforeEnd: 10, // s
111+
secondsBeforeEnd: 10, // s
112112
fadeScaling: "linear", // 'linear', 'logarithmic' or a positive number in dB
113113
},
114114
visualizer: {

plugins/crossfade/back.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const { ipcMain } = require("electron");
22
const { Innertube } = require("youtubei.js");
33

4-
module.exports = async (win, options) => {
4+
require("./config");
5+
6+
module.exports = async () => {
57
const yt = await Innertube.create();
68

79
ipcMain.handle("audio-url", async (_, videoID) => {

plugins/crossfade/config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const { PluginConfig } = require("../../config/dynamic");
2+
const config = new PluginConfig("crossfade", { enableFront: true });
3+
module.exports = { ...config };

plugins/crossfade/front.js

Lines changed: 124 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,146 +1,156 @@
1-
const { ipcRenderer } = require("electron");
2-
const { Howl } = require("howler");
1+
const { ipcRenderer } = require('electron');
2+
const { Howl } = require('howler');
33

44
// Extracted from https://github.com/bitfasching/VolumeFader
5-
require("./fader");
5+
require('./fader');
66

77
let transitionAudio; // Howler audio used to fade out the current music
88
let firstVideo = true;
99
let waitForTransition;
1010

11-
const config = require('../../config/defaults').plugins.crossfade;
11+
const defaultConfig = require('../../config/defaults').plugins.crossfade;
12+
13+
const configProvider = require('./config');
14+
let config = configProvider.getAll();
15+
16+
console.log({ config });
17+
18+
configProvider.subscribeAll((newConfig) => {
19+
config = newConfig;
20+
});
21+
22+
const configGetNum = (key) => Number(config[key]) || defaultConfig[key];
1223

1324
const getStreamURL = async (videoID) => {
14-
const url = await ipcRenderer.invoke("audio-url", videoID);
15-
return url;
25+
const url = await ipcRenderer.invoke('audio-url', videoID);
26+
return url;
1627
};
1728

1829
const getVideoIDFromURL = (url) => {
19-
return new URLSearchParams(url.split("?")?.at(-1)).get("v");
30+
return new URLSearchParams(url.split('?')?.at(-1)).get('v');
2031
};
2132

2233
const isReadyToCrossfade = () => {
23-
return transitionAudio && transitionAudio.state() === "loaded";
34+
return transitionAudio && transitionAudio.state() === 'loaded';
2435
};
2536

2637
const watchVideoIDChanges = (cb) => {
27-
navigation.addEventListener("navigate", (event) => {
28-
const currentVideoID = getVideoIDFromURL(
29-
event.currentTarget.currentEntry.url
30-
);
31-
const nextVideoID = getVideoIDFromURL(event.destination.url);
32-
33-
if (
34-
nextVideoID &&
35-
currentVideoID &&
36-
(firstVideo || nextVideoID !== currentVideoID)
37-
) {
38-
if (isReadyToCrossfade()) {
39-
crossfade(() => {
40-
cb(nextVideoID);
41-
});
42-
} else {
43-
cb(nextVideoID);
44-
firstVideo = false;
45-
}
46-
}
47-
});
38+
navigation.addEventListener('navigate', (event) => {
39+
const currentVideoID = getVideoIDFromURL(
40+
event.currentTarget.currentEntry.url,
41+
);
42+
const nextVideoID = getVideoIDFromURL(event.destination.url);
43+
44+
if (
45+
nextVideoID &&
46+
currentVideoID &&
47+
(firstVideo || nextVideoID !== currentVideoID)
48+
) {
49+
if (isReadyToCrossfade()) {
50+
crossfade(() => {
51+
cb(nextVideoID);
52+
});
53+
} else {
54+
cb(nextVideoID);
55+
firstVideo = false;
56+
}
57+
}
58+
});
4859
};
4960

5061
const createAudioForCrossfade = async (url) => {
51-
if (transitionAudio) {
52-
transitionAudio.unload();
53-
}
54-
transitionAudio = new Howl({
55-
src: url,
56-
html5: true,
57-
volume: 0,
58-
});
59-
await syncVideoWithTransitionAudio();
62+
if (transitionAudio) {
63+
transitionAudio.unload();
64+
}
65+
transitionAudio = new Howl({
66+
src: url,
67+
html5: true,
68+
volume: 0,
69+
});
70+
await syncVideoWithTransitionAudio();
6071
};
6172

6273
const syncVideoWithTransitionAudio = async () => {
63-
const video = document.querySelector("video");
64-
const videoFader = new VolumeFader(video, {
65-
fadeScaling: config.fadeScaling,
66-
fadeDuration: config.fadeInDuration,
67-
});
68-
69-
await transitionAudio.play();
70-
await transitionAudio.seek(video.currentTime);
71-
72-
video.onseeking = () => {
73-
transitionAudio.seek(video.currentTime);
74-
};
75-
video.onpause = () => {
76-
transitionAudio.pause();
77-
};
78-
video.onplay = async () => {
79-
await transitionAudio.play();
80-
await transitionAudio.seek(video.currentTime);
81-
82-
// Fade in
83-
const videoVolume = video.volume;
84-
video.volume = 0;
85-
videoFader.fadeTo(videoVolume);
86-
};
87-
88-
// Exit just before the end for the transition
89-
const transitionBeforeEnd = () => {
90-
if (
91-
video.currentTime >=
92-
video.duration - config.exitMusicBeforeEnd &&
93-
isReadyToCrossfade()
94-
) {
95-
video.removeEventListener("timeupdate", transitionBeforeEnd);
96-
97-
// Go to next video - XXX: does not support "repeat 1" mode
98-
document.querySelector(".next-button").click();
99-
}
100-
};
101-
video.ontimeupdate = transitionBeforeEnd;
74+
const video = document.querySelector('video');
75+
76+
const videoFader = new VolumeFader(video, {
77+
fadeScaling: configGetNum('fadeScaling'),
78+
fadeDuration: configGetNum('fadeInDuration'),
79+
});
80+
81+
await transitionAudio.play();
82+
await transitionAudio.seek(video.currentTime);
83+
84+
video.onseeking = () => {
85+
transitionAudio.seek(video.currentTime);
86+
};
87+
video.onpause = () => {
88+
transitionAudio.pause();
89+
};
90+
video.onplay = async () => {
91+
await transitionAudio.play();
92+
await transitionAudio.seek(video.currentTime);
93+
94+
// Fade in
95+
const videoVolume = video.volume;
96+
video.volume = 0;
97+
videoFader.fadeTo(videoVolume);
98+
};
99+
100+
// Exit just before the end for the transition
101+
const transitionBeforeEnd = () => {
102+
if (
103+
video.currentTime >=
104+
video.duration - configGetNum('secondsBeforeEnd') &&
105+
isReadyToCrossfade()
106+
) {
107+
video.removeEventListener('timeupdate', transitionBeforeEnd);
108+
109+
// Go to next video - XXX: does not support "repeat 1" mode
110+
document.querySelector('.next-button').click();
111+
}
112+
};
113+
video.ontimeupdate = transitionBeforeEnd;
102114
};
103115

104116
const onApiLoaded = () => {
105-
watchVideoIDChanges(async (videoID) => {
106-
await waitForTransition;
107-
const url = await getStreamURL(videoID);
108-
await createAudioForCrossfade(url);
109-
});
117+
watchVideoIDChanges(async (videoID) => {
118+
await waitForTransition;
119+
const url = await getStreamURL(videoID);
120+
await createAudioForCrossfade(url);
121+
});
110122
};
111123

112-
const crossfade = (cb) => {
113-
if (!isReadyToCrossfade()) {
114-
cb();
115-
return;
116-
}
117-
118-
let resolveTransition;
119-
waitForTransition = new Promise(function (resolve, reject) {
120-
resolveTransition = resolve;
121-
});
122-
123-
const video = document.querySelector("video");
124-
125-
const fader = new VolumeFader(transitionAudio._sounds[0]._node, {
126-
initialVolume: video.volume,
127-
fadeScaling: config.fadeScaling,
128-
fadeDuration: config.fadeOutDuration,
129-
});
130-
131-
// Fade out the music
132-
video.volume = 0;
133-
fader.fadeOut(() => {
134-
resolveTransition();
135-
cb();
136-
});
124+
const crossfade = async (cb) => {
125+
if (!isReadyToCrossfade()) {
126+
cb();
127+
return;
128+
}
129+
130+
let resolveTransition;
131+
waitForTransition = new Promise(function (resolve, reject) {
132+
resolveTransition = resolve;
133+
});
134+
135+
const video = document.querySelector('video');
136+
137+
const fader = new VolumeFader(transitionAudio._sounds[0]._node, {
138+
initialVolume: video.volume,
139+
fadeScaling: configGetNum('fadeScaling'),
140+
fadeDuration: configGetNum('fadeOutDuration'),
141+
});
142+
143+
// Fade out the music
144+
video.volume = 0;
145+
fader.fadeOut(() => {
146+
resolveTransition();
147+
cb();
148+
});
137149
};
138150

139-
module.exports = (options) => {
140-
Object.assign(config, options);
141-
142-
document.addEventListener("apiLoaded", onApiLoaded, {
143-
once: true,
144-
passive: true,
145-
});
151+
module.exports = () => {
152+
document.addEventListener('apiLoaded', onApiLoaded, {
153+
once: true,
154+
passive: true,
155+
});
146156
};

plugins/crossfade/menu.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
const { setOptions } = require("../../config/plugins");
1+
const config = require("./config");
22
const defaultOptions = require("../../config/defaults").plugins.crossfade;
33

44
const prompt = require("custom-electron-prompt");
55
const promptOptions = require("../../providers/prompt-options");
66

7-
module.exports = (win, options) => [
7+
module.exports = (win) => [
88
{
99
label: "Advanced",
1010
click: async () => {
11-
const newOptions = await promptCrossfadeValues(win, options);
12-
setOptions("crossfade", { ...options, ...newOptions });
11+
const newOptions = await promptCrossfadeValues(win, config.getAll());
12+
if (newOptions) config.setAll(newOptions);
1313
},
1414
},
1515
];
@@ -43,7 +43,7 @@ async function promptCrossfadeValues(win, options) {
4343
{
4444
label: "Crossfade x seconds before end",
4545
value:
46-
options.exitMusicBeforeEnd || defaultOptions.exitMusicBeforeEnd,
46+
options.secondsBeforeEnd || defaultOptions.secondsBeforeEnd,
4747
inputAttrs: {
4848
type: "number",
4949
required: true,
@@ -66,7 +66,7 @@ async function promptCrossfadeValues(win, options) {
6666
return {
6767
fadeInDuration: Number(res[0]),
6868
fadeOutDuration: Number(res[1]),
69-
exitMusicBeforeEnd: Number(res[2]),
69+
secondsBeforeEnd: Number(res[2]),
7070
fadeScaling: res[3],
7171
};
7272
}

0 commit comments

Comments
 (0)