SquishBox has an installation system now!
It's a combination of Python packages for most of the actual software, Debian packages for system-level dependencies and configuration, and a shell script that ties everything together when you first set up a Raspberry Pi. It took a while to arrive at that arrangement, but I think I've finally got the pieces divided up in a way that makes sense.
One of the things that gave me the idea was ttymidi. As a Raspberry Pi/MIDI hacker, I'd played with ttymidi quite a bit over the years, so I checked back in on it while working on the new SquishBox. There had been some updates that made it handle all of the MIDI message types, including SysEx, and I also came across a fork that packaged it for Raspberry Pi as a Debian package and set it up as a systemd service.
That got me thinking: I could use essentially the same model for SquishBox. Let Debian handle the things that belong to the operating system, and let Python packaging handle the things that belong to the application.
Don't Package Everything
Of course, I initially went too far.
My first thought was to make SquishBox and FluidPatcher system-wide Python packages and build Debian packages for them for both armhf and arm64. That turned out to be considerably more complicated than it sounded. Building and maintaining Python packages for multiple architectures brought along a lot of extra machinery, and I wasn't convinced that supporting the older 32-bit Raspberry Pi platforms was worth making the entire packaging system more complicated.
More importantly, I'd already learned during the software redesign that Python virtual environments were a pretty good fit for SquishBox. Why fight that?
So I backed up and simplified things.
The main Debian package became squishbox-system. It doesn't contain the SquishBox Python application itself. Instead, it handles the things that really belong at the system level: dependencies such as python3-evdev and python3-venv, systemd services, default configuration files, and the Raspberry Pi system configuration needed for things like the audio hardware and MIDI interfaces.
The actual SquishBox and FluidPatcher applications live in a Python virtual environment, where they can be installed and upgraded normally with pip.
This also meant I could stop worrying about making the Debian package understand every possible Python dependency. Debian is good at managing Debian packages, and Python is good at managing Python packages. Let each system do its own job.
Let the Package Manager Do Its Job
I ended up making the Debian side somewhat modular as well.
The core system package contains the things SquishBox actually needs to operate. Additional Debian packages can pull in the heavier dependencies required by particular applications — for example, FluidSynth and amsynth for the full audio setup, or the various GStreamer components needed by Trackbox.
I even kept the old browser-based file manager as an optional package. It's no longer part of the default installation because sbcommander, sbedit, and SSH make it unnecessary for most people, but there's no reason to remove the option entirely.
The nice thing about doing this through Debian packages is that I don't have to write a bunch of logic into the installer saying "if this package isn't installed, install it; if this version is old, upgrade it; if this dependency changed, do this other thing..."
I can put the relationships in the package's Depends: field and let apt do what it was designed to do.
That's a recurring theme with this project: SquishBox is a computer, not an appliance. If the operating system already has a good way to solve a problem, I'd rather use it than build my own miniature version of it.
The Installer Isn't the Operating System
That leaves the shell installer with a much more modest job.
Its purpose is basically to bootstrap a fresh Raspberry Pi into a SquishBox environment: install the appropriate Debian packages, create the Python virtual environment, install the SquishBox Python packages, configure the system, create the user's content directories, and set up a few convenient commands.
After that, the individual pieces can largely take care of themselves.
I added aliases such as:
squishbox-python
squishbox-pip
squishbox-launcher
squishbox-start
squishbox-stop
squishbox-status
so that there's an obvious way to interact with the SquishBox environment without having to remember where the virtual environment lives.
That also makes the distinction between the two kinds of updates pretty simple. Changes to system dependencies and configuration can be handled with the normal Debian update mechanism. Changes to the SquishBox Python code — which are likely to happen much more often while I'm developing it — can be installed with something as simple as:
squishbox-pip install -U squishbox
The installer can still be run again when a more substantial system change is needed, but it isn't supposed to be the mechanism for every little software update.
Don't Build an Appliance
There was another small decision in this process that fits the same philosophy.
I initially considered writing my own USB automounting service for SquishBox. But Raspberry Pi OS Desktop already knows how to handle removable media. Why should SquishBox duplicate that?
The same thing happened with the file manager. I had previously used a little web-based file manager, but once sbcommander existed — and USB storage worked normally through the desktop environment — running a web server and exposing a port just to manage files started to seem ridiculous.
The more I worked on the installer, the more I realized that the goal wasn't really to make the SquishBox self-contained. It was to make it fit naturally into the system it's running on.
That means using systemd for services, Debian for system dependencies, apt for system updates, Python packaging for Python software, virtual environments for application isolation, ALSA for MIDI, GStreamer for media playback, and the normal Raspberry Pi OS desktop infrastructure for things like removable storage.
There's a lot less code to maintain when I don't try to replace all of those things.
Finally, Something I Can Ship
This is probably the least glamorous part of the SquishBox project, but it's also one of the most important.
The hardware is working. The Python API is reasonably mature. FluidPatcher is a standalone package. There are several SquishBox applications now, rather than one giant application that happens to do everything. And now there's a reasonably sane way to turn a fresh Raspberry Pi into one of these things and keep it updated afterward.
But getting to this point has also made me think harder about what the SquishBox actually is.
There are already projects that do some very similar things. Zynthian is a great example: it turns a Raspberry Pi into a remarkably complete little musical workstation, with a polished hardware interface around a whole collection of synthesizers, effects, MIDI tools, and other functionality. At the other end of the spectrum, something like the Blokas PiSound is deliberately much more of a building block. It gives you excellent audio/MIDI hardware and a Raspberry Pi environment, and leaves it up to you to decide what instrument you want to build.
I don't think SquishBox needs to be better than either of those things. In fact, I think it's useful that there are multiple approaches to the same basic idea.
But I do think SquishBox has ended up in an interesting place between them.
It's much less of a complete workstation than Zynthian. The interface is intentionally simple, and the software doesn't try to expose every possible synthesis, effects, routing, and sequencing feature through a unified UI. At the same time, it's much more than a bare hardware platform. You don't have to start with a blank Raspberry Pi and build your own instrument from scratch.
Instead, SquishBox provides a small, purposeful set of tools and a consistent interface, and then gets out of the way.
You can run FluidPatcher. You can run amsynth. You can play tracks. You can manage files, edit configuration, connect MIDI devices, or drop into a shell. And if none of those are quite the instrument you want, you can write your own application in Python using the same SquishBox API.
That's the part I've come to like most about it. The SquishBox isn't really a particular synthesizer. It's a way of turning a Raspberry Pi into an instrument without telling you exactly what instrument it has to be.
The hardware gives you a small, immediate interface. The software gives you enough infrastructure that you don't have to reinvent the boring parts. But the actual musical behavior is still yours to decide.
I think that's a useful middle ground: enough of a system that you can sit down and play it, but enough freedom that you can make it your own.
And that's what finally makes me feel like I should actually ship it.
For a long time, SquishBox was basically my Raspberry Pi setup. If I wanted to build another one, I knew what packages to install, which configuration files to edit, which scripts to copy, and which things I'd probably forgotten until something didn't work.
Now I've turned that collection of knowledge into software that someone else can install.
The installation system isn't just the last bit of engineering needed to distribute the project. It forced me to answer a more fundamental question: what am I actually trying to distribute?
And I think I finally know.
Not a synth. Not a DAW. Not a Raspberry Pi development kit.
An instrument platform with just enough structure to make it useful, and just enough freedom to make it yours.