Skip to content

Commit ccfe743

Browse files
committed
fix mpris
1 parent f40ed04 commit ccfe743

File tree

5 files changed

+113
-50
lines changed

5 files changed

+113
-50
lines changed

plugins/shortcuts/back.js

+67-50
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
const { globalShortcut } = require("electron");
1+
const { globalShortcut, ipcMain } = require("electron");
22
const is = require("electron-is");
33
const electronLocalshortcut = require("electron-localshortcut");
44
const getSongControls = require("../../providers/song-controls");
55
const { setupMPRIS } = require("./mpris");
66
const registerCallback = require("../../providers/song-info");
77

8-
let player;
9-
108
function _registerGlobalShortcut(webContents, shortcut, action) {
119
globalShortcut.register(shortcut, () => {
1210
action(webContents);
@@ -31,54 +29,8 @@ function registerShortcuts(win, options) {
3129

3230
_registerLocalShortcut(win, "CommandOrControl+F", search);
3331
_registerLocalShortcut(win, "CommandOrControl+L", search);
34-
registerCallback(songInfo => {
35-
if (player) {
36-
player.metadata = {
37-
'mpris:length': songInfo.songDuration * 60 * 1000 * 1000, // In microseconds
38-
'mpris:artUrl': songInfo.imageSrc,
39-
'xesam:title': songInfo.title,
40-
'xesam:artist': songInfo.artist
41-
};
42-
if (!songInfo.isPaused) {
43-
player.playbackStatus = "Playing"
44-
}
45-
}
46-
}
47-
)
4832

49-
if (is.linux()) {
50-
try {
51-
const MPRISPlayer = setupMPRIS();
52-
53-
MPRISPlayer.on("raise", () => {
54-
win.setSkipTaskbar(false);
55-
win.show();
56-
});
57-
MPRISPlayer.on("play", () => {
58-
if (MPRISPlayer.playbackStatus !== 'Playing') {
59-
MPRISPlayer.playbackStatus = 'Playing';
60-
playPause()
61-
}
62-
});
63-
MPRISPlayer.on("pause", () => {
64-
if (MPRISPlayer.playbackStatus !== 'Paused') {
65-
MPRISPlayer.playbackStatus = 'Paused';
66-
playPause()
67-
}
68-
});
69-
MPRISPlayer.on("next", () => {
70-
next()
71-
});
72-
MPRISPlayer.on("previous", () => {
73-
previous()
74-
});
75-
76-
player = MPRISPlayer
77-
78-
} catch (e) {
79-
console.warn("Error in MPRIS", e);
80-
}
81-
}
33+
if (is.linux()) registerMPRIS();
8234

8335
const { global, local } = options;
8436
const shortcutOptions = { global, local };
@@ -106,6 +58,71 @@ function registerShortcuts(win, options) {
10658
}
10759
}
10860
}
61+
function registerMPRIS() {
62+
try {
63+
const secToMicro = n => Math.round(Number(n) * (1000 * 1000));
64+
const microToSec = n => Math.round(Number(n) / 1000 / 1000);
65+
66+
const seekTo = e => win.webContents.send("seekTo", microToSec(e.position));
67+
const seek = o => win.webContents.send("seek", microToSec(o));
68+
69+
const player = setupMPRIS();
70+
71+
const mprisSeek = p => {
72+
player.seeked(p);
73+
}
74+
win.webContents.send("registerOnSeek");
75+
76+
ipcMain.on('seeked', (_, t) => mprisSeek(secToMicro(t)));
77+
78+
let currentSeconds = 0;
79+
ipcMain.on('timeChanged', (_, t) => currentSeconds = t);
80+
81+
player.getPosition = () => secToMicro(currentSeconds)
82+
83+
player.on("raise", () => {
84+
win.setSkipTaskbar(false);
85+
win.show();
86+
});
87+
88+
player.on("play", () => {
89+
if (player.playbackStatus !== 'Playing') {
90+
player.playbackStatus = 'Playing';
91+
playPause()
92+
}
93+
});
94+
player.on("pause", () => {
95+
if (player.playbackStatus !== 'Paused') {
96+
player.playbackStatus = 'Paused';
97+
playPause()
98+
}
99+
});
100+
101+
player.on("playpause", playPause);
102+
player.on("next", next);
103+
player.on("previous", previous);
104+
105+
player.on('seek', seek);
106+
player.on('position', seekTo);
107+
108+
registerCallback(songInfo => {
109+
if (player) {
110+
player.metadata = {
111+
'mpris:length': secToMicro(songInfo.songDuration),
112+
'mpris:artUrl': songInfo.imageSrc,
113+
'xesam:title': songInfo.title,
114+
'xesam:artist': songInfo.artist,
115+
'mpris:trackid': '/'
116+
};;
117+
mprisSeek(secToMicro(songInfo.elapsedSeconds))
118+
player.playbackStatus = songInfo.isPaused ? "Paused" : "Playing"
119+
}
120+
})
121+
122+
} catch (e) {
123+
console.warn("Error in MPRIS", e);
124+
}
125+
}
109126
}
110127

111128
module.exports = registerShortcuts;

preload.js

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const config = require("./config");
66
const { fileExists } = require("./plugins/utils");
77
const setupFrontLogger = require("./providers/front-logger");
88
const setupSongInfo = require("./providers/song-info-front");
9+
const { setupSongControls } = require("./providers/song-controls-front");
910

1011
const plugins = config.plugins.getEnabled();
1112

@@ -45,6 +46,9 @@ document.addEventListener("DOMContentLoaded", () => {
4546
// inject song-info provider
4647
setupSongInfo();
4748

49+
// inject song-controls
50+
setupSongControls();
51+
4852
// inject front logger
4953
setupFrontLogger();
5054

providers/song-controls-front.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const { ipcRenderer } = require("electron");
2+
3+
module.exports.seekTo = seekTo;
4+
function seekTo(t) {
5+
document.querySelector('video').currentTime = t;
6+
}
7+
8+
module.exports.seek = seek;
9+
function seek(o) {
10+
document.querySelector('video').currentTime += o;
11+
}
12+
13+
module.exports.setupSongControls = () => {
14+
ipcRenderer.on("seekTo", async (_, t) => seekTo(t));
15+
ipcRenderer.on("seek", async (_, t) => seek(t));
16+
ipcRenderer.once("registerOnSeek", registerOnSeek)
17+
};
18+
19+
async function registerOnSeek() {
20+
const register = v => v.addEventListener('seeked', () => ipcRenderer.send('seeked', v.currentTime));
21+
let video = document.querySelector('video');
22+
if (video) {
23+
register(video);
24+
}
25+
else {
26+
document.addEventListener('apiLoaded', () => {
27+
register(document.querySelector('video'))
28+
}, { once: true, passive: true })
29+
}
30+
}

providers/song-info-front.js

+10
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,19 @@ ipcRenderer.on("update-song-info", async (_, extractedSongInfo) => {
1111

1212
module.exports = () => {
1313
document.addEventListener('apiLoaded', e => {
14+
setupTimeChangeListener();
15+
1416
document.querySelector('video').addEventListener('loadedmetadata', () => {
1517
const data = e.detail.getPlayerResponse();
1618
ipcRenderer.send("song-info-request", JSON.stringify(data));
1719
});
1820
}, { once: true, passive: true })
1921
};
22+
23+
function setupTimeChangeListener() {
24+
const progressObserver = new MutationObserver(mutations => {
25+
ipcRenderer.send('timeChanged', mutations[0].target.value);
26+
global.songInfo.elapsedSeconds = mutations[0].target.value;
27+
});
28+
progressObserver.observe(document.querySelector('#progress-bar'), { attributeFilter: ["value"] })
29+
}

providers/song-info.js

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const songInfo = {
4545
songDuration: 0,
4646
elapsedSeconds: 0,
4747
url: "",
48+
videoId: "",
4849
};
4950

5051
const handleData = async (responseText, win) => {
@@ -57,6 +58,7 @@ const handleData = async (responseText, win) => {
5758
songInfo.image = await getImage(songInfo.imageSrc);
5859
songInfo.uploadDate = data?.microformat?.microformatDataRenderer?.uploadDate;
5960
songInfo.url = data?.microformat?.microformatDataRenderer?.urlCanonical?.split("&")[0];
61+
songInfo.videoId = data?.videoDetails?.videoId;
6062

6163
// used for options.resumeOnStart
6264
config.set("url", data?.microformat?.microformatDataRenderer?.urlCanonical);

0 commit comments

Comments
 (0)