qxb3/conf

Custom metadata options for players

Closed this issue · 15 comments

Hi
How would i tweak the code in ~/.config/ags/shared/music.js to set custom metadata (specifically cover art) for certain players?
I have tried adding a if (spotifyPlayer.name == "mpv") { } block with edited variables but this does not work properly, this ought to be a simple edit but I can't seem to get it to work, please could you take a look at this .
Thank you!

const Mpris = await Service.import('mpris')

export const PLAYERS = ['mpv', 'brave']
export const NO_MUSIC = `${App.configDir}/assets/no-music.png`

export const player = Variable()
export const musicStatus = Variable('Stopped')
export const musicThumbnail = Variable(NO_MUSIC)
export const musicThumbnailUrl = Variable(NO_MUSIC)
export const musicTitle = Variable('No Music')
export const musicArtist = Variable('Artist')
export const musicAlbum = Variable('Album')
export const musicVolume = Variable(0)
export const musicPosition = Variable(0)
export const musicLength = Variable(0)

Mpris.connect('changed', () => {
  const spotifyPlayer = Mpris.players.find(player => PLAYERS.includes(player.name))

  let posInterval = null

  if (!spotifyPlayer) {
    musicStatus.value = 'Stopped'
    musicThumbnail.value = NO_MUSIC
    musicThumbnailUrl.value = NO_MUSIC
    musicTitle.value = 'No Music'
    musicArtist.value = 'Artist'
    musicAlbum.value = 'Album'
    musicVolume.value = 0
    musicPosition.value = 0
    musicLength.value = 0

    clearInterval(posInterval)
    posInterval = null
  }
  if (spotifyPlayer.name == "mpv") {                           <------ I tried adding this block
 musicStatus.value = spotifyPlayer.playBackStatus
    musicThumbnail.value = spotifyPlayer.coverPath
    musicThumbnailUrl.value = "CUSTOM PATH"
    musicTitle.value = spotifyPlayer.trackTitle
    musicArtist.value = spotifyPlayer.trackArtists.join(', ') || 'Album'
    musicAlbum.value = spotifyPlayer.trackAlbum
    musicVolume.value = parseFloat(spotifyPlayer.volume)
    musicLength.value = spotifyPlayer.length

    clearInterval(posInterval)
    posInterval = setInterval(() => {
      musicPosition.value = spotifyPlayer.position
    }, 1000)
  }


  spotifyPlayer?.connect('changed', () => {
    player.value = spotifyPlayer

    musicStatus.value = spotifyPlayer.playBackStatus
    musicThumbnail.value = spotifyPlayer.coverPath
    musicThumbnailUrl.value = spotifyPlayer.trackCoverUrl
    musicTitle.value = spotifyPlayer.name
    musicArtist.value = spotifyPlayer.trackArtists.join(', ') || 'Album'
    musicAlbum.value = spotifyPlayer.trackAlbum
    musicVolume.value = parseFloat(spotifyPlayer.volume)
    musicLength.value = spotifyPlayer.length

    clearInterval(posInterval)
    posInterval = setInterval(() => {
      musicPosition.value = spotifyPlayer.position
    }, 1000)
  })


})

export function toggle() {
  if (musicStatus.value === 'Stopped') return

  player.value.playPause()
}

export function play() {
  if (musicStatus.value === 'Stopped') return

  player.value.play()
}

export function pause() {
  if (musicStatus.value === 'Stopped') return

  player.value.stop()
}

export function next() {
  if (musicStatus.value === 'Stopped') return

  player.value.next()
}

export function prev() {
  if (musicStatus.value === 'Stopped') return

  player.value.previous()
}

export function setVolume(volume) {
  if (volume === undefined) throw new Error('"volume" is undefined')

  Utils.exec(`playerctl -p ${PLAYERS} volume ${volume}`)
}

export default {
  player,
  musicStatus,
  musicTitle,
  musicArtist,
  musicAlbum
}

my fault, i didn't really test this with other players and kinda just make it work with one player which is spotify. Im gonna be fixing it in a couple of hours and get back to you.

Also looks like mpv doesn't implement mpris so that will not work, But i might be wrong tho.

@ItsTerm1n4l Its should theoretically now work in the latest commit, I also added an example of how you can set custom properties on other players.

EDIT: I forgot to mention how will this now work.

There can be only one player metadata be exist at a time and the order in which you put the players in the PLAYERS array decides that. So if you have ['spotify', 'firefox', 'brave']. The spotify will be taken priority.

Thank you, I realized that the array order would determine priority, and Im using mpv-mpris to give mpv mpris support, the issue is that mpv-mpris doesnt supply cover art but i can still get the cover art and i have it as a local image file, so I needed a way to display that image whenever mpv is running.
Thanks for the epic rice, it is the only ags config that worked out of the box for me. Good Job

This commit doesn't work for some reason :/

Do you have any errors or something?

No, the bar renders as normal but does not show currently playing data even if there a video is playing.
20240307_15h31m16s_grim

Does the player output something when u log it?

how would i do that?

image

Like this

Ohh. Yes I do get a message:

Gjs-Console-Message: 15:57:05.714: MprisPlayer {
    "bus-name": "org.mpris.MediaPlayer2.brave.instance121648",
    "name": "brave",
    "entry": null,
    "identity": "Brave",
    "metadata": {
        "mpris:artUrl": "file:///tmp/.org.chromium.Chromium.Xlp9RU",
        "mpris:length": 647261000,
        "mpris:trackid": "/com/brave/MediaPlayer2/TrackList/TrackE6396142AEFB1932AD5F496416D71193",
        "xesam:album": "",
        "xesam:artist": [
            "DistroTube"
        ],
        "xesam:title": "Sync Files Across All Your Devices With Syncthing"
    },
    "trackid": "/com/brave/MediaPlayer2/TrackList/TrackE6396142AEFB1932AD5F496416D71193",
    "track-artists": [
        "DistroTube"
    ],
    "track-title": "Sync Files Across All Your Devices With Syncthing",
    "track-album": "",
    "track-cover-url": "file:///tmp/.org.chromium.Chromium.Xlp9RU",
    "cover-path": "/home/david/.cache/ags/media/9119a24ae140db26ca57fef7a3416074aea0b25e",
    "play-back-status": "Paused",
    "can-go-next": false,
    "can-go-prev": false,
    "can-play": true,
    "shuffle-status": null,
    "loop-status": null,
    "length": 647.261,
    "position": 5.730935,
    "volume": 1
}

can you show your code where you set the metadata of this player?

My full code

const MprisService = await Service.import('mpris')

export const PLAYERS = ['brave'/*, 'firefox'*/]
export const NO_MUSIC = `${App.configDir}/assets/no-music.png`

export const musicPlayer = Variable()
export const musicStatus = Variable('Stopped')
export const musicThumbnail = Variable(NO_MUSIC)
export const musicThumbnailUrl = Variable(NO_MUSIC)
export const musicTitle = Variable('No Music')
export const musicArtist = Variable('Artist')
export const musicAlbum = Variable('Album')
export const musicVolume = Variable(0)
export const musicPosition = Variable(0)
export const musicLength = Variable(0)

MprisService.connect('player-changed', () => {
  const player = MprisService.players.sort((a, b) => PLAYERS.indexOf(a.name) - PLAYERS.indexOf(b.name))[0]
console.log(player)
  let posInterval = null

  if (!player) {
    musicStatus.value = 'Stopped'
    musicThumbnail.value = NO_MUSIC
    musicThumbnailUrl.value = NO_MUSIC
    musicTitle.value = 'No Music'
    musicArtist.value = 'Artist'
    musicAlbum.value = 'Album'
    musicVolume.value = 0
    musicPosition.value = 0
    musicLength.value = 0

    clearInterval(posInterval)
    posInterval = null
  }

  player?.connect('changed', () => {
    musicPlayer.value = player

    if (player.name === 'brave') {
      musicStatus.value = player.playBackStatus
      musicThumbnail.value = player.coverPath
      musicThumbnailUrl.value = player.trackCoverUrl
      musicTitle.value = player.trackTitle
      musicArtist.value = player.trackArtists.join(', ') || 'Album'
      musicAlbum.value = player.trackAlbum
      musicVolume.value = parseFloat(player.volume)
      musicLength.value = player.length

      clearInterval(posInterval)
      posInterval = setInterval(() => {
        musicPosition.value = player.position
      }, 1000)
    }

    // if (player.name === 'firefox') {
    //   musicTitle.value = player.trackTitle
    //   musicArtist.value = player.trackArtists.join(', ') || 'Album'
    //   musicPosition.value = 0
    //   musicLength.value = player.length
    // }
  })
})

export function toggle() {
  if (!musicPlayer.value) return

  musicPlayer.value.playPause()
}

export function play() {
  if (musicStatus.value === 'Stopped') return

  musicPlayer.value.play()
}

export function pause() {
  if (musicStatus.value === 'Stopped') return

  musicPlayer.value.stop()
}

export function next() {
  if (musicStatus.value === 'Stopped') return

  musicPlayer.value.next()
}

export function prev() {
  if (musicStatus.value === 'Stopped') return

  musicPlayer.value.previous()
}

export function setVolume(volume) {
  if (volume === undefined) throw new Error('"volume" is undefined')

  Utils.exec(`playerctl -p ${PLAYERS} volume ${volume}`)
}

export default {
  player: musicPlayer,
  musicStatus,
  musicTitle,
  musicArtist,
  musicAlbum
}

Can't replicate, Sorry.

image

Ok.
I figured out the issue. the video has to start after the bar is running, if the bar is started after the video it doesn't find the display the info. with working on the bar and debugging i have to close and restart the bar as ags does not live reload.
Sorry, I didn't notice before.
20240307_16h25m41s_grim

yeah its some weird issue i cant find a solution.