CI/CD with Bitrise

To make the development process more reliable, I added 4 of the open-source libraries on my GitHub account to Bitrise. For small developers they offer a free service to have automated build pipelines for different platforms, including the Apple ecosystem.

Every commit will now trigger the build pipeline including running the test set (if present, which is currently not the case for part of my code). At least it will trigger in case existing builds fail. The build status will also be presented on the repository page.

There were some dependencies in 2 of the libraries on UIKit, which were causing build issues. The easiest way to solve that turned out to be to remove that dependency, and instead rely on Foundation only. That also means that the swift packages now (at least in theory) support all the Apple platforms: iOS, macOS, watchOS and tvOS.

Rigelian 2.0 is in the mail

I just completed the last bits-and-pieces and posted the new 2.0 version of Rigelian to the AppStore and into the review and approval process.

When I started the development of Rigelian over 2 years ago, I had a couple of things in mind. The main goal was to create the best remote control for mpd-based players. That meant it had to be easy to setup and use (hide configuration where possible), very responsive and great looking.

But next to that I also had technical goals I wanted to achieve. To make sure that extending and supporting the app would be possible with a reasonable amount of effort, I started from scratch using the latest that Apples development eco-system has to offer. That meant Github, swift, RxSwift, cocoapods and later swift package manager, and many of the great open source packages made available by the swift developer community. And bye-bye to Objective-C after almost 30 years (yes, really 30 years, I did my graduation project in computer science back in 1990 using Objective-C on a DEC Ultrix machine).

And I wanted to use the experience I collected over the last 10 years building music remote controls: first MPoD and MPaD, and later the iOS controller for the Bluesound system. I set out to abstract the generic concepts of a music remote control, and create a front-end that could operate completely independent of the player it is controlling. For that I created ConnectorProtocol which defines a generic way to communicate with a player regarding discovery, control, browsing and status updates. The front-end will only know about the protocol, and have zero knowledge of the specific implementation. The first implementation against the protocol was MPDConnector, which has been the basis for Rigelian up-to 1.7.2. And for the last half year, in parallel to further developing the front-end I created a second implementation, this time for kodi: KodiConnector.

And by now this has reached the point that it’s actually possible to perform the main things you want to do with a music remote, and I’m releasing my newborn into the world. I’m very happy with the result where I can maintain a single code base for the front-end, and seamlessly control 2 completely different kinds of players with an app that looks exactly the same in both cases. It will also mean that future improvements like Siri support will be available for both types of players with almost no additional effort. How nice is that.

Kodi support is nearing completion

It’s 2020 and we’re back on extending Rigelian with support for Kodi. Added recently are the ‘play random album’ and ‘play random songs’ functions. Turns out that adding 100 songs in one command is very slow on Kodi, so I had to limit that to 20 songs to keep the performance acceptable.

Also the sortation of albums in various screens is completed.

Remaining now is the ability to play radio stations, and creating a player setting screen and then we’re good to go.

Using c-style defines with Swift Package Manager

When compiling the c-based library libmpdclient, I ran into the problem that it contains some #define statements which have to be set during the build. It took me while to find out how to set those when building the package with Swift Package Manager.

In the end off course the answer was right there in the documentation, but I only found that after watching one of the SPM videos from WWDC 2019.

let package = Package(
     name: "libmpdclient",
     ...
     targets: [
         .target(
             name: "libmpdclient",
             publicHeadersPath: "mpd",
             cSettings: [
                 .define("DEFAULT_HOST", to: "\"localhost\""),
                 .define("DEFAULT_PORT", to: "6600"),
                 .define("ENABLE_TCP", to: "1")
             ]
         )
     ]
 )

Migration to swift package manager

After some initial try-outs with the swift package manager some months ago, I came back to it today to see if it’s possible to run it side-by-side with cocoapods, and gradually migrate packages over.

To begin with, I took out the libmpdclient sources of the mpdconnector framework, and put it into a framework of its own which can be built and included using swift package manager. While doing this I ran into various workspace and build issues, including a point at which the Xcode build server would crash every time I opened the workspace. But in the end I managed to get it all working again.

The framework is called libmpdclient-swift and is available on GitHub (I will gradually move over all sources from bitbucket). It’s based on the latest 0.21.17 version of the original libmpdclient.

Improved cover art assistant

Most Rigelian support questions are related to cover art not displaying correctly. Unfortunately mpd supports cover art retrieval only in recent versions (since 0.21) and the support is still basic.

To let the users get the best cover art under these constraints, the cover art assistant in Rigelian is updated with new functions, like selecting which sources are used, the order in which those sources are accessed, and a description how each of these sources work. Also added is the possibility to clear the cover art cache, forcing that all images are reloaded.

Cover art improvements

Recently version 2.17 of libmpdclient was released which adds support for binary responses, like for the ‘albumart’ command that was added to mpd a while ago. Using this new library version Rigelian can now read local cover art without requiring a http server on the player.

There are still two major limitations with this approach:

  • It only works with mpd version 0.20.10 and up. Many players are still on older versions.
  • It requires that the artwork file is named cover.jpg or cover.png.

Support for this will be in the next Rigelian version, along with some other improvements in the artwork department.

Rigelian on Mac

With macOS Catalina Apple has released catalyst, which makes it possible to port an iPad app to a Mac app with limited effort. A few months ago I had a first look at this, but ran into too many problems. Yesterday I tried again with the latest versions of all frameworks, and was able to get a version running on my Macbook in less than 4 hours.

The main issue I ran into is how to make existing subscriptions work on Mac as well.

Rigelian running fullscreen on my Macbook

Start using SF Symbols

In iOS 13 Apple introduced a set of around 1.500 symbols (icon images) which are easy to use in an app. This makes live, at least on iOS 13, easier so I started migrating to these symbols where possible. To keep it backwards compatible, I’m extending UIImage for every image that I migrate:

 extension UIImage {
     static var play: UIImage {
         if #available(iOS 13.0, *) {
             return UIImage(systemName: "play.fill")!
         } else {
             return UIImage(named: "Play-Small")!
         }
     }
 }

Rigelian users on iOS 13 will notice new, better looking, images appearing over time.