orchard/src/main/plugins/mpris.ts
2022-01-26 20:48:05 +00:00

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);
}
}