164 lines
6.3 KiB
Python
164 lines
6.3 KiB
Python
# Copyright 2022 (c) Anna Schumaker.
|
|
"""Set up our Application."""
|
|
import pathlib
|
|
from . import gsetup
|
|
from . import audio
|
|
from . import db
|
|
from . import header
|
|
from . import mpris2
|
|
from . import nowplaying
|
|
from . import options
|
|
from . import window
|
|
from gi.repository import GObject
|
|
from gi.repository import GLib
|
|
from gi.repository import Gio
|
|
from gi.repository import Adw
|
|
|
|
MAJOR_VERSION = 3
|
|
MINOR_VERSION = 0
|
|
VERSION_STRING = f"Emmental {MAJOR_VERSION}.{MINOR_VERSION}{gsetup.DEBUG_STR}"
|
|
|
|
|
|
class Application(Adw.Application):
|
|
"""Our custom Adw.Application."""
|
|
|
|
db = GObject.Property(type=db.Connection)
|
|
mpris = GObject.Property(type=mpris2.Connection)
|
|
player = GObject.Property(type=audio.Player)
|
|
win = GObject.Property(type=window.Window)
|
|
|
|
autopause = GObject.Property(type=int, default=-1, minimum=-1, maximum=99)
|
|
|
|
def __init__(self):
|
|
"""Initialize an Application."""
|
|
super().__init__(application_id=gsetup.APPLICATION_ID,
|
|
resource_base_path=gsetup.RESOURCE_PATH,
|
|
flags=Gio.ApplicationFlags.HANDLES_OPEN)
|
|
self.add_main_option_entries([options.Version])
|
|
|
|
def __load_file(self, file: pathlib.Path) -> None:
|
|
self.player.stop()
|
|
self.player.file = file
|
|
self.player.play()
|
|
|
|
def __load_path(self, src: GObject.GObject, path: pathlib.Path) -> None:
|
|
self.__load_file(path)
|
|
|
|
def __set_replaygain(self, *args) -> None:
|
|
enabled = self.db.settings["audio.replaygain.enabled"]
|
|
mode = self.db.settings["audio.replaygain.mode"]
|
|
mode = "track" if mode == "auto" else mode
|
|
self.player.set_replaygain(enabled, mode)
|
|
|
|
def build_header(self) -> header.Header:
|
|
"""Build a new header instance."""
|
|
hdr = header.Header(sql=self.db, title=VERSION_STRING)
|
|
hdr.bind_property("volume", self.player, "volume")
|
|
for (setting, property) in [("audio.volume", "volume"),
|
|
("audio.replaygain.enabled", "rg-enabled"),
|
|
("audio.replaygain.mode", "rg-mode")]:
|
|
self.db.settings.bind_setting(setting, hdr, property)
|
|
|
|
hdr.connect("notify::rg-enabled", self.__set_replaygain)
|
|
hdr.connect("notify::rg-mode", self.__set_replaygain)
|
|
hdr.connect("track-requested", self.__load_path)
|
|
self.__set_replaygain()
|
|
return hdr
|
|
|
|
def build_now_playing(self) -> nowplaying.Card:
|
|
"""Build a new now playing card."""
|
|
playing = nowplaying.Card()
|
|
playing.bind_property("autopause", self, "autopause",
|
|
GObject.BindingFlags.BIDIRECTIONAL)
|
|
for prop in ["title", "album", "artist", "album-artist",
|
|
"playing", "have-track"]:
|
|
self.player.bind_property(prop, playing, prop)
|
|
self.db.settings.bind_setting("now-playing.prefer-artist",
|
|
playing, "prefer-artist")
|
|
|
|
playing.connect("play", self.player.play)
|
|
playing.connect("pause", self.player.pause)
|
|
return playing
|
|
|
|
def build_window(self) -> window.Window:
|
|
"""Build a new window instance."""
|
|
win = window.Window(VERSION_STRING,
|
|
header=self.build_header(),
|
|
now_playing=self.build_now_playing())
|
|
|
|
for (setting, property) in [("window.width", "default-width"),
|
|
("window.height", "default-height"),
|
|
("now-playing.size", "now-playing-size")]:
|
|
self.db.settings.bind_setting(setting, win, property)
|
|
|
|
return win
|
|
|
|
def connect_mpris2(self) -> None:
|
|
"""Connect the mpris2 properties and functions."""
|
|
self.mpris.app.link_property("Fullscreen", self.win, "fullscreened")
|
|
self.mpris.app.connect("Raise", self.win.present)
|
|
self.mpris.app.connect("Quit", self.win.close)
|
|
|
|
for tag in ["artist", "album", "album-artist", "album-disc-number",
|
|
"title", "track-number", "file"]:
|
|
self.player.bind_property(tag, self.mpris.player, tag)
|
|
for (prop, mpris_prop) in [("have-track", "CanPlay"),
|
|
("have-track", "CanPause"),
|
|
("status", "PlaybackStatus")]:
|
|
self.player.bind_property(prop, self.mpris.player, mpris_prop)
|
|
self.mpris.player.link_property("Volume", self.win.header, "volume")
|
|
self.mpris.player.connect("OpenPath", self.__load_path)
|
|
self.mpris.player.connect("Pause", self.player.pause)
|
|
self.mpris.player.connect("Play", self.player.play)
|
|
self.mpris.player.connect("PlayPause", self.player.play_pause)
|
|
self.mpris.player.connect("Stop", self.player.stop)
|
|
|
|
def do_handle_local_options(self, opts: GLib.VariantDict) -> int:
|
|
"""Handle any command line options."""
|
|
if opts.contains("version"):
|
|
print(VERSION_STRING)
|
|
gsetup.print_versions()
|
|
return 0
|
|
return -1
|
|
|
|
def do_startup(self) -> None:
|
|
"""Handle the Adw.Application::startup signal."""
|
|
Adw.Application.do_startup(self)
|
|
self.db = db.Connection()
|
|
self.mpris = mpris2.Connection()
|
|
self.player = audio.Player()
|
|
|
|
gsetup.add_style()
|
|
self.db.load()
|
|
|
|
self.win = self.build_window()
|
|
self.add_window(self.win)
|
|
self.connect_mpris2()
|
|
|
|
def do_activate(self) -> None:
|
|
"""Handle the Adw.Application::activate signal."""
|
|
Adw.Application.do_activate(self)
|
|
self.win.present()
|
|
|
|
def do_open(self, files: list, n_files: int, hint: str) -> None:
|
|
"""Play an audio file passed from the command line."""
|
|
if n_files > 0:
|
|
self.__load_file(pathlib.Path(files[0].get_path()))
|
|
self.activate()
|
|
|
|
def do_shutdown(self) -> None:
|
|
"""Handle the Adw.Application::shutdown signal."""
|
|
Adw.Application.do_shutdown(self)
|
|
if self.player is not None:
|
|
self.player.shutdown()
|
|
self.player = None
|
|
if self.win is not None:
|
|
self.win.close()
|
|
self.win = None
|
|
if self.mpris is not None:
|
|
self.mpris.disconnect()
|
|
self.mpris = None
|
|
if self.db is not None:
|
|
self.db.close()
|
|
self.db = None
|