Skip to content

Commit

Permalink
feat: mpris support (#1279)
Browse files Browse the repository at this point in the history
* feat: mpris support

* fix: 修复网页版无法播放

* fix: 修复在 Player.js 里 ipcRenderer 为空时引发的错误

* docs: update README

* docs: update README

Co-authored-by: memorydream <[email protected]>
  • Loading branch information
awalol and memorydream committed Jan 29, 2022
1 parent 5a5fb1f commit d15b58d
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 8 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- 🟥 支持 Last.fm Scrobble
- ☁️ 支持音乐云盘
- ⌨️ 自定义快捷键和全局快捷键
- 🎧 支持Mpris
- 🛠 更多特性开发中

## 📦️ 安装
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@
"extract-zip": "^2.0.1",
"howler": "^2.2.3",
"js-cookie": "^2.2.1",
"jsbi": "^4.1.0",
"lodash": "^4.17.20",
"md5": "^2.3.0",
"mpris-service": "^2.1.2",
"music-metadata": "^7.5.3",
"node-vibrant": "^3.1.6",
"nprogress": "^0.2.0",
Expand All @@ -69,7 +71,8 @@
"vue-i18n": "^8.22.0",
"vue-router": "^3.4.3",
"vue-slider-component": "^3.2.5",
"vuex": "^3.4.0"
"vuex": "^3.4.0",
"x11": "^2.3.0"
},
"devDependencies": {
"@types/node": "^17.0.0",
Expand Down
15 changes: 15 additions & 0 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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}`);
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/electron/ipcRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,8 @@ export function ipcRenderer(vueInstance) {
value,
});
});

ipcRenderer.on('setPosition', (event, position) => {
player._howler.seek(position);
});
}
62 changes: 62 additions & 0 deletions src/electron/mpris.js
Original file line number Diff line number Diff line change
@@ -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;
});
}
22 changes: 19 additions & 3 deletions src/utils/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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,
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/utils/platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
4 changes: 4 additions & 0 deletions vue.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ module.exports = {
args[0]['IS_ELECTRON'] = true;
return args;
});
config.resolve.alias.set(
'jsbi',
path.join(__dirname, 'node_modules/jsbi/dist/jsbi-cjs.js')
);
},
// 渲染线程的配置文件
chainWebpackRendererProcess: config => {
Expand Down
Loading

0 comments on commit d15b58d

Please sign in to comment.