Skip to content

Commit

Permalink
Merge pull request #749 from foonathan/master
Browse files Browse the repository at this point in the history
Support MPRIS loop and volume change
  • Loading branch information
th-ch authored Aug 21, 2022
2 parents 5b004ac + 0f96da9 commit f0bb328
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 21 deletions.
26 changes: 15 additions & 11 deletions plugins/precise-volume/front.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
};
Expand Down Expand Up @@ -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() {
Expand Down
72 changes: 63 additions & 9 deletions plugins/shortcuts/mpris.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -19,7 +20,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);
Expand All @@ -34,6 +35,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 currentIndex = switches.indexOf(currentLoopStatus);
const targetIndex = switches.indexOf(status);

// Get a delta in the range [0,2]
const delta = (targetIndex - currentIndex + 3) % 3;

manuallySwitchingStatus = true;
songControls.switchRepeat(delta);
manuallySwitchingStatus = false;
})

player.getPosition = () => secToMicro(currentSeconds)

player.on("raise", () => {
Expand All @@ -53,21 +83,45 @@ 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);

player.on('seek', seekBy);
player.on('position', seekTo);

registerCallback(songInfo => {
if (player) {
const data = {
'mpris:length': secToMicro(songInfo.songDuration),
'mpris:artUrl': songInfo.imageSrc,
'xesam:title': songInfo.title,
'xesam:artist': [songInfo.artist],
ipcMain.on('volumeChanged', (_, value) => {
player.volume = value;
});
player.on('volume', (newVolume) => {
if (config.plugins.isEnabled('precise-volume')) {
// With precise volume we can set the volume to the exact value.
win.webContents.send('setVolume', newVolume)
} else {
// 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],
'mpris:trackid': '/'
};
if (songInfo.album) data['xesam:album'] = songInfo.album;
Expand Down
5 changes: 4 additions & 1 deletion providers/song-controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -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, "="),
Expand Down
20 changes: 20 additions & 0 deletions providers/song-info-front.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ module.exports = () => {
if (config.plugins.isEnabled('tuna-obs') ||
(is.linux() && config.plugins.isEnabled('shortcuts'))) {
setupTimeChangeListener();
setupRepeatChangeListener();
setupVolumeChangeListener(apiEvent.detail);
}
const video = $('video');
// name = "dataloaded" and abit later "dataupdated"
Expand Down Expand Up @@ -63,3 +65,21 @@ 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);
}

function setupVolumeChangeListener(api) {
$('video').addEventListener('volumechange', (_) => {
ipcRenderer.send('volumeChanged', api.getVolume());
});
// Emit the initial value as well; as it's persistent between launches.
ipcRenderer.send('volumeChanged', api.getVolume());
}

0 comments on commit f0bb328

Please sign in to comment.