#MPRIS and MediaKeys Support
During the first half of April, my primary goal was the introduction of MPRIS and "media keys" support via theorg.gnome.SettingsDaemon.MediaKeys
D-Bus interface. This interface is exposed by GNOME Settings Daemon to enable applications to either grab or release media player key focus, as well as be notified when media keys are pressed in relation to the application, such as:
- Play / Pause (typically a toggle functionality)
- Stop
- Backwards
- Forwards
- Repeat
- Shuffle
XF86XK_AudioRepeat
and XF86XK_AudioRandomPlay
.
Whenever Koto is in focus, we call GNOME Settings Daemon's MediaKeys GrabMediaPlayerKeys
method, which ensures Koto is actively registered with the daemon. Similarly, when we lose focus, we call the ReleaseMediaPlayerKeys
method. We are still able to receive these keyboard shortcuts after releasing or when the application is not in focus, so you can easily play / pause your music, go to the previous or next track, or even enable shuffle right from your keyboard's media keys (assuming you have them).
The bigger item however was the introduction of the Media Player Remote Interfacing Specification (MPRIS) support. While the primary focus of this support was ensuring Budgie's Raven is able to generate MPRIS controls for Koto, it can actually apply to and support any desktop environment or software which acts as the MPRIS D-Bus "client", with Koto being the MPRIS D-Bus "server".
As you can see from the image above, MPRIS support is now implemented in Koto. We are not providing 100% coverage of the specification, for example we are not actively supporting "TrackList" for recently played or upcoming tracks, nor do we support the "Playlists" part of the specification yet, however all relevant org.mpris.MediaPlayer2
and org.mpris.MediaPlayer2.Player
interfaces necessary for Budgie's Raven support are implemented, such as:
- Going to the previous or next track
- Raising or quitting Koto (quitting can be done via Raven as an example)
- Setting Repeat (referred to as "LoopStatus" in the spec) and Shuffle capabilities
- Toggling playback in the forms of "Pause", "PlayPause", "Play", and "Stop" methods.
#Playlists
In Dev Diary 5, I noted that one of my goals was to start work on graphical playlist management, which I noted was going to push into second half of April. I am happy to report that the playlist functionality is indeed underway. As Carl Sagan once said, "if you wish to make an apple pie from scratch, you must first invent the universe". In our far less grandiose scale, in order to manage or play a playlist (excluding our "temporary" ones we generate when playing an album), you must first be able to create a playlist. To facilitate this, work began on the Create Playlist dialog. While the design of the Create Playlist dialog will change (let us be honest, it is not the prettiest any of us have seen), the general idea for Koto is the majority of dialogs will not be the typical "popup" dialogs, but rather be GtkWidgets that are applied to a GtkStack, overlaid via GtkOverlay on top of our window contents. This provides a few benefits in our use case, such as:- We are able to use functionality which create modal / popup dialogs without having a weird "popup creating a popup" experience, such as when using a file picker from GtkFileChooserNative.
- It enables us to implement more sophisticated multi-step dialog user experiences than what we would likely get from the likes of GtkAssistant
- We can block manipulation of most of the Koto UX, such as playerbar controls, in any possible "dialogs" which may be responsible for changing those widgets on-the-fly.
KotoDialogContainer
that contains a close button for closing the active dialog, as well as a GtkStack so we can treat each dialog as a dedicated page or even series of pages if we want. Our KotoWindow was modified to have its primary layout as the "main child" of the GtkOverlay, with the overlays being the KotoDialogContainer itself. This provides us the benefit of not having to do per-dialog positioning and widget expansion as well, as the entire primary layout can be covered by the KotoDialogContainer itself.
To get started, I implemented the KotoCreatePlaylistDialog you can see in the screenshot above. It is a fairly simple dialog currently, however there are plans on adding some more UX polish as well as some additional functionality I will get into in a moment. It is likely that this dialog will also be used for the editing of an existing playlist as well, so a rename is expected.
The current Create Playlist Dialog is comprised of three parts: a GtkImage for setting the image of a playlist, a GtkEntry for the input of the playlist name, and the GtkButton for creating the playlist.
You can set an image for a playlist in one of two ways:
- Setting the image by drag and dropping a file on top of the "drop target" of the image
- Clicking on the image will spawn a file chooser.
koto_playlist_new
, which dynamically creates a UUID for the playlist, and adds it to our KotoCartographer playlist map before closing the dialog.
From there, a new KotoButton is generated for our Playlist navigation, which takes advantages of a metric ton of work that was done on KotoCartographer to emit "signals" (think of them as events that other parts of the codebase can listen for) for all of our different types, such as:
- Adding or removing Albums
- Adding or removing Artists
- Adding or removing Playlists
- Adding or removing Tracks
- An ability to "favorite" a playlist, so when we implement our Home dashboard it will be pinned there.
- An ability to "share" a playlist. This has no mechanism yet, so it will not likely be included until we have one implemented, but the idea is that once we have a discovery service, you will be able to toggle the sharing of the playlist contents (not the files themselves, mind you) to the service, which you will be able to share with others or be used for recommending you different artists.
- An ability to modify various attributes of the playlist such as the image and name, as well as delete the playlist.
- Whether you click one or more item, we will use a GtkActionBar to present various relevant actions for the items.
- When clicking on one item, you will have the option to play that track specifically, or start playlist playback from that track. Additionally you will have the option to navigate to the track's respective album (if no album, then artist).
- When clicking on one or more items, you will have the option to remove the track(s) from the KotoPlaylist.
- KOTO_PREFERRED_MODEL_TYPE_DEFAULT: This is the default (hence the name) and we will sort by the most recent track added to a playlist first, followed by older tracks.
- KOTO_PREFERRED_MODEL_TYPE_OLDEST_FIRST: This model will sort by oldest tracks added to newest.
- KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ALBUM: This model will alphabetically sort a playlist by album names.
- KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ARTIST: This model will alphabetically sort a playlist by artist name.
- KOTO_PREFERRED_MODEL_TYPE_SORT_BY_TRACK_NAME: This model will alphabetically sort a playlist by track names.
#Upcoming
As I am sure you can tell, there is a lot of work to be done on playlist functionality. So far, our new dedicated KotoPlaylistPage generates the header based on playlist metadata, however the following additional work needs to be done (not in this specific order necessarily):- Implementation of a playlist-metadata signal for KotoPlaylist so we can notify when a playlist has been modified.
- Updating our logic for going to the previous and next tracks to leverage our currently selected model (or default based on the type we set during creation) and base the tracks on that instead.
- Implement the track rendering in the GtkListView.
- Implement the selection handling and GtkActionBar rendering, events, etc. when clicking on one or more tracks.
- Implement helper functions as part of our KotoButton for "click" and touch gesture setup to avoid repetitive GtkEventController / Gesture code.
- Refactoring the album artwork image used in the KotoAlbumView into a generic widget that can be leveraged in our KotoPlaylistPage.
- Implement playlist-removed handling in the KotoNav to delete the button.
- Refactor some of our functionality that listens to the various KotoCartographer events so we do not have a bunch of signal listeners splintered across different files.
- Finish the uncrustify config so I can have a standardized code styling.
- Finish necessary VS Code bits so I can hopefully launch Koto in various modes and stop using GNOME Builder (too buggy for me).
#Streams
All development streams happen on my Twitch every Tuesday and Thursday from 12pm-5pm GMT+3 / EEST (Eastern European Time). Remember the daylight savings time change. If you miss these streams, I upload all of them to Odysee so be sure to check them out! I am part of Odysee's Viewer Rewards Program, so if you have an Odysee account, you can now get a daily watch reward of a bit of LBRY Credits (LBC) when you watch my videos, and I get some too!