/images/gsoc.png

Hey everyone, it’s been more than a month since I last wrote. This part of my GSoC project had to do more with reading and understanding than just coding. We continue from the last where we left off, I had to start with the more challenging issue of providing android integration to Kasts and adding chapter markers. While the latter was pretty easy, the former was something I was dreading from the beginning as I have zero experience with Android programming.
The android platform is HUGE and it was a pretty daunting task at first to get started with, knowing that I have to write production-level code in only a few weeks and on a topic that is so new to me. The first thing I did was to interact with my mentor on what is being expected out of it. So I was tasked with creating a media session for android. Kasts was already ported to android but when there is media content playing on android, there is just no way to control it from outside the app. This is where media sessions come in. They provide a universal way to interact with the underlying audio player. Media sessions are to Android what MPRIS is for Linux. A media session allows an app to expose playback externally and to receive commands in the form of physical buttons pressed (play/pause button on an earpiece or TV remotes or the Google assistant).
The android documentation does a great job in explaining what needs to be done to create a media session, creating an instance of MediaSessionCompat for the basic session (For Kasts we don’t really need the MediaControllerCompat) and then implementing the callbacks (onPause(), onPlay(), etc) to control the playback. In retrospect, this part was confusing me for some reason, what I was failing to understand was that the media session does not manage the media player. The player and the session ought to be different components and should be managed separately.
So I started working on this relatively late, partly because I had a lot of android stuff to read before I could even start with this. In the meantime I started a small android personal project to boost my learning, nothing fancy, just a basic calculator, but it works well and it’s my first android app so that was good. I was able to create a session successfully but for some reason I was not able to show the notification. This is where my mentor Tobias helped me with a very important patch of adding the notification. Once we got that working, I started working on making the session interact with our underlying C++ media player over the JNI. So the way it works is that we have two classes in the android support library to maintain the playback state and metadata, ie. the PlaybackStateCompat and the MediaMetadataCompat. We use an object of the former to describe the media state and of the latter to describe the metadata of the content playing. We send requests from the android server side to the C++ client to do all the playback changes according to the session state and which enables the client to inform the android(java) side of the metadata changes accordingly. It makes sense once you get the hang of it, which clearly it didn’t for me ;)
After some tries, it started working fine. The client and the server would remain in sync and the metadata would be preserved according to the state so that would turn out to be fine. There were some features that could not be completed like Seeking which I plan on finishing after GSoC.
Now the last issue on the list was adding the podcast chapter markers. Chapter marks are clickable points used to break an audio/video into sections and they let users jump to a specific time of the media. I used the podlove simple chapters, a formal to extend Atom and RSS feeds to define chapter structures. The task was accomplished by first fetching everything that represents a chapter and adding it to the database with their title, name, start time, link, image and then using a model to list them according to the podcast id.

License

MIT License

Copyright (c) 2023 swaptr

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.