Hi. I want to play an external synth from SC.
I’ve tried several things, newByName with patch connection,
m.connect, with or without a2jmidid, but I miss something.
For example, has alsa sequencer to be enable ?
If you know the tips, thanks for your help.
Hi. I want to play an external synth from SC.
I assume you’re using qjackctl to start up jackd? If so, check the connections window, then the ALSA tab. There should be a visual confirmation that the MIDI device is connected to SuperCollider.
If there isn’t, connect them manually and retry.
Someone else can chime in if I’m wrong here, but my understanding is that SuperCollider does not actually make this connection - it just initializes a connection that ALSA has already made.
Ok thanks ! I’ve tried with Qjackctl and seen the Alsa tab.
MIDIOut.connect(outport: 0, device: 1);
If you specify a device when creating the MIDIOut object, then no connection will be visible in qjackctl. Instead, outgoing messages will include the target device in the ALSA MIDI function call and the message will go only specifically to that device (bypassing the out port that you see in qjackctl, and thus bypassing connections visible in qjackctl). Actually this depends on the output device instance variable (whose name I forget) – I think you can even set this variable after the fact, though that’s likely to be confusing down the road.
If you don’t specify a device at creation time, then the message will go out through the given outport and its eventual destination depends on any connections that you’ve made. It doesn’t matter whether you make the connection by
.connect or by mouse in qjackctl.
Even though the help file states that newByName is “also Linux compatible” it never worked for me on Linux. Wrote about it in this post a while ago. I don’t know why, but you still need to do the alsa connections manually it seems. I wrote this little class extension to MIDIOut (based on some code from @ludo) some weeks ago. Seems to work fine so far, but feedback is welcome of course.
I reread the thread – it was actually “it used to work and then stopped, and maybe pipewire is involved somehow” (but the latter was never proven). I’d still guess that the uid in the MIDIOut object doesn’t match the system’s uid for the hardware (somehow…?) but that wasn’t proven either – only that “newByName to Pd works and the UID matches” so the uid approach wasn’t totally broken.
I generally prefer (in Linux)
Thanks for polishing my rather crude bit of code. I will borrow your improved and generalized extension promptly! Thanks for sharing!
Here’s an amusing test – with Pd and VCV Rack open.
MIDIClient.init; m = MIDIOut.newByName("Pure Data", "Pure Data Midi-In 1"); (type: \midi, midiout: m).play; // a Pd patch responds // in Rack, choose ALSA - SuperCollider 0 as a MIDI source n = MIDIOut(0); (type: \midi, midiout: n).play; // Rack responds // now flip n's status to be like a newByName MIDIOut n.uid = m.uid; (type: \midi, midiout: n).play; // Pd responds, Rack does not
EDIT: There’s one more case to test.
Checked so far:
- The MIDIOut has a valid UID pointing to another client, and no ALSA connection: MIDI goes to the target identified by UID.
- The MIDIOut has no UID (
nil), and a valid ALSA connection: MIDI goes to the connected target.
- The MIDIOut has a valid UID pointing to another client, and a valid ALSA connection: MIDI goes to the target identified by UID and not to the connected client.
The case that was mentioned in the other thread is
MIDIOut.newByName, but the uid device didn’t receive the message without making a connection externally.
MIDIOut.newByName sets the uid, or throws an error (even with
dieIfNotFound: false, it still throws an error!) – so we are certain that uid must be populated. And the above tests showed that the only way the ALSA connections are used is if uid is nil.
So what happens if the MIDIOut has an invalid UID, and a connection? In my test, nobody receives the message. The UID is invalid, so that can’t work – but the test shows that it doesn’t fall back to the connections. It just fails to send.
n.uid = n.uid + 1; (type: \midi, midiout: n).play; // no response
So the only conclusions I can reach about the other thread are:
- Either (somehow??) you have a version of newByName that will return a MIDIOut object with an empty UID. AFAICS this is not possible in the standard library, but maybe you have an extension that overwrites the method. If UID is empty, that would explain all of the behaviors noted in that case.
- Or PipeWire interferes with the functioning of UIDs. This was never proven, and it would be quite strange for ALSA MIDI’s send function to behave differently based on the audio backend.
Of these, I think the first one is more likely.