I think one of the things that makes me different from other people is that it really bothers me when things don’t work correctly. I feel a compulsion to fix things when I see that they’re broken. As I’ve written about in the past, it’s not glamorous work to be a bug fixer. You don’t get the same credit as the original author. But it’s still important work to do and I find it oddly satisfying to put things back into their intended order.
This project started with a bug on my issue tracker for Playerctl that was submitted two years ago. Media players implement a standard protocol on the Linux Desktop called MPRIS which is used for desktop integration. This allows things like the media keys to work, and the desktop to have widgets that allow you to see what song is playing, adjust the volume, and things like that. Playerctl is a utility people use to make their own desktop media player integrations.
When I built the media players affected by the bug and tested them, I found that the bug was in their code and there was nothing I could do on my side to make this work. This makes things a lot more complicated for me. It’s a lot more difficult to understand the inner workings of code that you didn’t write. And since these are established projects, I would have to communicate clearly what needed to be done and make the fixes in the least intrusive way possible so people would accept the fix. There is a whole established etiquite for this within the open source community that needs to be followed in situations like these.
The Broken Library
What the broken media players have in common is that they all have a dependency on a library called mpris-service. I was really lucky here because the owner of the library is someone who I have worked with a lot in the past, Simon (emersion), who is an amazingly talented and responsive open source developer. We met in person about a year ago at a hackathon for Sway.
On his issue tracker, I found all the same issues. Only the very basic features of MPRIS were working and everything else was broken. I was surprised that in the state it was in that the library had gotten such wide adoption. Three major media players were using it despite all the bugs and no progress had been made on the issue for years. I decided to make this my responsibility to help out a friend with a buggy library he didn’t have time to fix (because he’s busy doing other amazing work), for the users of Playerctl, and to improve the Linux Desktop environment.
The Next Broken Library
But it turned out that the bug wasn’t in Simon’s library either. He was using a library for the underlying protocol of MPRIS (called DBus) which simply wasn’t working correctly. It didn’t have support for the data types that are used in MPRIS. And further, both the implementation and the user interface were very bad because it uses platform-specific code written in C++ which makes it less portable across systems. This introduced some build errors in the media players they got around in various hacky ways with their own fork of the library. This definitely needed to be fixed.
The problem though was the DBus library was just not written in such a way that it could ever support MPRIS. Also, the owner seems to have abandoned the project and is no longer taking submissions for fixes. It was then I realized why this hasn’t been fixed. This was going to take a lot of work.
There was some discussion about using an alternative DBus library called dbus-native which had gotten some support by the library users. This path seemed promising because this library was much cleaner than the other DBus library and didn’t require compiling platform-specific C++ code. So I set out to make mpris-service work with this new library.
This didn’t work either. While dbus-native has great internal features, the user interface for creating DBus services did not support some very basic features I needed to implement an MPRIS service, and adding them would require a very extensive rewrite of the top layer of the library.
My Very Own DBus Library
Since I knew this was the only way to get this bug fixed, I did this rewrite and submitted a pull request on the dbus-native project. This pull request remained open for a few months before I realized that it would probably not be merged. This is totally understandable because lots of old code depends on this library that could break with my changes, and reviewing the code is a lot of effort that I couldn’t expect someone to do just to help fix my silly Playerctl bug.
So I decided to fork the library with all my changes and release it as a new library called dbus-next. I also fixed a lot of other bugs and added an integration test suite for all the new functionality that has very good coverage. So now NodeJS finally has a working DBus library. Great.
After that work was done, I then rewrote mpris-service to use my new library and everything worked great.
Media player implementations
Now that the mpris-service library works, people are starting on implementations of MPRIS on media players written in NodeJS and I’m doing my best to help out.
- museeks (#477)
- headset (#255)
- nuclear (#279)
- GPMDP (#3513)
- pocket-casts-linux (#2)
- Poddr (#104)
- Brain.FM Desktop Client (#16)
- auryo (fc4170b)
Now it’s possible for all these media players to support Linux Desktop integration. And when that work is done, I can finally close that Playerctl bug on my issue tracker.