196 lines
5.3 KiB
TypeScript
196 lines
5.3 KiB
TypeScript
// @ts-ignore
|
|
import * as Player from 'mpris-service';
|
|
|
|
export default class MPRIS {
|
|
/**
|
|
* Private variables for interaction in plugins
|
|
*/
|
|
private _win: any;
|
|
private _app: any;
|
|
|
|
/**
|
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
|
*/
|
|
public name: string = 'MPRIS Service';
|
|
public description: string = 'Handles MPRIS service calls for Linux systems.';
|
|
public version: string = '1.0.0';
|
|
public author: string = 'Core';
|
|
|
|
/**
|
|
* MPRIS Service
|
|
*/
|
|
private mpris: any;
|
|
private mprisEvents: Object = {
|
|
"playpause": "pausePlay",
|
|
"play": "pausePlay",
|
|
"pause": "pausePlay",
|
|
"next": "nextTrack",
|
|
"previous": "previousTrack",
|
|
}
|
|
|
|
/*******************************************************************************************
|
|
* Private Methods
|
|
* ****************************************************************************************/
|
|
|
|
/**
|
|
* Runs a media event
|
|
* @param type - pausePlay, nextTrack, PreviousTrack
|
|
* @private
|
|
*/
|
|
private runMediaEvent(type: string) {
|
|
if (this._win) {
|
|
this._win.webContents.executeJavaScript(`MusicKitInterop.${type}()`).catch(console.error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Blocks non-linux systems from running this plugin
|
|
* @private
|
|
* @decorator
|
|
*/
|
|
private static linuxOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
|
|
if (process.platform !== 'linux') {
|
|
descriptor.value = function () {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Connects to MPRIS Service
|
|
*/
|
|
@MPRIS.linuxOnly
|
|
private connect() {
|
|
this.mpris = Player({
|
|
name: 'Cider',
|
|
identity: 'Cider',
|
|
supportedUriSchemes: [],
|
|
supportedMimeTypes: [],
|
|
supportedInterfaces: ['player']
|
|
});
|
|
this.mpris = Object.assign(this.mpris, {
|
|
canQuit: true,
|
|
canControl: true,
|
|
canPause: true,
|
|
canPlay: true,
|
|
canGoNext: true,
|
|
active: true
|
|
})
|
|
|
|
|
|
const pos_atr = {durationInMillis: 0};
|
|
this.mpris.getPosition = function () {
|
|
const durationInMicro = pos_atr.durationInMillis * 1000;
|
|
const percentage = parseFloat("0") || 0;
|
|
return durationInMicro * percentage;
|
|
}
|
|
|
|
for (const [key, value] of Object.entries(this.mprisEvents)) {
|
|
this.mpris.on(key, () => {
|
|
this.runMediaEvent(value)
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update MPRIS Player Attributes
|
|
*/
|
|
@MPRIS.linuxOnly
|
|
private updatePlayer(attributes: any) {
|
|
|
|
const MetaData = {
|
|
'mpris:trackid': this.mpris.objectPath(`track/${attributes.playParams.id.replace(/[.]+/g, "")}`),
|
|
'mpris:length': attributes.durationInMillis * 1000, // In microseconds
|
|
'mpris:artUrl': (attributes.artwork.url.replace('/{w}x{h}bb', '/512x512bb')).replace('/2000x2000bb', '/35x35bb'),
|
|
'xesam:title': `${attributes.name}`,
|
|
'xesam:album': `${attributes.albumName}`,
|
|
'xesam:artist': [`${attributes.artistName}`,],
|
|
'xesam:genre': attributes.genreNames
|
|
}
|
|
|
|
if (this.mpris.metadata["mpris:trackid"] === MetaData["mpris:trackid"]) {
|
|
return
|
|
}
|
|
|
|
this.mpris.metadata = MetaData
|
|
|
|
}
|
|
|
|
/**
|
|
* Update MPRIS Player State
|
|
* @private
|
|
* @param attributes
|
|
*/
|
|
@MPRIS.linuxOnly
|
|
private updatePlayerState(attributes: any) {
|
|
|
|
let status = 'Stopped';
|
|
if (attributes.status) {
|
|
status = 'Playing';
|
|
} else if (attributes.status === false) {
|
|
status = 'Paused';
|
|
}
|
|
|
|
if (this.mpris.playbackStatus === status) {
|
|
return
|
|
}
|
|
this.mpris.playbackStatus = status;
|
|
}
|
|
|
|
/**
|
|
* Clear state
|
|
* @private
|
|
*/
|
|
private clearState() {
|
|
this.mpris.metadata = {'mpris:trackid': '/org/mpris/MediaPlayer2/TrackList/NoTrack'}
|
|
this.mpris.playbackStatus = 'Stopped';
|
|
}
|
|
|
|
|
|
/*******************************************************************************************
|
|
* Public Methods
|
|
* ****************************************************************************************/
|
|
|
|
/**
|
|
* Runs on plugin load (Currently run on application start)
|
|
*/
|
|
constructor(app: any, _store: any) {
|
|
this._app = app;
|
|
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
|
}
|
|
|
|
/**
|
|
* Runs on app ready
|
|
*/
|
|
onReady(win: any): void {
|
|
this._win = win;
|
|
console.debug(`[Plugin][${this.name}] Ready.`);
|
|
this.connect()
|
|
}
|
|
|
|
/**
|
|
* Runs on app stop
|
|
*/
|
|
onBeforeQuit(): void {
|
|
console.debug(`[Plugin][${this.name}] Stopped.`);
|
|
this.clearState()
|
|
}
|
|
|
|
/**
|
|
* Runs on playback State Change
|
|
* @param attributes Music Attributes (attributes.state = current state)
|
|
*/
|
|
onPlaybackStateDidChange(attributes: object): void {
|
|
this.updatePlayerState(attributes)
|
|
}
|
|
|
|
/**
|
|
* Runs on song change
|
|
* @param attributes Music Attributes
|
|
*/
|
|
onNowPlayingItemDidChange(attributes: object): void {
|
|
this.updatePlayer(attributes);
|
|
}
|
|
|
|
}
|