Device Management (in Thorn), and Replacing the Unwanted Auto-Connect

Rosegarden 1.7.x has quite a strange device management system, in which devices (meaning: virtual things within the Rosegarden document, that can be connected to external MIDI hardware ports or software programs) are created “on demand” by Rosegarden itself, connected up automatically, and so on.

Devices in 1.7.x exist in two places – there is a device record within the document in the GUI process (base/Studio), and a mapped device record within the sequencer process. The sequencer's list is actually the authoritative one in 1.7.x, and at various pivotal moments it will contact the GUI and ask it to re-pull the list of devices from the sequencer (RosegardenGUIDoc::syncDevices()). So when, for example, the user adds a device from within the device manager dialog, the add-device command (in the GUI) both adds a device to the studio and pushes a device to the sequencer; the sequencer then requests a re-pull; and the document pulls back the list of devices, hopefully matching the list it already has. When a new device is created at the sequencer side (as happens automatically when a new ALSA client becomes visible, for example), the sequencer requests a re-pull and the document pulls back the list which now contains a device it did not already have.

There are various reasons why this is an awkward design from a code point of view, as well as being godawful to use.

As of right now (SVN rev 10600) the Qt4 port in trunk contains much of this structure, but auto-device-creation on the sequencer has been disabled. We need to go quite a lot further, as various disgusting race conditions and so on still remain. We need to make the document's list of devices the authoritative one, and have the sequencer either refer to that directly (requiring some thought about locking strategies) or pull its own copy (perhaps simpler when re-using at least some existing code). Devices should be added to or removed from the list only when the user asks.

A list of aims from an email of mine some time ago:

On first startup with an empty composition, we should have one output device, connected to some plausible looking MIDI client if there is one. (“Plausible-looking” means that ALSA reports it as a software synth or a hardware port.) You want any more devices in your composition, create (and connect) them yourself.

If a new “plausible-looking” MIDI device appears while we're running, and _if_ an existing device has no current connection at all, connect that to it. Don't create any new devices.

When loading an existing composition, do our best to connect the devices in that document to connections that look the same as the ones they were connected to before it was saved. In the ideal case where all the MIDI devices are exactly the same as they were then, we should be able to do this perfectly…

Make it simpler (somehow!) for the user to see and change connections in the main user interface, without having to use the MIDI device dialog. Adding and removing devices however will involve the dialog.

Generally, even in comparison to the relatively muted behaviour just described, we should err on the side of caution when it comes to automatically connecting things, and we should never create, remove, or disconnect a device without the user specifically requesting it (except when creating the very first device in an empty document).