Commit Graph

1266 Commits

Author SHA1 Message Date
Anna Schumaker a5db116d42 audio: Add a 'duration' property to the player
And make sure we are able to watch for changes when tracks are loaded. I
also export it as mpris' mpris:length metadata field.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 2ed34d3465 nowplaying: Add Controls to the Now Playing card
And wire up signals between the Now Playing card and the player.

Implements: #45 (Create a new NowPlaying widget)
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 3157c53423 nowplaying: Add Control buttons
Complete with signals so we'll know when the user wants us to do
something. I also clear the autopause property when the user manually
pauses the player. I use large versions of the play and pause icons from
the Gnome Icon Library for the buttons.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker bf8d7fac1b nowplaying: Create an Autopause Button
This is a PopoverButton that has an autopause.Entry set as the child. I
also override the displayed icon to show the current autopause count.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 7cd77d3aed nowplaying: Create an Autopause Entry
This entry is inspired by the Gtk.SpinButton, but lets us set
placeholder text to display the current autopause value to the user.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 69c59438c2 buttons: Create a SplitButton
This is inspired by the Adw.SplitButton, except it allows for
configuring the secondary button so we can show the current autopause
count.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker b3c2dd25fb buttons: Add a generic Button class
This Button is like a Gtk.Button, except it provides ways to set the
icon-size. I also default to large buttons, since that'll be a good
portion of the users.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 8ec5239acc audio: Add play(), pause(), play_pause(), and stop() functions
These functions are set up to take an unused argument list so they can
be connected to signals directly. I also add a 'playing' property to
track the current state of the playbin and a 'status' property to
translate 'playing' into something mpris understands.

Implements: #7 (Implement MPRIS2 Support)
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 4bced82b1f nowplaying: Add a TagInfo window to the Now Playing card
And bind the Player tag properties to the Now Playing card.

Implements: #45 (Create a new NowPlaying widget)
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker dbc2ec03f2 nowplaying: Add a widget for displaying the current track's tags
And expose properties for setting their values.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker c434f6672e nowplaying: Add the PreferArtistMenu to the ArtistLabel
This menu is used to select between showing the artist or album artist
tag.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 997b1de012 nowplaying: Create a PreferArtistMenu
For selecting between showing the artist or album-artist tag.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 81fdfe66cb nowplaying: Create an ArtistLabel
This label has properties for both Artist and Album Artist, and chooses
which to display based on the prefer-artist property and which tags have
been set.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker c899c15c42 nowplaying: Create a custom Label for displaying tags
This Label supports setting a prefix that is applied to the displayed
string and setting a font size in pixels.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 318b2564ce audio: Add properties for track tags
I set these properties when the bus sends us tag messages, and wire them
up do the mpris2.Player object to notify dbus of their values.

These properties are cleared on both EOS and when a new file is started.
This is to account for the user changing the file mid-playback.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 35d0d815ca audio: Load a track requested by the user
Either through the command line, mpris2, or the open button in the
header.

Implements: #7 (Add MPRIS2 Support)
Implements: #47 (Signal that the track has changed when it actually changes)
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 51096104ce nowplaying: Add a basic Now Playing widget
It doesn't have any children yet, the application will save its size
when the user resizes it.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:58 -04:00
Anna Schumaker 88e4fa4b0c emmental: Add a Player instance to the application
And wire it up to the Header and Mpris.Player so we can apply volume &
replaygain changes as they happen.

Implements: #42 ("Remove global audio.Player instance")
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker d105b15e02 mpris2: Add a Player object
This begins to implement the MediaPlayer2.Player interface. The
properties and signals are there, and I expect to fully implement them
as Emmental development goes on.

Implements: #7 ("Add MPRIS2 Support")
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 93dc476706 audio: Add ReplayGain support to the Gst.Playbin
And add functions for setting and quering the state.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker d134b303ab audio/replaygain: Add a ReplayGain filter
With options for album mode, track mode, and completely disabled.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 47bc858630 audio: Create an audio player GObject
Right now it only supports the volume property, but will be expanded on
as we go forward.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 5d0d522e3c header/open: Create an Open button
This button will be used by the user to open and play a track from the
filesystem.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker bb1d01f951 header: Add ReplayGain selector to the Header
And modify the Application to store ReplayGain settings in the database.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 3f28799437 header/replaygain: Add widgets for selecting ReplayGain mode
This includes a set of Gtk.CheckButtons to choose what ReplayGain mode
to use, and a Gtk.Switch to enable or disable ReplayGain

Implements: #46 ("Create new Volume controls")
Implements: #48 ("Implement Intelligent ReplayGain")
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 081cae4cd8 header: Add new volume control widgets to the Header class
They live in a Gtk.MenuButton with a custom popover box that can have
replaygain options added to it. I also modify the Application to save
the volume when it is changed.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 847c15f64b header/volume: Create new volume control widgets
I can't use a Gtk.VolumeButton because I want to add ReplayGain controls
under the popover menu as well.

Implements: #46 ("Create new Volume controls")
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 4cd1e89493 header/dialog: Create a Settings Dialog
This dialog is used to manually edit the settings in the database. I
bind the properties in such a way that changes are seen instantly.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 50270bd04c header: Add a custom Header class
The header currently contains just the title & subtitle information, but
will be expanded to add volume controls in the next patch.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 236a1e60c2 factory: Create a LabelRow and LabelFactory
The LabelRow is an implementation of the ListRow for the common case of
displaying text to the user. It has some convenience properties for
setting the xalign property and adding the "numeric" class to the Gtk.Label.

The LabelFactory creates LabelRows.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 711fa0da5b factory: Create ListRow and Factory classes
The ListRow class is intended to be used as a base class for displaying
individual Gtk.ListView rows. The implement some helpful functionality
to make it easier to bind list items to child widgets.

The Factory class is designed to create ListRow widgets.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 5d3fb980af entry: Create entries for displaying specific types of values
I implement Integer, Float, and String entries that update their "value"
property based on the user-provided text when the Enter key is pressed.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 47d5f0c0c6 entry: Create an entry for Filtering
This entry provides some helper functionality around a Gtk.SearchEntry
to make filtering lists easier.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 3cf730a5cc format: Add a function for formatting search strings
This takes the input string, casefolds it, and then adds some extra glob
operators to it so we can do a case insensitive substring search by
default.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 6ede296ba6 buttons: Create a PopoverButton
This is a MenuButton that already has a popover attached and a property
for setting the popover child directly.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker a73063a04c emmental: Add our Window to the application
Bind the width and height properties to the settings so they are
restored on startup and bind the fullscreen property to mpris.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 5d1c11e64e window: Add a custom Window class
This window is set up with specific areas for our header, sidebar, now
playing info, and tracklist. It also implements a post_toast() function
so toast notifications can be displayed to the user.

Implements: #44 ("Create a new 3WayPane widget")
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 767f0c1584 mpris2: Add an Mpris2 DBus Connection
And implement the MediaPlayer2 interface on top of it.

Implements: #7 ("Add MPRIS2 Support")
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker b1cd1706ed db/settings: Create a Settings table
This creates a new class to dynamically create GObject Properties, save
them to the database, and make it easy to bind application properties to
specific settings properties.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:42 -04:00
Anna Schumaker 788ca374a8 db: Create a Table base class
This is a Gtk.FilterListModel containing a store.SortedList to store
individual rows in sorted order. I also implemented some convenience
functions to make it easier to add, remove, look up, and filter rows.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 10:41:41 -04:00
Anna Schumaker 651f24672b db: Create a database row Filter
This filter takes a set of primary keys for rows that should be visible
during filtering. Passing None as a value means that all rows are shown.
It also has functions for adding or removing individual rows from the
filter.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 09:26:27 -04:00
Anna Schumaker 2eef68f76f db: Create a database Row base class
This will be shared between settings, playlists, and tracks so we have a
common interface for working with database rows.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 09:26:26 -04:00
Anna Schumaker 8c8135fc23 db: Create a full-featured Connection manager
This inherits from the base Connection manager and adds in reading our
sql script to set up the database. It will also eventually hold pointers
to table objects that we can access directly.

Finally, I add a db property to the Application instance. The db is
connected during the ::startup signal handler, and disconnected during
the ::shutdown signal handler.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 09:26:25 -04:00
Anna Schumaker deb4f3d252 db: Create a base Connection manager
This is a wrapper around the sqlite3.Connection objct that adds some
nice functionality to make working with SQL easier.

I defined the following magic methods:
  * __enter__() to manually begin a transaction
  * __exit__() to commit or rollback a manual transaction
  * __call__() to execute a SQL statement with either positional or
    keyword arguments.

Additionally:
  * I define a "CASEFOLD" function that can be used in queries
    to lowercase unicode text when searching.
  * I set foreign_keys = ON so foreign keys checking is always enabled
  * I provide an executemany() function for running running the same
    statement multiple times with different arguments.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-04-12 09:23:14 -04:00
Anna Schumaker 61fc252172 store: Add a SortedList store
This ListStore implementation uses a key function to keep the items
sorted at all times.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-03-07 11:19:30 -05:00
Anna Schumaker 482a199731 store: Add a Python-based ListStore
This is implemented as an alternative to the Gio.ListStore that uses a
Python list object to hold items.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-03-07 11:19:29 -05:00
Anna Schumaker 4be26c5fee gsetup: Load a Gio Resource with our application icons
We can put all our icons into a single resource bundle that gets loaded
and only exists for our app.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-03-07 11:19:29 -05:00
Anna Schumaker 5cd5d2640d gsetup: Load our application CSS file
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-03-07 11:19:27 -05:00
Anna Schumaker 4072ea97d4 emmental3.py: Start Emmental 3.0
I'm going to put all of the main source code into a single subdirectory
under emmental/ and separate out tests into a separate tests/ directory.

Additionally, I have switched over to pytest for running tests to give
me better output (with color!)

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2023-03-07 11:18:46 -05:00
Anna Schumaker 08ea7342dc Emmental 2.10 AUR Commit
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2022-02-25 13:34:26 -05:00