frobar-ng: Fix mpris issues
This commit is contained in:
parent
9916cb0170
commit
24dd070bd9
|
@ -709,6 +709,39 @@ class MprisProvider(MirrorProvider):
|
|||
"mpv": "",
|
||||
}
|
||||
|
||||
async def run(self) -> None:
|
||||
await super().run()
|
||||
self.status = self.sectionType(parent=self.module, color=self.color)
|
||||
self.album = self.sectionType(parent=self.module, color=self.color)
|
||||
self.artist = self.sectionType(parent=self.module, color=self.color)
|
||||
self.title = self.sectionType(parent=self.module, color=self.color)
|
||||
|
||||
self.manager = gi.repository.Playerctl.PlayerManager()
|
||||
self.manager.connect("name-appeared", self.on_name_appeared)
|
||||
self.manager.connect("player-vanished", self.on_player_vanished)
|
||||
|
||||
self.playerctldName = gi.repository.Playerctl.PlayerName()
|
||||
self.playerctldName.name = "playerctld"
|
||||
self.playerctldName.source = gi.repository.Playerctl.Source.DBUS_SESSION
|
||||
|
||||
self.player: gi.repository.Playerctl.Player | None = None
|
||||
self.playing = asyncio.Event()
|
||||
|
||||
for name in self.manager.props.player_names:
|
||||
self.init_player(name)
|
||||
|
||||
self.update_sections()
|
||||
|
||||
while True:
|
||||
await self.playing.wait()
|
||||
self.update_title()
|
||||
if self.player:
|
||||
pos = self.player.props.position
|
||||
rem = 1 - (pos % 1000000) / 1000000
|
||||
await asyncio.sleep(rem)
|
||||
else:
|
||||
self.playing.clear()
|
||||
|
||||
@staticmethod
|
||||
def get(
|
||||
something: gi.overrides.GLib.Variant, key: str, default: typing.Any = None
|
||||
|
@ -725,13 +758,41 @@ class MprisProvider(MirrorProvider):
|
|||
else:
|
||||
return str(datetime.timedelta(microseconds=ms))
|
||||
|
||||
def show_player(self, player_: gi.repository.Playerctl.Player) -> None:
|
||||
player = player_.props.player_name
|
||||
def find_current_player(self) -> None:
|
||||
for name in [self.playerctldName] + self.manager.props.player_names:
|
||||
# TODO Test what happens when playerctld is not available
|
||||
self.player = gi.repository.Playerctl.Player.new_from_name(name)
|
||||
if not self.player.props.can_play:
|
||||
continue
|
||||
break
|
||||
else:
|
||||
self.player = None
|
||||
|
||||
def update_sections(self) -> None:
|
||||
self.find_current_player()
|
||||
|
||||
if self.player is None:
|
||||
self.status.setText(None)
|
||||
self.album.setText(None)
|
||||
self.artist.setText(None)
|
||||
self.title.setText(None)
|
||||
self.playing.clear()
|
||||
return
|
||||
|
||||
player = self.player.props.player_name
|
||||
player = self.PROVIDERS.get(player, player)
|
||||
status = self.STATUSES.get(player_.props.playback_status, "?")
|
||||
status = self.STATUSES.get(self.player.props.playback_status, "?")
|
||||
self.status.setText(f"{player} {status}")
|
||||
|
||||
metadata = player_.props.metadata
|
||||
if (
|
||||
self.player.props.playback_status
|
||||
== gi.repository.Playerctl.PlaybackStatus.PLAYING
|
||||
):
|
||||
self.playing.set()
|
||||
else:
|
||||
self.playing.clear()
|
||||
|
||||
metadata = self.player.props.metadata
|
||||
|
||||
album = self.get(metadata, "xesam:album")
|
||||
if album:
|
||||
|
@ -746,8 +807,14 @@ class MprisProvider(MirrorProvider):
|
|||
else:
|
||||
self.artist.setText(None)
|
||||
|
||||
pos = player_.props.position # In µs
|
||||
# FIXME Doesn't increment during play
|
||||
self.update_title()
|
||||
|
||||
def update_title(self) -> None:
|
||||
if self.player is None:
|
||||
return
|
||||
|
||||
metadata = self.player.props.metadata
|
||||
pos = self.player.props.position # In µs
|
||||
text = f" {self.format_us(pos)}"
|
||||
dur = self.get(metadata, "mpris:length")
|
||||
if dur:
|
||||
|
@ -757,38 +824,12 @@ class MprisProvider(MirrorProvider):
|
|||
text += f" {clip(title)}"
|
||||
self.title.setText(text)
|
||||
|
||||
def show_players(
|
||||
self, manager: gi.repository.Playerctl.PlayerManager, exclude: str | None = None
|
||||
) -> None:
|
||||
# FIXME Opening and closing a chromium player, it will stay there (as default),
|
||||
# which is not the behaviour of playerctl somehow
|
||||
for name in manager.props.player_names:
|
||||
if name == exclude: # DEBUG
|
||||
continue
|
||||
player = gi.repository.Playerctl.Player.new_from_name(name)
|
||||
self.show_player(player)
|
||||
break
|
||||
else:
|
||||
self.status.setText(None)
|
||||
self.album.setText(None)
|
||||
self.artist.setText(None)
|
||||
self.title.setText(None)
|
||||
|
||||
def on_player_appear(
|
||||
self,
|
||||
manager: gi.repository.Playerctl.PlayerManager,
|
||||
player: gi.repository.Playerctl.Player,
|
||||
) -> None:
|
||||
log.debug(f"Player appeared: {player.props.player_name}")
|
||||
self.show_player(player)
|
||||
|
||||
def on_player_vanished(
|
||||
self,
|
||||
manager: gi.repository.Playerctl.PlayerManager,
|
||||
player: gi.repository.Playerctl.Player,
|
||||
) -> None:
|
||||
log.debug(f"Player vanished: {player.props.player_name}")
|
||||
self.show_player(player)
|
||||
self.update_sections()
|
||||
|
||||
def on_event(
|
||||
self,
|
||||
|
@ -796,54 +837,25 @@ class MprisProvider(MirrorProvider):
|
|||
_: typing.Any,
|
||||
manager: gi.repository.Playerctl.PlayerManager,
|
||||
) -> None:
|
||||
log.debug(f"Player evented: {player.props.player_name}")
|
||||
self.show_player(player)
|
||||
self.update_sections()
|
||||
|
||||
def init_player(
|
||||
self, manager: gi.repository.Playerctl.PlayerManager, name: str
|
||||
) -> None:
|
||||
def init_player(self, name: gi.repository.Playerctl.PlayerName) -> None:
|
||||
player = gi.repository.Playerctl.Player.new_from_name(name)
|
||||
# All events will cause the active player to change,
|
||||
# so we listen on all events, even if the display won't change
|
||||
player.connect("playback-status", self.on_event, manager)
|
||||
player.connect("loop-status", self.on_event, manager)
|
||||
player.connect("shuffle", self.on_event, manager)
|
||||
player.connect("metadata", self.on_event, manager)
|
||||
player.connect("volume", self.on_event, manager)
|
||||
player.connect("seeked", self.on_event, manager)
|
||||
manager.manage_player(player)
|
||||
player.connect("playback-status", self.on_event, self.manager)
|
||||
player.connect("loop-status", self.on_event, self.manager)
|
||||
player.connect("shuffle", self.on_event, self.manager)
|
||||
player.connect("metadata", self.on_event, self.manager)
|
||||
player.connect("volume", self.on_event, self.manager)
|
||||
player.connect("seeked", self.on_event, self.manager)
|
||||
self.manager.manage_player(player)
|
||||
|
||||
def on_name_appeared(
|
||||
self, manager: gi.repository.Playerctl.PlayerManager, name: str
|
||||
) -> None:
|
||||
log.debug(f"Player name appeared: {name}")
|
||||
self.init_player(manager, name)
|
||||
|
||||
def on_name_vanished(
|
||||
self,
|
||||
manager: gi.repository.Playerctl.PlayerManager,
|
||||
name: str,
|
||||
) -> None:
|
||||
log.debug(f"Player name vanished: {name}")
|
||||
self.show_players(manager, exclude=name)
|
||||
|
||||
async def run(self) -> None:
|
||||
await super().run()
|
||||
self.status = self.sectionType(parent=self.module, color=self.color)
|
||||
self.album = self.sectionType(parent=self.module, color=self.color)
|
||||
self.artist = self.sectionType(parent=self.module, color=self.color)
|
||||
self.title = self.sectionType(parent=self.module, color=self.color)
|
||||
|
||||
manager = gi.repository.Playerctl.PlayerManager()
|
||||
manager.connect("name-appeared", self.on_name_appeared)
|
||||
manager.connect("player-appeared", self.on_player_appear)
|
||||
manager.connect("name-vanished", self.on_name_vanished)
|
||||
manager.connect("player-vanished", self.on_player_vanished)
|
||||
|
||||
for name in manager.props.player_names:
|
||||
self.init_player(manager, name)
|
||||
|
||||
self.show_players(manager)
|
||||
self.init_player(name)
|
||||
self.update_sections()
|
||||
|
||||
|
||||
class AlertingProvider(Provider):
|
||||
|
|
Loading…
Reference in a new issue