In this development diary, I provide an update on progress made on Koto in the first half of March 2021. This one is a slightly shorter Dev Diary, but solid progress nonetheless!
My goals in the first half of March for Koto were primarily centered around the database and playlist functionality. I am happy to report that significant progress was made on both of those fronts, despite some unexpected hurdles and time sinks not associated with Koto development (like my server infrastructure disappearing overnight thanks to a fire at an OVH datacenter).
All Things Data
Not that kind of data.
The primary goal was to enable reading and writing from the artists, albums, and tracks database tables early on. This would enable us to skip the file indexing during launch if our database existed, enabling us to iterate on Koto faster without the startup time regression from having to index our library every time we launch Koto.
This functionality has been implemented. Building on this, I introduced some fixes to file name parsing, mostly around hyphens (
-) and made the checks when splitting the file name contents more robust.
Alongside the database reading and writing, I spent a considerable amount of time simplifying our pointer references to various structs / classes, such as KotoIndexedTracks within KotoIndexedAlbums, KotoIndexedAlbums in KotoIndexedArtists, and artists related to libraries. This was done via a
KotoCartographer class (since it holds multiple maps, or in GLib’s lingo - HashTables). There is no longer a required association between albums and tracks now, as an example, since all tracks are stored in the
tracks HashTable, opening up the door to easily implementing that support down the road in a different class similar to a KotoIndexedArtist, like a podcast. All of the structs are stored in a HashTable for that respective type, with their key being their UUID (universal unique identifier) that we assign during our file index operation. Lastly a benefit of this is we can more reliably free the memory associated with a struct, like if we deleted a track and wanted to remove the relevant KotoIndexedTrack.
Moving to our KotoCartographer model enabled us to change from referencing the structs, as mentioned earlier, to just the UUIDs. This simplifies our APIs, allowing us to pass just the UUID for the associated struct and perform the consistent sanity checking, such as in our
KotoCartographer struct methods. This change provided the foundation for our KotoPlaylist functionality as well, which I began implementing.
KotoPlaylist functionality went from non-existent to being able to be dynamically generated based on an KotoIndexedAlbum and having a swath of functionality, such as:
- Adding and removing tracks based on the structs or UUIDs.
- Saving these playlists to the database tables, including iterating over each track associated with a KotoPlaylist to save those too!
- Functionality for getting and setting artwork
- Functionality for getting and setting the current position in the playlist.
- Functionality for going to the next or previous track.
In addition to this, I already have playlist shuffling functionality implemented. This implementation guarantees that if you have unplayed tracks, they will be played, and you will not encounter a track in a playlist multiple times during shuffle. To do this, we keep tabs on all the tracks played in a given session for a specific playlist and exclude those from being able to be played again until all the tracks have been exhausted.
To ensure we are able to reliably swap between playlists, we also have a
KotoCurrentPlaylist class with the scope of it being to:
- Enable us to be emit a signal when the current playlist has changed, enabling any listeners to update the UX.
- Providing functionality for getting and setting the current playlist.
I have already hooked up “ephemeral” playlist generation (read: a temporary playlist) when we click on our album artwork in an artist’s album view, which we will be able to leverage in our playback engine.
Speaking of Playback, I started work on our
KotoPlaybackEngine class. I laid out all the immediately desirable functionality in our engine’s header file, ranging from going backwards and forwards in playback to setting our position in the current playing track, setting volume, starting and pausing playback, etc.
The implementation of our
KotoPlaybackEngine is still in its early days. The functions which tie directly into the
KotoCurrentPlaylist and current
KotoPlaylist have been already been implemented though, specifically
During the second half of March, my goals are:
- Hook into GStreamer’s GstPlaybin, GstPipeline, and GstElement functionality to successfully begin the management of playback of audio, ranging from validating forwards / backwards to implementing muting and volume setting, play / pause, and scrubbing through a track.
- Get all that hooked into the UI
- Begin laying down the foundation for graphical playlist management
All development streams happen on my Twitch every Tuesday and Thursday from 12pm-5pm EEST (Eastern European Standard Time). If you miss these streams, I upload all of them to Odysee so be sure to check them out! Since my last Dev Diary, the folks over at Odysee have added me to their 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!