JUCE
JUCE copied to clipboard
Jack midi support
Currently JUCE supports jack audio ports fairly well, but there is no jack midi support at all. This makes sequencing JUCE applications really difficult, having to create virtual midi ports and routing signals via these. It's quite the hassle.
Please consider adding jack midi support to make life a little easier on those that use this system.
It would just need to expose an input port and let the user take care of routing signals to the application.
Pipewire bypasses this problem, by the way.
Kind of. It's still nice to be able to control the graph from outside the juce application, which is not possible if juce "latches on" without any regard to routing rules.
Also many cases where running pipewire is not wanted and dedicated jack configuration is needed.
With Pipewire you can use any JACK routing program (such as Qjackctl) to route audio and MIDI connections written originally for ALSA, Pulseaudio and JACK.
Yes, but any routing logic from within the JUCE app doesn't make any sense then. There would still need to be some sort of "just expose midi port" ability, without any routing on the JUCE side.
PulseAudio does not have a midi api afaik.
I'd like to add that this specific issue is about MIDI support, not audio. Indeed, with PipeWire I can route the two output audio channels to whatever audio sink I want, but no MIDI input is available for JUCE applications.
For comparison, look at how amsynth behaves, when compared to a JUCE-based application (odin2). qpwgraph shows native JACK/PipeWire MIDI input, and even the correct application name with an application icon:
As well as basic ALSA MIDI input:
And both can be re-routed easily via PipeWire using qpwgraph. However, any JUCE-based application only shows two audio output channels and zero MIDI input channels. Thus, it's impossible to route MIDI to JUCE applications.
It is extremely annoying to have to hunt down for the configuration screen of each application and then toggle some checkboxes over there. It negates the patchbay saving/loading feature of qpwgraph. It is also frustrating to press some MIDI keys and not know which application is handling those and generating audio.
This issue affects several projects:
Some potentially related issues:
- https://github.com/juce-framework/JUCE/issues/333
- https://github.com/juce-framework/JUCE/issues/952 (this one)
- https://github.com/sonosaurus/sonobus/issues/152
- https://github.com/BespokeSynth/BespokeSynth/issues/273
- https://github.com/TheWaveWarden/odin2/issues/452
If anyone wants to tackle this issue, this is probably a good start: juce_Midi_linux.cpp
On Fri, Sep 8, 2023 at 1:41 PM Denilson Sá Maia @.***> wrote:
I'd like to add that this specific issue is about MIDI support, not audio. Indeed, with PipeWire I can route the two output audio channels to whatever audio sink I want, but no MIDI input is available for JUCE applications.
Here's the rough fix I'm using: https://github.com/kmatheussen/radium/blob/e115ad6ec6fb9dfa9348a716efe706aa740a38ad/pluginhost/midi_linux.diff#L32
Problem is that this is disabled by default instead of enabled by default, for some reason. I just force it to always be enabled. (I think I submitted a patch around 10 years ago, but it wasn't accepted)
Message ID: @.***>
@kmatheussen, that is very helpful!
As a quick-and-dirty fix, we can have a single-line patch!
--- juce_Midi_linux.cpp 2023-09-08 16:19:43.865931328 +0200
+++ juce_Midi_linux.cpp 2023-09-08 16:09:52.193231251 +0200
@@ -469,7 +469,7 @@
{
if (portID != -1)
{
- port = client.createPort (portName, forInput, false);
+ port = client.createPort (portName, forInput, true);
jassert (port->isValid());
port->connectWith (sourceClient, portID);
break;
With just that change, I've managed to recompile OPL and it indeed shows up in qpwgraph
:
Changes in the settings screen seem to be mostly reflected into qpwgraph
(but I can't uncheck my main controller, for whatever reason). Changes from PipeWire are not reflected in the application, so changes can get out-of-sync. MIDI playback still works, anyway, even if the application checkboxes are out-of-sync compared to the real PipeWire connections.
Unfortunately, the ports have the name copied from the devices, which gets confusing. Even more confusing because all ports end up duplicated in the PipeWire Midi-Bridge box.
In this screenshot, I'm running VMPK and connecting it to OPL (a JUCE application), together with a hardware device. I'm also running amsynth, but unconnected. This leads to many duplicated ports in many boxes (and some of that is inherent to how PipeWire's Midi-Bridge works); but it's still better than not being able to route anything.
Please note that kmatheussen's patch does a few more changes, one of them is related to the port name. I haven't tested those changes.
My suggestion for next steps:
- Apply the simple one-line patch.
- Apply additional changes for better port naming in JUCE.
- Figure out how to keep the checkboxes in-sync with the real connections.
- Write a brand-new MIDI driver for linux, targeting JACK/PipeWire instead of plain ALSA. All input and output ports should show up in the same box (in qpwgraph), and the box should have the application name and possibly the application icon.
- At some point, send PRs to many applications so they can use the newer JUCE version with the MIDI fixes. These can happen as early as step one.
I'm sorry, but I'm not going to implement those. These are just my suggestions (from easiest to hardest). I'll leave those to whoever is more familiar with JUCE.
i actually just meant to refer to line 32 of that patch, which is also a one-liner. :)
On Fri, 8 Sep 2023 at 16:44, Denilson Sá Maia @.***> wrote:
@kmatheussen https://github.com/kmatheussen, that is very helpful!
As a quick-and-dirty fix, we can have a single-line patch https://github.com/juce-framework/JUCE/blob/22df0d2266007bccb25d6ed52b9907f60d04e971/modules/juce_audio_devices/native/juce_Midi_linux.cpp#L472 !
--- juce_Midi_linux.cpp 2023-09-08 16:19:43.865931328 +0200+++ juce_Midi_linux.cpp 2023-09-08 16:09:52.193231251 +0200@@ -469,7 +469,7 @@ { if (portID != -1) {- port = client.createPort (portName, forInput, false);+ port = client.createPort (portName, forInput, true); jassert (port->isValid()); port->connectWith (sourceClient, portID); break;
With just that change, I've managed to recompile OPL https://github.com/reales/OPL and it indeed shows up in qpwgraph:
[image: Screenshot of qpwgraph] https://user-images.githubusercontent.com/121676/266639643-0ff3294d-00eb-477a-b64a-40372bc6f188.png
Changes in the settings screen seem to be mostly reflected into qpwgraph (but I can't uncheck my main controller, for whatever reason). Changes from PipeWire are not reflected in the application, so changes can get out-of-sync. MIDI playback still works, anyway, even if the application checkboxes are out-of-sync compared to the real PipeWire connections.
Unfortunately, the ports have the name copied from the devices, which gets confusing. Even more confusing because all ports end up duplicated in the PipeWire Midi-Bridge box.
[image: Another screenshot of qpwgraph] https://user-images.githubusercontent.com/121676/266644555-0f2f2e07-19a5-490a-97da-ece8265bc83c.png
In this screenshot, I'm running VMPK http://vmpk.sourceforge.net and connecting it to OPL https://github.com/reales/OPL (a JUCE application), together with a hardware device. I'm also running amsynth https://amsynth.github.io/, but unconnected. This leads to many duplicated ports in many boxes (and some of that is inherent to how PipeWire's Midi-Bridge works); but it's still better than not being able to route anything.
Please note that kmatheussen's patch https://github.com/kmatheussen/radium/blob/e115ad6ec6fb9dfa9348a716efe706aa740a38ad/pluginhost/midi_linux.diff does a few more changes, one of them is related to the port name. I haven't tested those changes.
My suggestion for next steps:
- Apply the simple one-line patch.
- Apply additional changes for better port naming in JUCE.
- Figure out how to keep the checkboxes in-sync with the real connections.
- Write a brand-new MIDI driver for linux, targeting JACK/PipeWire instead of plain ALSA.
- At some point, send PRs to many applications so they can use the newer JUCE version with the MIDI fixes. These can happen as early as step one.
I'm sorry, but I'm not going to implement those. These are just my suggestions (from easiest to hardest). I'll leave those to whoever is more familiar with JUCE.
— Reply to this email directly, view it on GitHub https://github.com/juce-framework/JUCE/issues/952#issuecomment-1711787509, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAIX3J57FJ2KXO4NQZCY3TDXZMVM3ANCNFSM5ETMXVIQ . You are receiving this because you were mentioned.Message ID: @.***>
By just looking at git history, I guess this behavior was introduced in 2017 (6 years ago), in this commit, which was a large refactor with hundreds of lines. That commit added the enableSubscription
parameter, as previously that flag was always set.
The commit message mentions:
- Fixed a bug when getDeivces() would return devices created by the application itself
- Only ports created with createNewDevice() are allowed to be subscribed, other ports (created by openDevice()) doesn't allow subscription
As a workaround for this issue, if your JUCE application is also built and installed as LV2 plugin, then you can use Jalv as a simple standalone LV2 plugin host. It will behave properly, having one box for the whole application, with proper audio out and midi in channels, with proper name, and even including the icon.
Compare Odin2 running inside Jalv (above) with Odin2 standalone binary (below):
Of course, you can also run other more complete plugin hosts, like Carla (which also shows up properly just like Jalv).
Except most (extensive) standalone JUCE applications don't run as a plugin at all.