const dbus = require('dbus-next'); const { info } = require('./render'); const playerName = process.env.BOUNCY_MUSICPLAYER || 'org.mpris.MediaPlayer2.rhythmbox'; const MPRIS_IFACE = 'org.mpris.MediaPlayer2.Player'; const MPRIS_PATH = '/org/mpris/MediaPlayer2'; const PROPERTIES_IFACE = 'org.freedesktop.DBus.Properties'; let artist = ''; let title = ''; let album = ''; let songStart; // timestamps let songEnd; let songPauseSpot; let songPaused; let infoFunc; let warningFunc; let errorFunc; let lastStatus = ''; async function updateMetadata(metadata, props) { try { let artistVariant = metadata.value['xesam:artist']; let titleVariant = metadata.value['xesam:title']; artist = artistVariant ? artistVariant.value[0] : 'unknown'; title = titleVariant ? titleVariant.value : 'unknown'; let durationVariant = metadata.value['mpris:length']; let duration = durationVariant ? durationVariant.value : 0n; let position = (await props.Get(MPRIS_IFACE, 'Position')).value; songStart = Date.now() - Number(position / 1000n); songEnd = songStart + Number(duration / 1000n); if (metadata.value['xesam:album'] && metadata.value['xesam:album'] !== 'Unknown') { album = metadata.value['xesam:album'].value; } else { album = null; } songPaused = (await props.Get(MPRIS_IFACE, 'PlaybackStatus')).value === 'Paused'; if (songPaused) songPauseSpot = Date.now(); } catch(err) { errorFunc(err.message); } } async function setupProps(props) { let metadata = await props.Get(MPRIS_IFACE, 'Metadata'); updateMetadata(metadata, props); props.on('PropertiesChanged', (iface, changed) => { if (changed.hasOwnProperty('PlaybackStatus')) { let status = changed['PlaybackStatus']; if (lastStatus !== status.value) { lastStatus = status.value; info(status.value); updateMetadata(metadata, props); } } if (changed.hasOwnProperty('Metadata')) { metadata = changed['Metadata']; updateMetadata(metadata, props); } }); } async function setup() { try { let bus = dbus.sessionBus(); let obj = await bus.getProxyObject(playerName, MPRIS_PATH); let props = obj.getInterface(PROPERTIES_IFACE); setupProps(props); infoFunc('connected to mpris') } catch(err) { errorFunc(err.message); setTimeout(setup, 5000); } } function init(e, w, i) { errorFunc = e; warningFunc = w; infoFunc = i; setup(); } function getArtist() { return artist; } function getTitle() { return title; } function getAlbum() { return album; } function getSongStart() { return songStart; } function getSongEnd() { return songEnd; } function getSongPauseSpot() { return songPauseSpot; } function getSongPaused() { return songPaused; } module.exports.init = init; module.exports.getArtist = getArtist; module.exports.getTitle = getTitle; module.exports.getAlbum = getAlbum; module.exports.getSongStart = getSongStart; module.exports.getSongEnd = getSongEnd; module.exports.getSongPauseSpot = getSongPauseSpot; module.exports.getSongPaused = getSongPaused;