From 6e1c50ede112b17f82855c78e90779df97efdb11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Tue, 14 Jun 2022 15:45:58 +0200 Subject: [PATCH 1/8] Support MPRIS loop --- plugins/shortcuts/mpris.js | 29 +++++++++++++++++++++++++++++ providers/song-controls.js | 5 ++++- providers/song-info-front.js | 11 +++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/plugins/shortcuts/mpris.js b/plugins/shortcuts/mpris.js index 973feb51..7c656624 100644 --- a/plugins/shortcuts/mpris.js +++ b/plugins/shortcuts/mpris.js @@ -34,6 +34,35 @@ function registerMPRIS(win) { let currentSeconds = 0; ipcMain.on('timeChanged', (_, t) => currentSeconds = t); + let currentLoopStatus = undefined; + let manuallySwitchingStatus = false; + ipcMain.on("repeatChanged", (_, mode) => { + if (manuallySwitchingStatus) + return; + + if (mode == "Repeat off") + currentLoopStatus = "None"; + else if (mode == "Repeat one") + currentLoopStatus = "Track"; + else if (mode == "Repeat all") + currentLoopStatus = "Playlist"; + + player.loopStatus = currentLoopStatus; + }); + player.on("loopStatus", (status) => { + // switchRepeat cycles between states in that order + const switches = ["None", "Playlist", "Track"]; + const curIdx = switches.indexOf(currentLoopStatus); + const newIdx = switches.indexOf(status); + + // Get a delta in the range [0,2] + const delta = ((newIdx - curIdx) % 3 + 3) % 3; + + manuallySwitchingStatus = true; + songControls.switchRepeat(delta); + manuallySwitchingStatus = false; + }) + player.getPosition = () => secToMicro(currentSeconds) player.on("raise", () => { diff --git a/providers/song-controls.js b/providers/song-controls.js index d4659504..bd9d048e 100644 --- a/providers/song-controls.js +++ b/providers/song-controls.js @@ -20,7 +20,10 @@ module.exports = (win) => { go1sBack: () => pressKey(win, "h", ["shift"]), go1sForward: () => pressKey(win, "l", ["shift"]), shuffle: () => pressKey(win, "s"), - switchRepeat: () => pressKey(win, "r"), + switchRepeat: (n = 1) => { + for (let i = 0; i != n; ++i) + pressKey(win, "r"); + }, // General volumeMinus10: () => pressKey(win, "-"), volumePlus10: () => pressKey(win, "="), diff --git a/providers/song-info-front.js b/providers/song-info-front.js index e8bb8bcf..3a704598 100644 --- a/providers/song-info-front.js +++ b/providers/song-info-front.js @@ -22,6 +22,7 @@ module.exports = () => { if (config.plugins.isEnabled('tuna-obs') || (is.linux() && config.plugins.isEnabled('shortcuts'))) { setupTimeChangeListener(); + setupRepeatChangeListener(); } const video = $('video'); // name = "dataloaded" and abit later "dataupdated" @@ -63,3 +64,13 @@ function setupTimeChangeListener() { }); progressObserver.observe($('#progress-bar'), { attributeFilter: ["value"] }) } + +function setupRepeatChangeListener() { + const repeatObserver = new MutationObserver(mutations => { + ipcRenderer.send('repeatChanged', mutations[0].target.title); + }); + repeatObserver.observe($('#right-controls .repeat'), { attributeFilter: ["title"] }); + + // Emit the initial value as well; as it's persistent between launches. + ipcRenderer.send('repeatChanged', $('#right-controls .repeat').title); +} From bba499044bac5b57d3a7a9e581d023faca3ca9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Tue, 14 Jun 2022 19:43:36 +0200 Subject: [PATCH 2/8] Style changes for review --- plugins/shortcuts/mpris.js | 6 +++--- providers/song-controls.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/shortcuts/mpris.js b/plugins/shortcuts/mpris.js index 7c656624..53d46ff7 100644 --- a/plugins/shortcuts/mpris.js +++ b/plugins/shortcuts/mpris.js @@ -52,11 +52,11 @@ function registerMPRIS(win) { player.on("loopStatus", (status) => { // switchRepeat cycles between states in that order const switches = ["None", "Playlist", "Track"]; - const curIdx = switches.indexOf(currentLoopStatus); - const newIdx = switches.indexOf(status); + const currentIndex = switches.indexOf(currentLoopStatus); + const targetIndex = switches.indexOf(status); // Get a delta in the range [0,2] - const delta = ((newIdx - curIdx) % 3 + 3) % 3; + const delta = (targetIndex - currentIndex + 3) % 3; manuallySwitchingStatus = true; songControls.switchRepeat(delta); diff --git a/providers/song-controls.js b/providers/song-controls.js index bd9d048e..e5b4848e 100644 --- a/providers/song-controls.js +++ b/providers/song-controls.js @@ -21,7 +21,7 @@ module.exports = (win) => { go1sForward: () => pressKey(win, "l", ["shift"]), shuffle: () => pressKey(win, "s"), switchRepeat: (n = 1) => { - for (let i = 0; i != n; ++i) + for (let i = 0; i < n; i++) pressKey(win, "r"); }, // General From 9932fd7647fe717f12e19688a709a49ceac9b2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Wed, 22 Jun 2022 18:30:49 +0200 Subject: [PATCH 3/8] Fix mpris playback status on play/pause --- plugins/shortcuts/mpris.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/shortcuts/mpris.js b/plugins/shortcuts/mpris.js index 53d46ff7..2609ddee 100644 --- a/plugins/shortcuts/mpris.js +++ b/plugins/shortcuts/mpris.js @@ -82,8 +82,11 @@ function registerMPRIS(win) { playPause() } }); + player.on("playpause", () => { + player.playbackStatus = player.playbackStatus == 'Playing' ? "Paused" : "Playing"; + playPause(); + }); - player.on("playpause", playPause); player.on("next", next); player.on("previous", previous); From e7e873866d74f3aa68d8ceeb45f7418f2b925e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Sun, 26 Jun 2022 17:37:25 +0200 Subject: [PATCH 4/8] Use triple equals --- plugins/shortcuts/mpris.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/shortcuts/mpris.js b/plugins/shortcuts/mpris.js index 2609ddee..cc936caf 100644 --- a/plugins/shortcuts/mpris.js +++ b/plugins/shortcuts/mpris.js @@ -83,7 +83,7 @@ function registerMPRIS(win) { } }); player.on("playpause", () => { - player.playbackStatus = player.playbackStatus == 'Playing' ? "Paused" : "Playing"; + player.playbackStatus = player.playbackStatus === 'Playing' ? "Paused" : "Playing"; playPause(); }); From 2499f574efcab851c0c7a078e5aaa7c18ddac492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Sun, 26 Jun 2022 19:43:03 +0200 Subject: [PATCH 5/8] Use triple equals in more places --- plugins/shortcuts/mpris.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/shortcuts/mpris.js b/plugins/shortcuts/mpris.js index cc936caf..49fc8d96 100644 --- a/plugins/shortcuts/mpris.js +++ b/plugins/shortcuts/mpris.js @@ -40,11 +40,11 @@ function registerMPRIS(win) { if (manuallySwitchingStatus) return; - if (mode == "Repeat off") + if (mode === "Repeat off") currentLoopStatus = "None"; - else if (mode == "Repeat one") + else if (mode === "Repeat one") currentLoopStatus = "Track"; - else if (mode == "Repeat all") + else if (mode === "Repeat all") currentLoopStatus = "Playlist"; player.loopStatus = currentLoopStatus; From d9c51063f4367e083f63802ec291eea3cad88697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Mon, 11 Jul 2022 19:55:16 +0200 Subject: [PATCH 6/8] Add MPRIS volume control Fixes #776. --- plugins/shortcuts/mpris.js | 18 +++++++++++++++++- providers/song-info-front.js | 11 +++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/plugins/shortcuts/mpris.js b/plugins/shortcuts/mpris.js index 49fc8d96..3bb256d0 100644 --- a/plugins/shortcuts/mpris.js +++ b/plugins/shortcuts/mpris.js @@ -19,7 +19,7 @@ function setupMPRIS() { function registerMPRIS(win) { const songControls = getSongControls(win); - const { playPause, next, previous } = songControls; + const { playPause, next, previous, volumeMinus10, volumePlus10 } = songControls; try { const secToMicro = n => Math.round(Number(n) * 1e6); const microToSec = n => Math.round(Number(n) / 1e6); @@ -93,6 +93,22 @@ function registerMPRIS(win) { player.on('seek', seekBy); player.on('position', seekTo); + ipcMain.on('volumeChanged', (_, value) => { + player.volume = value; + }); + player.on('volume', (newVolume) => { + // With keyboard shortcuts we can only change the volume in increments of 10, so round it. + const deltaVolume = Math.round((newVolume - player.volume) / 10); + + if (deltaVolume > 0) { + for (let i = 0; i < deltaVolume; i++) + volumePlus10(); + } else { + for (let i = 0; i < -deltaVolume; i++) + volumeMinus10(); + } + }); + registerCallback(songInfo => { if (player) { const data = { diff --git a/providers/song-info-front.js b/providers/song-info-front.js index 3a704598..121d9cac 100644 --- a/providers/song-info-front.js +++ b/providers/song-info-front.js @@ -23,6 +23,7 @@ module.exports = () => { (is.linux() && config.plugins.isEnabled('shortcuts'))) { setupTimeChangeListener(); setupRepeatChangeListener(); + setupVolumeChangeListener(); } const video = $('video'); // name = "dataloaded" and abit later "dataupdated" @@ -74,3 +75,13 @@ function setupRepeatChangeListener() { // Emit the initial value as well; as it's persistent between launches. ipcRenderer.send('repeatChanged', $('#right-controls .repeat').title); } + +function setupVolumeChangeListener() { + const volumeObserver = new MutationObserver(mutations => { + ipcRenderer.send('volumeChanged', mutations[0].target.value); + }); + volumeObserver.observe($('#right-controls .volume-slider'), { attributeFilter: ["value"] }); + + // Emit the initial value as well; as it's persistent between launches. + ipcRenderer.send('volumeChanged', $('#right-controls .volume-slider').value); +} From dfba3d9c2d9aba0751150ca1558010267b81252e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Mon, 11 Jul 2022 20:20:13 +0200 Subject: [PATCH 7/8] Support precise volume changes in MPRIS when possible --- plugins/precise-volume/front.js | 26 ++++++++++++++---------- plugins/shortcuts/mpris.js | 36 +++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 0bf3e36d..38a2a60b 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -11,6 +11,7 @@ module.exports = (_options) => { document.addEventListener('apiLoaded', e => { api = e.detail; ipcRenderer.on('changeVolume', (_, toIncrease) => changeVolume(toIncrease)); + ipcRenderer.on('setVolume', (_, value) => setVolume(value)); firstRun(); }, { once: true, passive: true }) }; @@ -163,26 +164,29 @@ function setupSliderObserver() { }); } -/** if (toIncrease = false) then volume decrease */ -function changeVolume(toIncrease) { - // Apply volume change if valid - const steps = Number(options.steps || 1); - api.setVolume(toIncrease ? - Math.min(api.getVolume() + steps, 100) : - Math.max(api.getVolume() - steps, 0)); - +function setVolume(value) { + api.setVolume(value); // Save the new volume - saveVolume(api.getVolume()); + saveVolume(value); // change slider position (important) updateVolumeSlider(); // Change tooltips to new value - setTooltip(options.savedVolume); + setTooltip(value); // Show volume slider showVolumeSlider(); // Show volume HUD - showVolumeHud(options.savedVolume); + showVolumeHud(value); +} + +/** if (toIncrease = false) then volume decrease */ +function changeVolume(toIncrease) { + // Apply volume change if valid + const steps = Number(options.steps || 1); + setVolume(toIncrease ? + Math.min(api.getVolume() + steps, 100) : + Math.max(api.getVolume() - steps, 0)); } function updateVolumeSlider() { diff --git a/plugins/shortcuts/mpris.js b/plugins/shortcuts/mpris.js index 3bb256d0..bf427b58 100644 --- a/plugins/shortcuts/mpris.js +++ b/plugins/shortcuts/mpris.js @@ -2,6 +2,7 @@ const mpris = require("mpris-service"); const { ipcMain } = require("electron"); const registerCallback = require("../../providers/song-info"); const getSongControls = require("../../providers/song-controls"); +const config = require("../../config"); function setupMPRIS() { const player = mpris({ @@ -97,25 +98,30 @@ function registerMPRIS(win) { player.volume = value; }); player.on('volume', (newVolume) => { - // With keyboard shortcuts we can only change the volume in increments of 10, so round it. - const deltaVolume = Math.round((newVolume - player.volume) / 10); - - if (deltaVolume > 0) { - for (let i = 0; i < deltaVolume; i++) - volumePlus10(); + if (config.plugins.isEnabled('precise-volume')) { + // With precise volume we can set the volume to the exact value. + win.webContents.send('setVolume', newVolume) } else { - for (let i = 0; i < -deltaVolume; i++) - volumeMinus10(); + // With keyboard shortcuts we can only change the volume in increments of 10, so round it. + const deltaVolume = Math.round((newVolume - player.volume) / 10); + + if (deltaVolume > 0) { + for (let i = 0; i < deltaVolume; i++) + volumePlus10(); + } else { + for (let i = 0; i < -deltaVolume; i++) + volumeMinus10(); + } } }); - registerCallback(songInfo => { - if (player) { - const data = { - 'mpris:length': secToMicro(songInfo.songDuration), - 'mpris:artUrl': songInfo.imageSrc, - 'xesam:title': songInfo.title, - 'xesam:artist': [songInfo.artist], + registerCallback(songInfo => { + if (player) { + const data = { + 'mpris:length': secToMicro(songInfo.songDuration), + 'mpris:artUrl': songInfo.imageSrc, + 'xesam:title': songInfo.title, + 'xesam:artist': [songInfo.artist], 'mpris:trackid': '/' }; if (songInfo.album) data['xesam:album'] = songInfo.album; From 0f96da9928af71050a8056ec4ab8e354e63cfe91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Thu, 14 Jul 2022 20:59:35 +0200 Subject: [PATCH 8/8] Change volume observer --- providers/song-info-front.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/providers/song-info-front.js b/providers/song-info-front.js index 121d9cac..03cf2957 100644 --- a/providers/song-info-front.js +++ b/providers/song-info-front.js @@ -23,7 +23,7 @@ module.exports = () => { (is.linux() && config.plugins.isEnabled('shortcuts'))) { setupTimeChangeListener(); setupRepeatChangeListener(); - setupVolumeChangeListener(); + setupVolumeChangeListener(apiEvent.detail); } const video = $('video'); // name = "dataloaded" and abit later "dataupdated" @@ -76,12 +76,10 @@ function setupRepeatChangeListener() { ipcRenderer.send('repeatChanged', $('#right-controls .repeat').title); } -function setupVolumeChangeListener() { - const volumeObserver = new MutationObserver(mutations => { - ipcRenderer.send('volumeChanged', mutations[0].target.value); +function setupVolumeChangeListener(api) { + $('video').addEventListener('volumechange', (_) => { + ipcRenderer.send('volumeChanged', api.getVolume()); }); - volumeObserver.observe($('#right-controls .volume-slider'), { attributeFilter: ["value"] }); - // Emit the initial value as well; as it's persistent between launches. - ipcRenderer.send('volumeChanged', $('#right-controls .volume-slider').value); + ipcRenderer.send('volumeChanged', api.getVolume()); }