mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-16 21:28:06 +00:00
feat: mpris support (#1279)
* feat: mpris support * fix: 修复网页版无法播放 * fix: 修复在 Player.js 里 ipcRenderer 为空时引发的错误 * docs: update README * docs: update README Co-authored-by: memorydream <34763046+memorydream@users.noreply.github.com>
This commit is contained in:
parent
5a5fb1f191
commit
d15b58d805
9 changed files with 235 additions and 8 deletions
|
|
@ -14,6 +14,7 @@ import {
|
|||
isLinux,
|
||||
isDevelopment,
|
||||
isCreateTray,
|
||||
isCreateMpris,
|
||||
} from '@/utils/platform';
|
||||
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib';
|
||||
import { startNeteaseMusicApi } from './electron/services';
|
||||
|
|
@ -29,6 +30,7 @@ import { EventEmitter } from 'events';
|
|||
import express from 'express';
|
||||
import expressProxy from 'express-http-proxy';
|
||||
import Store from 'electron-store';
|
||||
import { createMpris } from '@/electron/mpris';
|
||||
const clc = require('cli-color');
|
||||
const log = text => {
|
||||
console.log(`${clc.blueBright('[background.js]')} ${text}`);
|
||||
|
|
@ -113,6 +115,14 @@ class Background {
|
|||
|
||||
// handle app events
|
||||
this.handleAppEvents();
|
||||
|
||||
// disable chromium mpris
|
||||
if (isCreateMpris) {
|
||||
app.commandLine.appendSwitch(
|
||||
'disable-features',
|
||||
'HardwareMediaKeyHandling,MediaSessionService'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async initDevtools() {
|
||||
|
|
@ -362,6 +372,11 @@ class Background {
|
|||
if (this.store.get('settings.enableGlobalShortcut') !== false) {
|
||||
registerGlobalShortcut(this.window, this.store);
|
||||
}
|
||||
|
||||
// create mpris
|
||||
if (isCreateMpris) {
|
||||
createMpris(this.window);
|
||||
}
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
|
|
|
|||
|
|
@ -87,4 +87,8 @@ export function ipcRenderer(vueInstance) {
|
|||
value,
|
||||
});
|
||||
});
|
||||
|
||||
ipcRenderer.on('setPosition', (event, position) => {
|
||||
player._howler.seek(position);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
62
src/electron/mpris.js
Normal file
62
src/electron/mpris.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { ipcMain, app } from 'electron';
|
||||
|
||||
export function createMpris(window) {
|
||||
const Player = require('mpris-service');
|
||||
const renderer = window.webContents;
|
||||
|
||||
const player = Player({
|
||||
name: 'yesplaymusic',
|
||||
identity: 'YesPlayMusic',
|
||||
});
|
||||
|
||||
player.on('next', () => renderer.send('next'));
|
||||
player.on('previous', () => renderer.send('previous'));
|
||||
player.on('playpause', () => renderer.send('play'));
|
||||
player.on('play', () => renderer.send('play'));
|
||||
player.on('pause', () => renderer.send('play'));
|
||||
player.on('quit', () => app.exit());
|
||||
player.on('position', args =>
|
||||
renderer.send('setPosition', args.position / 1000 / 1000)
|
||||
);
|
||||
player.on('loopStatus', () => renderer.send('repeat'));
|
||||
player.on('shuffle', () => renderer.send('shuffle'));
|
||||
|
||||
ipcMain.on('player', (e, { playing }) => {
|
||||
player.playbackStatus = playing
|
||||
? Player.PLAYBACK_STATUS_PLAYING
|
||||
: Player.PLAYBACK_STATUS_PAUSED;
|
||||
});
|
||||
|
||||
ipcMain.on('metadata', (e, metadata) => {
|
||||
player.metadata = {
|
||||
'mpris:trackid': player.objectPath('track/' + metadata.trackId),
|
||||
'mpris:artUrl': metadata.artwork[0].src,
|
||||
'mpris:length': metadata.length * 1000 * 1000,
|
||||
'xesam:title': metadata.title,
|
||||
'xesam:album': metadata.album,
|
||||
'xesam:artist': metadata.artist.split(','),
|
||||
};
|
||||
});
|
||||
|
||||
ipcMain.on('playerCurrentTrackTime', (e, position) => {
|
||||
player.getPosition = () => position * 1000 * 1000;
|
||||
});
|
||||
|
||||
ipcMain.on('switchRepeatMode', (e, mode) => {
|
||||
switch (mode) {
|
||||
case 'off':
|
||||
player.loopStatus = Player.LOOP_STATUS_NONE;
|
||||
break;
|
||||
case 'one':
|
||||
player.loopStatus = Player.LOOP_STATUS_TRACK;
|
||||
break;
|
||||
case 'on':
|
||||
player.loopStatus = Player.LOOP_STATUS_PLAYLIST;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('switchShuffle', (e, shuffle) => {
|
||||
player.shuffle = shuffle;
|
||||
});
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import { personalFM, fmTrash } from '@/api/others';
|
|||
import store from '@/store';
|
||||
import { isAccountLoggedIn } from '@/utils/auth';
|
||||
import { trackUpdateNowPlaying, trackScrobble } from '@/api/lastfm';
|
||||
import { isCreateTray } from '@/utils/platform';
|
||||
import { isCreateMpris, isCreateTray } from '@/utils/platform';
|
||||
|
||||
const electron =
|
||||
process.env.IS_ELECTRON === true ? window.require('electron') : null;
|
||||
|
|
@ -229,6 +229,9 @@ export default class {
|
|||
if (this._howler === null) return;
|
||||
this._progress = this._howler.seek();
|
||||
localStorage.setItem('playerCurrentTrackTime', this._progress);
|
||||
if (isCreateMpris) {
|
||||
ipcRenderer.send('playerCurrentTrackTime', this._progress);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
_getNextTrack() {
|
||||
|
|
@ -478,7 +481,7 @@ export default class {
|
|||
return;
|
||||
}
|
||||
let artists = track.ar.map(a => a.name);
|
||||
navigator.mediaSession.metadata = new window.MediaMetadata({
|
||||
const metadata = {
|
||||
title: track.name,
|
||||
artist: artists.join(','),
|
||||
album: track.al.name,
|
||||
|
|
@ -489,7 +492,14 @@ export default class {
|
|||
sizes: '512x512',
|
||||
},
|
||||
],
|
||||
});
|
||||
length: this.currentTrackDuration,
|
||||
trackId: this.current,
|
||||
};
|
||||
|
||||
navigator.mediaSession.metadata = new window.MediaMetadata(metadata);
|
||||
if (isCreateMpris) {
|
||||
ipcRenderer.send('metadata', metadata);
|
||||
}
|
||||
}
|
||||
_updateMediaSessionPositionState() {
|
||||
if ('mediaSession' in navigator === false) {
|
||||
|
|
@ -799,9 +809,15 @@ export default class {
|
|||
} else {
|
||||
this.repeatMode = 'on';
|
||||
}
|
||||
if (isCreateMpris) {
|
||||
ipcRenderer.send('switchRepeatMode', this.repeatMode);
|
||||
}
|
||||
}
|
||||
switchShuffle() {
|
||||
this.shuffle = !this.shuffle;
|
||||
if (isCreateMpris) {
|
||||
ipcRenderer.send('switchShuffle', this.shuffle);
|
||||
}
|
||||
}
|
||||
switchReversed() {
|
||||
this.reversed = !this.reversed;
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@ export const isLinux = process.platform === 'linux';
|
|||
export const isDevelopment = process.env.NODE_ENV === 'development';
|
||||
|
||||
export const isCreateTray = isWindows || isLinux || isDevelopment;
|
||||
export const isCreateMpris = isLinux;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue