I’ve been quiet for the past few weeks, with no live streams nor blog posts. Sorry! This was the reason:
That’s right: rich and engaging Stream Deck integration on Linux.
Boatswain is a new app I’ve been working on for the past month that allows controlling Stream Deck devices. It can assign icons and actions to buttons, and execute these actions. Boatswain is on track for it’s first stable release soon.
I just announced this project in a live stream, and made an actually decent and fun “product” presentation using OBS Studio and Boatswain:
You can watch the full stream here, where I talk a bit more about about the app, do a quick tour on its features, and talk about random things about it.
Sprint Towards Deck
I was originally expecting my Ko-Fi goal to be achieved to buy a Stream Deck, but during that time, I’ve found a 50% sale on an original, brand new Stream Deck and couldn’t resist it.
Since it arrived, I’ve been trying to get it to work. There are a couple of apps available, and the authors are true heroes of open source, but sadly I did not find these apps adequate to my usage. I was tempted to write a new app anyway, so I felt that was a good opportunity to do so.
What you see above is the result of precisely 3 mad weeks of coding.
It all began with the implementation of the custom HID protocol that Stream Deck devices use. The protocol itself was already reverse-engineered by other community members, so I just had to implement what I’ve found documented.
Writing the interface was easy with GTK4 and libadwaita, it was actually where I spent the least amount of time. It is trivially easy to write graphical applications with this combination of libraries!
It was certainly a short, intense road, and I’m happy to see how much was achieved in this time.
Preparing the Stack
Right after starting my work on Boatswain, I faced a bug: Boatswain just couldn’t open the Stream Deck device for write access. This left me scratching my head for a good pair of days. The code was just… alright. After digging deeper and deeper, I realized that others who use Stream Deck on Linux document adding a custom rule for Udev to enable user access to Stream Deck.
Clearly, our stack was not ready for these devices.
If you know me well, you know that I am a huge, massive, colossal proponent of “upstream everything”. I do not enjoy the downstream-first approach. And evidently, something in the Linux needed to be fixed to accommodate Stream Deck devices, because adding custom Udev rules to the root system is just not an acceptable experience.
This led me to navigate through the oceans of systemd, and investigate a solution that would allow everyone, everywhere, to use Stream Decks without absolutely any manual configuration.
Thanks to the fantastic orientation of systemd contributors, sending a patch was a breeze, and I’m happy to announce that my contributions were accepted and will be part of the next systemd release!
Long live fixing bugs upstream! \o/
The first release of Boatswain will contain a minimal amount of functionality for it to be useful. I’ve been focusing on the “streaming” use case. So far, the features I’ve been implementing for 1.0 are:
- Backend code to detect Stream Deck devices, open them, upload images to buttons, and change the brightness of the device
- Folders, profiles, and multiactions
- OBS Studio integration: start & stop streaming, start & stop recording, switch to a scene
- Sound player, initially focusing on playing sound effects
- App launching
Very soon I’ll be proposing Boatswain to be included in the GNOME Circle apps, and will publish on Flathub. The Flathub package will be the only supported installation method.
Future additions that I might consider implementing if I’m motivated enough:
- Chat integration with various streaming services (Twitch, YouTube, etc)
- Window management actions through a custom GNOME Shell extension
- More features to OBS Studio integration, such as showing & hiding sources, recording to the replay buffer, etc
- Enhanced sound player with different playlists and MPRIS integration
Of course, if you’re interested in any one of these features, consider contributing directly. I’ll be happy to add actions and features I don’t use as long as there’s someone willing to maintain them.
Internally, Boatswain is architectured to use plugins. However, because I didn’t want to commit to a plugin API just yet, as the domain is still largely unknown to me, all plugins are in-tree. The plugin architecture is more of a API design choice than a feature.
I’d like to thank everyone who has helped me throughout these mad weeks of coding – Jakub Steiner and Sam Hewitt for the icons and design guidance, Emmanuele Bassi for all the contribution, and Bastien Nocera for handholding my systemd contribution. Without your help, I am absolutely positive there wouldn’t be so much progress on this project on such a short amount of time.
If you think this work is valuable, consider supporting me through Ko-Fi. This side project turned out to be an expensive one, both in terms of work hours, and also because Stream Decks are expensive here in southern lands.