Tooth Fairy 2.4 - Battery Status!

I just released a new version of Tooth Fairy with another long time request feature - battery status.

Now you can check the battery level of your bluetooth device with a glance of the icon on the menu bar.

If you like the feature, be sure to turn it on in the preferences.

In case you don’t know. Tooth Fairy is a menu bar tool to help you switching connection of bluetooth devices with just one click or a hotkey. Check it out at Mac App Store

Tooth Fairy 2.3 - A Nerdy Release

Last month, I received an feature requesting email for Tooth Fairy. It’s about an interesting issue of using AirPods.

Normally, when you use AirPods on a mac for output only, they use AAC as active codec.

But if you use AirPods as both input and output, for example using it as mic with Skype or FaceTime, macOS drops the output codec to SCO, which is much worse than AAC.

You can have a try by opening the system preferences’ Sound pane while listening music. The dropping of sound quality is quite noticeable. The dear user of Tooth Fairy avoided it by switching the audio input to the built-in mic every time AirPods were connected. He used a command line tool to achieve it and hoped Tooth Fairy could automate the process.

It’s not something that needed by everyone. Most of us just ignore or bear with it or even don’t notice it at all. But it’s not hard and can make those who do care really happy. So, why not?

In Tooth Fairy 2.3, I added a new mode called “Audio Output Only”. If you enable the mode for a headset device, it will be used as audio output only and the system sticks to the previous input device.

Furthermore, the long time requested feature - running shell scripts after connect/disconnect - is also supported in the 2.3 release. I moved all the these less frequently used options to a separate sheet.

Now Tooth Fairy 2.3 is on App Store. It’s not a big update for everyone. Just hope someone will love it.

Is it possible to write Quick Look plugins in Swift?

Swift has become the first go-to-language whenever I am going to build something on macOS or iOS. Recently, I was trying to write a quick look plugin in Swift but met some problems.

First, the default quick look plugin files generated by Xcode were .c. Swift is compatible with Objective-C and they can interact with each other well. Swift can also handle C API well but it’s not easy to call Swift from .c files. I changed the file extension from .c to .m and got it fixed.

However, the next problem would not be that easy to fix. After I finished the code and tried to run it in qlmanage, qlmanage failed to load my plugin because it was unable to find libswiftCore.dylib. I checked the Build Settings and set Always Embed Swift Standard Libraries to YES so that all the Swift libraries can be copied to the frameworks directory in the plugin. To make the qlmanage find the frameworks, I also set Runpath Search Paths to @load_path/../Frameworks but the libraries were still not loading. I turned on the debug log by running qlmanage -d4 and found @load_path/../Frameworks “being ignored in restricted program because it is a relative path”.

I posted a question in Apple Developer Forums and quickly got an answer with detail. The short answer is “No”.

No.  You could probably make this work but it’s definitely not safe.

The fundamental problem here is the Swift runtime.  Quick Look plug-ins are hosted in a system process and it’s possible that that system process might load multiple plug-ins.  If there are two plug-ins written in Swift, they might have different versions of the Swift runtime and that will not end well.

The reply also suggested two approaches:

  • Eventually Swift will reach ABI stability and be bundled in the system instead of bundled in apps or plug-ins.
  • Moving Quick Look over to use the new plug-ins mechanism based on app extension, which allows plug-ins to run in their own process.

As the replier suggested, I opened an request in Apple Bug Reporter and the problem ID is 32095249 . Have a check if you also interested in it.