Managing plugins in Logic Pro X with Python (part 1)

25/10/2019

I spend way too much time making sure I add every new plugin I buy to a plugin manager category, else it gets forgotten and lost in the depths of the plugins by manufacturer section - so I decided to see if I could improve this a little with python.

In the first post in this series we look at how the plugin manger works and how this can be used for our benefit.

Intro

This post is part of a series which will end with some C++ and Python code that can scan for plugins and alert us if a plugin hasn't been added to a category. In the process we'll cover the following: I assume that you're already familiar with the plugin manager and how to use it to create categories. If not, I recommend reading this article for an introduction.

This post will explain how the plugin manager stores data, and how we can do something useful with it (no code just yet!).

How the Plugin Manager Works

Logic Pro stores the plugin manager's database in a series of XML files in:
/Users/<user name>/Music/Audio Music Apps/Databases/Tags
In there you'll find a file called MusicApps.properties which lists all the categories which have been created.

There will also be a series of files that look something like:
61756678-73686674-534e5348.tagset
Each of these files represent a single plugin, and the file name contains the hexadecimal values of the plugin's type, subtype, and manufacturer. These values are 4 characters long, uniquely identify a plugin, and are required by the AudioUnit standard.

Each plugin provides these values inside the compiled binary which contains all the other plugin code, and often (but not always) in a human readable Info.plist file. Both of these are contained inside each plugin package in the usual AudioUnit location (ie. /Library/Audio/Plug-Ins/Components).

For the file above, if we convert the hexadecimal values to the corresponding characters using an ASCII table, we get:
aufx-shft-SNSH.tagset
These values correspond to the Pitch Shifter plugin, which is included with Logic Pro.

If we open one of these .tagset files, we'll find something like this:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
            <key>tags</key>
            <dict>
                    <key>Pitch</key>
                    <string>tag</string>
            </dict>
    </dict>
    </plist>
The "Pitch" key here tells us that this plugin is in the pitch category. Inside the dict tag there can be multiple key/string pairs, which would indicate that the plugin is in several different categories.

Using this Data for Something Useful

For me the most useful application of what we've just learned is that I can know create a script which can be scheduled to run everyday, and check that any plugins I've recently installed have been added to a category so that I'll actually find them in a session.

To achieve this I wrote a Python script (with a little C++ help) that did the following:
  1. Scan all the installed plugins just like any DAW might do on startup
  2. Extract the manufacturer, name, and other identifying information from the plugin
  3. Compare this to what is in the plugin manager's tagset files
  4. Is ran everyday by the launchd scheduler in macOS
So how do we implement all this? That's coming in part 2.