
Developing unison
In 2021, I created unison. This month, I published version 1.5, which is, for the time being, the last version that will not only be maintenance and bug fixing. In this article, I'm going to reflect on its development, what was interesting, its shortcomings, and why I'm pausing it.
What is unison?
unison is a client for Music Player Daemon (MPD). MPD is a music player server, which can be controlled by any client, through a protocol. unison is one of such clients. I like MPD for my use case. It is running on a Raspberry Pi 4, connected directly to my sound system. I have all my audio files on it, and not say on my main computer, which saves a lot of space. With a client, I can control it from any device. A program such as Snapcast allows playing music from any place. Combining those two servers makes it really powerful and convenient, but it requires two separate clients.
That is the inception of unison: wanting to be able to control MPD from my Windows PC and being able to play music through Snapcast.
Picture the following situation: MPD is playing music to my sound system via my Raspberry Pi, but my computer is in another room. With Snapcast, I can play it through my computer, whether it is headphones or speakers, with a single library and configuration.
I like to control things with my keyboard. Hence, the main focus of unison was to be able to control my music through shortcuts (next, pause, mute, etc.).
To sum it up: unison is a MPD daemon client focused on shortcuts with a Snapcast implementation. Other features were added over time, but that was the initial focus.
Development
Development started in August 2021. For each version, I'll reflect on the technology choices I made and what was implemented.
v1.0
With no single modern UI framework for Windows, I had to settle for something well documented. That’s why I chose WPF: it is quite straightforward and has been there for a long time. I also know of quite a few projects made by friends in WPF, so it was an argument if I ever needed help. WPF is a bit ugly and visually outdated, but it gets the work done. I had an okay visual result in a few hours, so I just settled for it while implementing the basics of the MPD protocol. Remember, it was supposed to be a daemon with absolutely no focus on the interface, so an okay result was more than enough.
Since I was programming in C#, I searched for an implementation of the client library protocol. There was MpcNET. There were multiple versions, but one was maintained: used in Stylophone, an MPD client. I used his version since it was the most up-to-date, and I could see his implementation as an inspiration for mine. It was not the most practical as the updates made by the Stylophone developer were not on a separate repository, so I had to manually integrate the code, with no automatic update option available.
Next up was the daemon part. To my surprise, there was no simple way in WPF to make a taskbar icon. It was a bit shocking since so many apps live there. Thankfully, the NuGet package Hardcodet.NotifyIcon.Wpf was the solution, and I just had to implement it.
As for the Snapcast part, I did the most simple thing: I launched the exe from unison as a child process. I could have done a real implementation, but this was the easiest way, and with a few tweaks to kill the process correctly when needed in every circumstances, it gets the job done.
As for the shortcuts, it was also not standard. It is not available in C# and is a legacy feature. Not shortcuts themselves, but the ability to call them from any context. Thankfully, there are a lot of examples available, but this once again felt like a hack rather than to use standard APIs. For this version, I just hardcoded the shortcuts I needed.
With this, unison was more than feature-complete for my initial needs. I published the first release in September 2021.
First design iteration
Here is the design evolution of unison leading to version 1.0. I learned WPF and its controls at the same time.




Compared to other platforms, what was tricky was having an idea of how it was supposed to look. There is not a single unified design guideline for Windows, and everyone has their own opinion on how it should look. As someone who grew up with Mac platforms (where it is quite the contrary) and had experimented programming for them, this was a bit troubling. But visuals were not the main focus of the app; remember, it was to control my music with shortcuts and play it with Snapcast. Having an interface was almost a side project, because I was interested in exploring the MPD protocol and displaying meaningful information (and also because I did not want to just make something completely ugly).
v1.1
I could have stopped there… But developing unison was fun! Except for a few bug fixes and tweaks, I implemented a feature to copy the information of the current song and its path by double-clicking on the title. This has proven useful to share songs with friends and find exactly where it is located on my Raspberry Pi.
For example:
Don't Lose Touch - Against Me!
Searching For A Former Clarity (2005)
punk/Against Me!/Searching For A Former Clarity/13 Don't Lose Touch.mp3
But the main feature of this release is the implementation of Radio-Browser. It is a collective index of radio stations broadcasting over the internet. There is an API implementation available in this NuGet package, which is quite straightforward.
I find it quite interesting to be able to listen to such different radio stations across the world. However, it would have been nice to have a curated list of radios, because it can be challenging to find a radio that is:
- of good streaming bitrate
- with a good uptime
- interesting to one's own tastes

All in all, after trying regularly, I found quite a few stations that I like and often listen to them.
Another detail was being able to display flags from the radio stations. There are no flag emojis on Windows. For this purpose, I used the NuGet package Emoji.Wpf.
This version was released in October 2021.
v1.2
With this release, I added something that felt crucial for unison: rebindable shortcuts. I put the one that were useful to me first, but that wasn’t going to be enough if I wanted to make its core functions complete. It was just a matter of detecting and registering keys.

I had previously contacted the MpcNET maintainer to ask them if they were keen on making a NuGet package and separate repository for easier integration. It became the case in October 2021, so this release integrates it. Rather than having to update files manually in the project, this made subsequent updates and contributions a lot easier!
I also added some MPD stats by querying the database.

This version was released in April 2022.
v1.3 & v1.3.1
This release had nothing major, except for a few MPD protocol implementations, a few tweaks, and bug fixes. Nothing of interest to talk about here, except that they were released in April and November 2022.
v1.4
As you can see in the protocol documentation, there are filtering options to query songs. However, prior to MpcNET v1.4.0, the filters were only taking account of a simple TAG comparison as (TAG == 'VALUE')
. This was quite limiting, so I made a pull request to expand filters to their complete protocol implementation. It is indeed a great feeling to be able to contribute to an open-source project. This allowed me to create a shuffle feature.
This feature allows querying songs with parameters (song, artist, album, year, genre, directory) with a comparison operator (contains, is, is not). They can be combined, like you can see on the screen below.

There are two options to shuffle songs:
- you can add them to the queue by selecting a determined number of songs,
- or you can enable continuous shuffle which will endlessly add songs to the queue (if unison is running, since it is only client side).
Other than that, I added two features that are expected for any program: an installer setup and an updater.
The installer is made with InnoSetup, which must be the most popular one in the ecosystem. It requires its own script declaration and is quite straightforward.

The update feature comes from Autoupdater.NET and works with an XML file. AutoUpdate will locate this file on a server (in my case, on GitHub) and compare the version number. If the one on the server is higher, a dialog window will open and alert the user that an update is available.

This version was released in December 2022.
v1.5
As with version 1.3, unison 1.5 does not have significant features. Mostly Windows 11 design compatibility, a few fixes and MPD protocol features, plus the obvious updates on the components. I finally decided unison was mature enough to share broadly, because I’ve been using it every day since 2021, and for what it does, it does it okay. I initially wanted to wait for version 2 (implemented all the expected MPD protocol features) before doing that, but at this point, for reasons I’ll explain right after, it will not happen for the foreseeable future.
unison is now featured on the official MPD website with this June 2025 release.

The future
No new version was released for two and a half years. This comes from two main reasons:
- unison works well enough for its core functions,
- I struggle seeing the future of Windows native programming.
My first issue that explains the wide gap between version releases is the interface. The new frameworks are WinUI2 and WinUI3, that both coexist. And the last time I checked, critical features are still missing. There is also .NET MAUI for cross-platform development, but it is not really mature and is not as good as native development. There are a lot of "modern WPF" frameworks (MahApps.Metro, ModernWpf, Avalonia, wpfui, uno), but nothing feels official. The complexity of the ecosystem makes it hard to make a choice and hard to be motivated to invest time in it. With Windows 10, I was hopeful that Microsoft would once and for all unify its frameworks and interfaces, but it has not come close to being the case, and Windows 11 made matters worse.
I became a bit fed up with Microsoft choices. My PC is also not compatible with Windows 11 for reasons that are absolutely not technical, for a machine that is not really old and has quite a modern CPU architecture. My focus of needing a PC with a powerful gaming CPU has also changed, and I do not need it anymore. All those reasons make me want to go back to the Mac ecosystem. It is far from perfect and has its own flaws, but it's all-in-all a more comfortable experience, and I feel that the Apple Silicon architecture really improved the machines and made them more interesting (including price-wise) than a few years back when I switched to Windows.
Switching to the Apple ecosystem would also allow me to write an iPhone app allowing me to control my music and play it through Snapcast, kind of a personal Spotify/Apple Music. As I prefer native development, I would be able to easily make the same backend for both macOS, iPadOS, and iOS. At least, that's the theory I have high hopes for. Perhaps I'll regret it, but if I start making an Apple version of unison, be sure that I'll talk about my experience on this blog.
Features I would have liked to implement
There are a lot of things I would have liked to work on (and that I will perhaps work on for a native macOS version).
To start, a single window interface. It's too much of a hassle to have multiple windows for such a program. I did some work to make them more comfortable, but it still would be better like this. It would also mean implementing MVVM to remove logic dependency to the presence of a specific window. Not hard to do, but mandatory.
A way to have favorite radio stations. As I said before, it can be difficult to find ones you like, so it would be great not to lose track of them. This, however, could cause some issues as a radio can be dereferenced from Radio-Browser or be temporarily unavailable.
A more complete shuffle system. If they were AND/OR operators, it would become a great smart playlist system. And as such, it would be great to be able to load and save those shuffle configurations as such.
Apart from that, the obvious comes to mind: finish the whole MPD implementation. This includes playlists, queue view and management, and library view and management. The idea is to have both a small window and a big window interface that can be easily switched depending on the needs.
Of course, since unison is an open-source project, other people can work on it and implement those features if they'd like. Though I'm not sure that there are enough people using MPD, Windows and having the same usage as me for unison to be used by more than a few people, ever.
unison's source code is available on GitHub.