Commit Graph

1334 Commits

Author SHA1 Message Date
Anna Schumaker 1b9458c278 db: Add Track support to Playlist Objects
Playlists use a tracks.TrackidSet to manage a set of trackids
representing the Tracks in this Playlist.

I have two functions for loading tracks: load_tracks() and
reload_tracks(). Calling load_tracks() checks if the tracks have been
loaded first before doing any work, but calling reload_tracks() will
force the Playlist to go to the database to load the latest tracks.

Finally, I add a have-next-track property to the main database
connection. This is set to True whenever the active playlist has one or
more tracks.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-05-10 17:31:33 -04:00
Anna Schumaker 11560d781e db: Add a TrackidSet
The TrackidSet is intened to be used by Playlists to keep track of which
Tracks have been added without much overhead.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-05-10 17:31:33 -04:00
Anna Schumaker ff835832c8 db: Save Track data when deleting
This includes the favorite status, playcount, last played timestamp, and
last started timestamp. These values will be restored if a Track with
the same mbid is created at a later time.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-05-10 17:31:32 -04:00
Anna Schumaker 8a16b4e05f db: Add favorite track accounting
This patch adds extra handling for changing the value of the
Track:favorite property, if the Track is the current track. This lets us
have the Now Playing card bind to the current-favorite property to
update the UI (and have the UI update the Track).

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-05-10 14:42:58 -04:00
Anna Schumaker dc8ccff311 db: Add current track accounting
Tracks now have start(), stop(), and restart() functions that can be
used by the application to update the laststarted, lastplayed,
playcount, active, and restarted properties.

The track Table implements their half of these functions in addition to
a mark_path_active() function so opening Emmental with a filepath can
update the current track before the database is loaded. The Table also
adjusts the necessary system playlists when tracks are marked as played.

Finally, the Table now has have-current-track and current-track
properties that can be wired up to the Now Playing card.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-05-10 14:42:58 -04:00
Anna Schumaker 08687882a3 db: Add a Track Table
The Track Table does all the work for saving, loading, and managing
Track objects. I also create a SQLite View to link tracks to their
associated artists, albums, and mediums.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-05-10 14:42:57 -04:00
Anna Schumaker 24cb87d298 db: Add a Track object
The Track object represents a single track in the Library along with all
their corresponding metadata.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:09:08 -04:00
Anna Schumaker afb599dcf4 audio: Add Track support to the tagger
I extract the artist, length, mbid, mtime, tracknumber, and title from
the tags to use when constructing Tracks.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:09:08 -04:00
Anna Schumaker 2c629c887c audio: Notify when playback is almost done
The application can use this to pre-load the next track for gapless
playback.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:09:08 -04:00
Anna Schumaker 4be92c7326 audio: Calculate the play time for the current track
I am going to use this to determine if a track has been played or not.
Gstreamer resets the clock when seeking, so I do some extra work to save
the play time just before seeking and add it back later.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:09:08 -04:00
Anna Schumaker 1c0712e673 sidebar: Add the Library section to the sidebar
And show the directory chooser if the application is started without any
library paths.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:08:10 -04:00
Anna Schumaker 0dcdcd4a68 sidebar: Create a Section for Libraries
This section shows a list of library path playlists. I also add an extra
widget that opens a Gtk.FileDialogso users can add music to their
collections.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:07:07 -04:00
Anna Schumaker 0de8089d59 sidebar: Add the Decade section to the sidebar
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:07:02 -04:00
Anna Schumaker 3ba46db064 sidebar: Create a Section for Decades
This section shows a tree of Decade and Year playlists. I use the
year-alt icon from the gnome icon-library as the section header.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:06:58 -04:00
Anna Schumaker f8494cf47b sidebar: Add the Genre section to the sidebar
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:06:53 -04:00
Anna Schumaker 0f2a5aee9d sidebar: Create a Section for Genres
This section uses the default Row for displaying genre playlists. I use
the theater icon from the gnome icon-library as the section header.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:06:49 -04:00
Anna Schumaker c396839316 sidebar: Add the Artist section to the sidebar
I make sure to save the "show-all" property to the settings so it can be
preserved across sessions.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:06:43 -04:00
Anna Schumaker 2f239bd94d sidebar: Create a Section for Artists
This section shows a tree of Artist and Album playlists. I use the
library-artists icon from the gnome icon-library as the section header,
and the music-artist / music-artist2 icons for the "show all" button to
indicate state..

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:05:18 -04:00
Anna Schumaker 711c04cb29 sidebar: Add the Playlist section to the Sidebar
I created a section Group with this section as the only member for now, and
bind the "selected-playlist" property to the sidebar.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 15:05:17 -04:00
Anna Schumaker d49b033b0d sidebar: Create a Section for Playlists
This section creates PlaylistRows for displaying user and system
playlists.  We also hook into the database playlist table to provide a
way to create new playlists. I add several new icons from the
icon-library to use for the section header and playlists.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker eb0b005c75 sidebar: Create a Section Group
This group manages a list of sections so only one is active at a time.
Additionally, it adjusts the animation property of each section to match
the direction the header moves when activated.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker b316184bf1 sidebar: Create a Section class
This class combines a header with an initially hidden ListView that can
be configured to list our playlists. It also implements
"playlist-activated" and "playlist-selected" signals to signal user
interaction.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 976f465cec sidebar: Create a TreeRow
The TreeRow is a factory.TreeRow configured for binding playlists to a
child widget. Individual sections are expected to inherit from this to
set up their section-specific widgets and bind any extra properties.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 70799fa50f sidebar: Create a LibraryRow
This is a preconfigured row for displaying library paths. It includes a
switch to enable & disable the path, buttons for removing and updating a
path, and a progress bar for displaying scan progress.

I use the "update-symbolic" and "stop-sign-large-symbolic" icons from
the gnome icon library for this widget.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker dcd63015b8 sidebar: Create a PlaylistRow
This row is configured for showing user and system playlists. This means
we use a SettableIcon, and EditableTitle, and an extra button for
deleting playlists.  I use the big-x-symbolic icon from the gnome icon
library for deleting playlists.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 0adb0d472b sidebar: Create a Row widget
This is a basic Row widget with an Icon as a prefix widget, and no
postfix widget. You can set the "year" property to set a year value to
the icon text.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker bf4fa68991 sidebar: Create a BaseRow widget
This is intended to be used as a base class for our playlist Row
widgets, and sets up some common variables needed by both.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker b25ca24dc3 sidebar: Create a Header class
This will be used to display different types of playlists in the
sidebar, such as artist or genre. It also has a revealer that shows its
child when the header is active.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 2542a6cbd7 sidebar: Create a Settable Icon widget
This widget allows users to change the displayed image by selecting a
new one from the filesystem.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 0584a2398a sidebar: Create an Icon widget
This is mostly a wrapper around an Adw.Avatar to make it easier to load
images from a file.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 673c6910e9 sidebar: Create an EditableTitle widget
This widget gives users the ability to change the title of the displayed
playlist.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker cdae9541e9 sidebar: Create a PlaylistTitle widget
This widget sets the Title::subtitle property to a nicely formatted
string based on the number set to the 'count' property.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker cd4caf7df8 sidebar: Create row Title widgets
This widget displays a title and subtitle line, with some added styling.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 710f3fba80 factory: Give ListRows an "active" property
And style them so the row is highlighted and the text is bold.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 9d7763a730 factory: Create a TreeRow
The TreeRow is used to display rows from a Gtk.TreeListModel. I adjust
the TreeRow "item" and "child" properties so they still access the
underlying item or child widget instead of the Gtk.TreeRow or
Gtk.TreeExpander.

I also give the TreeRow widget "n-children" and "have-children" properties
which are used to dynamically show or hide the expander arrow when there
aren't any children.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 40c463da81 sidebar: Create a basic Sidebar widget
It only contains a FilterEntry for filtering future playlists. The
application will save its size when resized.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:43 -04:00
Anna Schumaker 5545cb106d db: Give Libraries an idle Tagger
This uses a combination of an Idle Queue, ReaddirThread, and tagger
Thread to scan a directory path and tag the audio files found within. I
do this by adding a scan() function to each Library object to begin
scanning (if not already running).

Libraries also have a stop() function to cancel any pending idle tasks
and stop any running threads. The Library table makes sure to stop each
Library object during shutdown so we don't leave any hanging threads.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:17 -04:00
Anna Schumaker 6131640e25 db: Create a tagger Thread
This Thread uses the audio.tagger.tag_file() function to find the tags
for a specific file without hanging the UI. There may be cases where we
have an Artist MBID but not the matching Artist name. When this happens,
I do my best to first check the database and then query the musicbrainz
server.

I take some care to only connect to the database once, and to close the
connection when the thread exits.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 14:18:16 -04:00
Anna Schumaker 300ee18569 db: Add a Tagger tool
This tool wraps around a mutagen.File to read tags and translate them
into our database playlists.

Implements: #41 ("Check for new or modified tags during startup")
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker 24c1a31367 db: Add a Library Table
This table allows us to work with Library playlists that are represented
by a filesystem path. The user can manually enable or disable library
paths to prevent their tracks from showing up in the Collection
playlist. Additionally, library paths have an online property to
determine if the library still exists in the filesystem to prevent us
from removing tracks due to a broken NFS mount or symlink.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker b7f1a05967 db: Give Decades knowledge about their Years
Similar to the Artists tree structure. I create a filter on the Year
table for each Decade object and adjust filtering so a Decade remains
visible if one or more years match the query.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker c0edbd9bff db: Add a Year Table
This table allows us to work with Year playlists that are represented
only by the year.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker 0cf5f80eb4 db: Add a Decade Table
This table allows us to work with Decade playlists that can be created
or looked up by an individual year in that decade. I also add a few
custom functions to SQLite to make working with decades easier.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker 2dc5d9ed0a db: Add a Genre Table
This table allows us to work with Genre playlists.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker aeeee1417a db: Give Artists knowledge about their Media
I also adjust how filtering Artists works so an Artist remains visible
if one of its Media matches the query.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker 87606f8fac db: Give Albums knowledge about their Media
We create a filter on the Media table for each Album object, but
only match Media that have a name set. I also adjust filtering to
display Albums that have a matching Medium.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker 51a13a8a04 db: Add a Media Table
This table represents an individual medium in an album (such as a single
CD). Each medium has an associated album, number, type, and (optional)
title. This means we can have multiple media for a given album as long
as they each have a different number or type.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker 1730b7e92c db: Create a link between Artists and Albums
I use a sql link table to accomplish this so a single album can be added
to multiple album-artists. Additionally, I set up a view on Artists and
Albums to make filtering easier without needing to use a complicated
join every time.

Additionally, I use the Playlist.add_children() function to set up a
filter on the Album list model for each Artist's albums.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker 1b38c4d6ec db: Add an Album Table
This table allows us to work with Album playlists that have a name,
album artist, release date, (optional) mbid, and (optional) cover.
Note that we can insert multiple albums with the same name as long as
their mbid, artist, or release date is different.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00
Anna Schumaker d3bdaaa063 db: Add an Artist Table
This table allows us to work with Artist playlists that have a name and
(optional) mbid. Note that we can insert multiple artists with the same
name into the database as long as they have different mbids.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:44:34 -04:00