# Copyright 2022 (c) Anna Schumaker """Easily work with our underlying sqlite3 database.""" import pathlib from gi.repository import GObject from typing import Generator from . import albums from . import artists from . import connection from . import decades from . import genres from . import libraries from . import playlist from . import media from . import playlists from . import settings from . import table from . import tracks from . import years SQL_V1_SCRIPT = pathlib.Path(__file__).parent / "emmental.sql" SQL_V2_SCRIPT = pathlib.Path(__file__).parent / "upgrade-v2.sql" SQL_V3_SCRIPT = pathlib.Path(__file__).parent / "upgrade-v3.sql" class Connection(connection.Connection): """Connect to the database.""" active_playlist = GObject.Property(type=playlist.Playlist) loaded = GObject.Property(type=bool, default=False) def __init__(self): """Initialize a sqlite connection.""" super().__init__() self.__check_version() self.settings = settings.Table(self) self.playlists = playlists.Table(self) self.artists = artists.Table(self) self.albums = albums.Table(self, queue=self.artists.queue) self.media = media.Table(self, queue=self.artists.queue) self.genres = genres.Table(self) self.decades = decades.Table(self) self.years = years.Table(self, queue=self.decades.queue) self.libraries = libraries.Table(self) self.tracks = tracks.Table(self) def __check_loaded(self) -> None: for tbl in list(self.playlist_tables()) + [self.tracks]: if tbl.loaded is False: return self.loaded = True def __check_version(self) -> None: user_version = self("PRAGMA user_version").fetchone()["user_version"] match user_version: case 0: self.executescript(SQL_V1_SCRIPT) self.executescript(SQL_V2_SCRIPT) self.executescript(SQL_V3_SCRIPT) case 1: self.executescript(SQL_V2_SCRIPT) self.executescript(SQL_V3_SCRIPT) case 2: self.executescript(SQL_V3_SCRIPT) case 3: pass case _: raise Exception(f"Unsupported data version: {user_version}") def close(self) -> None: """Close the database connection.""" self.settings.stop() for tbl in self.playlist_tables(): tbl.stop() self.tracks.stop() super().close() def filter(self, glob: str) -> None: """Filter the playlist tables.""" for tbl in self.playlist_tables(): tbl.filter(glob) def load(self) -> None: """Load the database tables.""" self.settings.load() for tbl in self.playlist_tables(): tbl.load() self.tracks.load() def playlist_tables(self) -> Generator[playlist.Table, None, None]: """Iterate over each playlist table.""" for tbl in [self.playlists, self.artists, self.albums, self.media, self.genres, self.decades, self.years, self.libraries]: yield tbl def set_active_playlist(self, plist: playlist.Playlist) -> None: """Set the currently active playlist.""" if self.active_playlist == plist: return if self.active_playlist is not None: self.active_playlist.active = False self.active_playlist = plist if plist is not None: plist.active = True @GObject.Signal(arg_types=(table.Table,)) def table_loaded(self, tbl: table.Table) -> None: """Signal that a table has been loaded.""" tbl.loaded = True self.__check_loaded()