# Copyright 2022 (c) Anna Schumaker. """Our Mpris2 Player dbus Object.""" import pathlib from gi.repository import GObject from gi.repository import GLib from .. import path from . import dbus PLAYER_XML = pathlib.Path(__file__).parent / "Player.xml" OBJECT_PATH = "/com/nowheycreamery/emmental" class Player(dbus.Object): """The mpris2 Player dbus object.""" PlaybackStatus = GObject.Property(type=str, default="Stopped") LoopStatus = GObject.Property(type=str, default="None") Rate = GObject.Property(type=float, default=1.0) Shuffle = GObject.Property(type=bool, default=False) Volume = GObject.Property(type=float, default=1.0) Position = GObject.Property(type=float, default=0) MinimumRate = GObject.Property(type=float, default=1.0) MaximumRate = GObject.Property(type=float, default=1.0) CanGoNext = GObject.Property(type=bool, default=False) CanGoPrevious = GObject.Property(type=bool, default=False) CanPlay = GObject.Property(type=bool, default=False) CanPause = GObject.Property(type=bool, default=False) CanSeek = GObject.Property(type=bool, default=False) CanControl = GObject.Property(type=bool, default=True) artist = GObject.Property(type=str) album = GObject.Property(type=str) album_artist = GObject.Property(type=str) album_disc_number = GObject.Property(type=int) title = GObject.Property(type=str) track_number = GObject.Property(type=int) duration = GObject.Property(type=float) trackid = GObject.Property(type=int) file = GObject.Property(type=GObject.TYPE_PYOBJECT) def __init__(self): """Initialize the mpris2 application object.""" super().__init__(xml=PLAYER_XML) def do_notify(self, property: str) -> None: """Notify DBus when tags change.""" match property: case "artist" | "album" | "album-artist" | "album-disc-number" | \ "title" | "track-number" | "duration" | "trackid" | "uri": changed = GLib.Variant("a{sv}", self.Metadata) self.properties_changed({"Metadata": changed}) case "PlaybackStatus": changed = GLib.Variant("s", self.PlaybackStatus) self.properties_changed({property: changed}) case "CanPlay" | "CanPause" | "CanSeek": changed = GLib.Variant("b", self.get_property(property)) self.properties_changed({property: changed}) def seeked(self, newpos: float) -> None: """Notify that the track position has changed.""" args = GLib.Variant.new_tuple(GLib.Variant("x", newpos)) self.dbus.emit_signal(None, dbus.OBJECT_PATH, self.interface.name, "Seeked", args) @GObject.Property def Metadata(self) -> dict: """Metadata for the current Track.""" res = dict() if self.file: trackid = f"{OBJECT_PATH}/{self.trackid}" res["mpris:trackid"] = GLib.Variant("o", trackid) res["mpris:length"] = GLib.Variant("x", self.duration) res["xesam:url"] = GLib.Variant("s", self.file.as_uri()) if len(self.artist) > 0: res["xesam:artist"] = GLib.Variant("as", [self.artist]) if len(self.album) > 0: res["xesam:album"] = GLib.Variant("s", self.album) if len(self.album_artist) > 0: res["xesam:albumArtist"] = GLib.Variant("as", [self.album_artist]) if self.album_disc_number > 0: res["xesam:discNumber"] = GLib.Variant("u", self.album_disc_number) if len(self.title) > 0: res["xesam:title"] = GLib.Variant("s", self.title) if self.track_number > 0: res["xesam:trackNumber"] = GLib.Variant("u", self.track_number) return res @GObject.Signal def Next(self) -> None: """Skip to the next track.""" @GObject.Signal def Previous(self) -> None: """Skip to the previous track.""" @GObject.Signal def Pause(self) -> None: """Pause playback.""" @GObject.Signal def PlayPause(self) -> None: """Toggle playback status.""" @GObject.Signal def Stop(self) -> None: """Stop playback.""" @GObject.Signal def Play(self) -> None: """Start or resume playback.""" @GObject.Signal(arg_types=(float,)) def Seek(self, offset: float) -> None: """Seek forward or backward by the given offset.""" @GObject.Signal(arg_types=(str, float)) def SetPosition(self, trackid: str, position: float) -> None: """Set the current track position in microseconds.""" @GObject.Signal(arg_types=(str,)) def OpenUri(self, uri: str) -> None: """Open the given uri.""" self.emit("OpenPath", path.from_uri(uri)) @GObject.Signal(arg_types=(GObject.TYPE_PYOBJECT,)) def OpenPath(self, filepath: pathlib.Path) -> None: """Open the given path."""