orchard/src/main/plugins/mpris.ts
2022-07-13 15:08:54 +01:00

177 lines
5.5 KiB
TypeScript

// @ts-ignore
import * as Player from 'mpris-service';
export default class mpris {
/**
* Private variables for interaction in plugins
*/
private static utils: any;
/**
* MPRIS Service
*/
private static player: Player.Player;
/**
* 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';
/*******************************************************************************************
* Private Methods
* ****************************************************************************************/
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(utils: any) {
mpris.utils = utils
console.debug(`[Plugin][${mpris.name}] Loading Complete.`);
}
/**
* 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
*/
private static connect() {
const player = Player({
name: 'cider',
identity: 'Cider',
supportedInterfaces: ['player']
});
console.debug(`[${mpris.name}:connect] Successfully connected.`);
const renderer = mpris.utils.getWindow().webContents
const loopType: { [key: string]: number; } = {
'none': 0,
'track': 1,
'playlist': 2,
}
player.on('next', () => mpris.utils.playback.next())
player.on('previous', () => mpris.utils.playback.previous())
player.on('playpause', () => mpris.utils.playback.playPause())
player.on('play', () => mpris.utils.playback.play())
player.on('pause', () => mpris.utils.playback.pause())
player.on('quit', () => mpris.utils.getApp().exit())
player.on('position', (args: { position: any; }) => mpris.utils.playback.seek(args.position / 1000 / 1000))
player.on('loopStatus', (status: string) => renderer.executeJavaScript(`app.mk.repeatMode = ${loopType[status.toLowerCase()]}`))
player.on('shuffle', () => renderer.executeJavaScript('app.mk.shuffleMode = (app.mk.shuffleMode === 0) ? 1 : 0'))
mpris.utils.getIPCMain().on('mpris:playbackTimeDidChange', (event: any, time: number) => {
player.getPosition = () => time;
})
mpris.utils.getIPCMain().on('repeatModeDidChange', (_e: any, mode: number) => {
switch (mode) {
case 0:
player.loopStatus = Player.LOOP_STATUS_NONE;
break;
case 1:
player.loopStatus = Player.LOOP_STATUS_TRACK;
break;
case 2:
player.loopStatus = Player.LOOP_STATUS_PLAYLIST;
break;
}
})
mpris.utils.getIPCMain().on('shuffleModeDidChange', (_e: any, mode: number) => {
player.shuffle = mode === 1
})
mpris.player = player;
}
/**
* Update M.P.R.I.S Player Attributes
*/
private static updateMetaData(attributes: any) {
mpris.player.metadata = {
'mpris:trackid': mpris.player.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
};
}
/*******************************************************************************************
* Public Methods
* ****************************************************************************************/
/**
* Clear state
* @private
*/
private static clearState() {
if (!mpris.player) {
return
}
mpris.player.metadata = {'mpris:trackid': '/org/mpris/MediaPlayer2/TrackList/NoTrack'}
mpris.player.playbackStatus = Player.PLAYBACK_STATUS_STOPPED;
}
/**
* Runs on app ready
*/
@mpris.linuxOnly
onReady(_: any): void {
console.debug(`[${mpris.name}:onReady] Ready.`);
}
/**
* Renderer ready
*/
@mpris.linuxOnly
onRendererReady(): void {
mpris.connect()
}
/**
* Runs on app stop
*/
@mpris.linuxOnly
onBeforeQuit(): void {
console.debug(`[Plugin][${mpris.name}] Stopped.`);
mpris.clearState()
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
@mpris.linuxOnly
onPlaybackStateDidChange(attributes: any): void {
mpris.player.playbackStatus = attributes?.status ? Player.PLAYBACK_STATUS_PLAYING : Player.PLAYBACK_STATUS_PAUSED
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
@mpris.linuxOnly
onNowPlayingItemDidChange(attributes: object): void {
mpris.updateMetaData(attributes);
}
}