mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 10:11:46 +00:00
Merge pull request #749 from foonathan/master
Support MPRIS loop and volume change
This commit is contained in:
@ -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() {
|
||||
|
||||
@ -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({
|
||||
@ -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);
|
||||
@ -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", () => {
|
||||
@ -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;
|
||||
|
||||
@ -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, "="),
|
||||
|
||||
@ -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"
|
||||
@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user