ISO icon indicating copy to clipboard operation
ISO copied to clipboard

Make MIDI keyboards "just work"

Open probonopd opened this issue 3 years ago • 75 comments

dmesg
ugen4.6: <M-Audio Keystation Mini 32 MK3> at usbus4
uaudio0 on uhub12
uaudio0: <M-Audio Keystation Mini 32 MK3, class 0/0, rev 1.11/1.11, addr 5> on usbus4
uaudio0: No playback.
uaudio0: No recording.
uaudio0: MIDI sequencer.
uaudio0: No HID volume keys found.

ls /dev/ | grep umidi
umidi0.0

But when I try to play in LMMS or MuseScore it does not work.

Why?

Do we need something utterly complicated like JACK just to make the keyboard work?

probonopd avatar Jul 24 '21 21:07 probonopd

image

It says nothing about "MIDI Input"...

probonopd avatar Jul 24 '21 21:07 probonopd

Maybe @hselasky knows?

probonopd avatar Jul 24 '21 21:07 probonopd

Hi,

USB MIDI keyboards in FreeBSD are RAW and do not go through the sequencer infrastructure for various reasons. I think portaudio doesn't scan for these devices. Technically they should work just fine with any application, as long as they detect properly. Usually when starting synths, I just override the default MIDI device. ZynAddSubFX example:

env MIDI_DEVICE=/dev/umidiX.X zynaddsubfx -I OSS ........

There is also a small tool to wrapper for FreeBSD USB MIDI devices into ALSA:

https://github.com/hselasky/alsa-seq-server

Else "jack_umidi" is frequently used.

Feel free to submit patches. Many people use JACK for more advanced setups, but patching portaudio to recognize /dev/umidi* would be great too.

--HPS

hselasky avatar Jul 26 '21 09:07 hselasky

Thanks @hselasky, very helpful.

I should add that I am not using JACK because it is way too complex for "normal users" in my opinion. I am also not using ALSA because it, too, adds complexity (albeit less). Hence I am interested in a "plan FreeBSD sound" solution, which I assume is OSS.

  • env MIDI_DEVICE=/dev/umidiX.X zynaddsubfx -I OSS compains about missing jackd
  • (sudo) env MIDI_DEVICE=/dev/umidi0.0 musescore does not make the MIDI keyboard work in MuseScore
  • sudo qsynth -a oss, when configured to use OSS instead of jackd, is complaining about missing /dev/midi (where is this supposed to come from?)

image

At this point I a wondering 2 things:

  1. Is using MIDI devices with OSS on FreeBSD even possible?
  2. Is this documented somewhere?

What I am after is the user experience on the Mac: You plug in a MIDI keyboard, open GarageBand, and it "just works". If possible I would like to make things equally easy on helloSystem.

Thanks for any pointers, they are very helpful since I know nothing about this and searching in the FreeBSD handbook also didn't enlighten me.

probonopd avatar Jul 26 '21 19:07 probonopd

Thanks @hselasky, very helpful.

I should add that I am not using JACK because it is way too complex for "normal users" in my opinion. I am also not using ALSA because it, too, adds complexity (albeit less). Hence I am interested in a "plan FreeBSD sound" solution, which I assume is OSS.

* `env MIDI_DEVICE=/dev/umidiX.X zynaddsubfx -I OSS` compains about missing jackd

Try to add "-O OSS". Shouldn't need jackd.

* `(sudo) env MIDI_DEVICE=/dev/umidi0.0 musescore` does not make the MIDI keyboard work in MuseScore

Not all applications support this environment variable.

* `sudo qsynth -a oss`, when configured to use OSS instead of jackd, is complaining about missing `/dev/midi` (where is this supposed to come from?)

"/dev/midi" is the OSS compatible sequencer global interface. USB MIDI devices are not hooked up there. They simply create a per-device character device, which transport raw MIDI.

image

At this point I a wondering 2 things:

1. Is using MIDI devices with OSS on FreeBSD even possible?

Sure. I use them every week. I use "midipp" from ports to route and re-direct all MIDI events between applications.

If you want to use fluidsynth I think to you need to use the ALSA MIDI backend or possibly also jackd will work.

2. Is this documented somewhere?

Most programs come from Linux and are integrated there. Then the compatibility options are very few:

Either you patch the program to support MIDI_DEVICE= or you use JACKD or you use ALSA MIDI.

What I am after is the user experience on the Mac: You plug in a MIDI keyboard, open GarageBand, and it "just works". If possible I would like to make things equally easy on helloSystem.

I see. On Mac there is only one MIDI API, so that makes it easier for everyone. In FreeBSD and Linux there are multiple ones. Maybe what we need is some kind of libmidi library in FreeBSD and a midi server which can route events. That is exactly what ALSA MIDI does and my simplified daemon at github. It even can redirect MIDI via wine that way.

Thanks for any pointers, they are very helpful since I know nothing about this and searching in the FreeBSD handbook also didn't enlighten me.

Sure. I hope you got a satisfying answer.

BTW: I have some youtube videos which show how I use MIDI on FreeBSD. Just search for hselasky on YouTube.

hselasky avatar Jul 27 '21 10:07 hselasky

I can confirm that I see data (gibberish) coming in on sudo cat /dev/umidi0.0 when I press keys on the MIDI keyboard.

First thing sudo midipp does is also complain Could not connect to the JACK subsystem! (which I am not using at all).

I do see this:

image

I hope this means progress. Can I use this to "route events" (meaning MIDI data) to applications such as MuseScore, fluidsynth/QSynth and the like?

my simplified daemon at github

Meaning midipp?

probonopd avatar Jul 27 '21 18:07 probonopd

D'oh! At least for fluidsynth the solution is really simple:

sudo ln -s /dev/umidi0.0 /dev/midi
fluidsynth -m oss -a oss ~/Desktop/MuseScore_General.sf2

So a first step would probably be to just put this symlink in place by default on helloSystem.

probonopd avatar Jul 27 '21 18:07 probonopd

You should check if /dev/midi is already there, else you will get a kernel panic when the system tries to create such a device. The best would be to patch fluidsynth to take the devicename somehow. You maybe also need to add a devfs rule for the umidi* devices, to change permissions or ownership.

MidiPP can route MIDI events, but the best would be to implement a midi server for FreeBSD of some kind, so that the same midi device can be used by multiple applications.

By MIDI server I mean: https://github.com/hselasky/alsa-seq-server

You see, sometimes applications want to serve MIDI data aswell, and then you need a server to do that.

I wonder if sndio also does something similar, but I didn't check yet.

Are you interested in doing some work in this area?

hselasky avatar Jul 28 '21 08:07 hselasky

I just put the ALSA MIDI sequencer server into FreeBSD ports: https://cgit.freebsd.org/ports/commit/?id=a3c9b320dbc478af1dbd3339e9d5f1925204fc5a

I would recommend this over JACKD if you need low latency.

hselasky avatar Aug 02 '21 06:08 hselasky

@mekanix : FYI

hselasky avatar Aug 02 '21 08:08 hselasky

I'm very interested in doing some work on this. I think I mentioned (maybe even few years back) I would enjoy having something like virtual_midi resembling virtual_oss, so I'm in. @hselasky just create repo somewhere and mention it here for reference.

mekanix avatar Aug 02 '21 09:08 mekanix

You maybe also need to add a devfs rule for the umidi* devices, to change permissions or ownership.

Yes, I would like the last plugged in MIDI device to be symlinked to /dev/midi with permissions that allow everyone to use it. What is the best way to do this?

the best would be to implement a midi server for FreeBSD of some kind

Yes, I understand. I was trying to send MIDI commands to /dev/midi while fluidsynth was using it, but it did not let me to. I guess this is where the MIDI server would come in.

I just put the ALSA MIDI sequencer server into FreeBSD ports

Is the ALSA MIDI server related to the ALSA stack in any way other than the name? Would an "OSS MIDI server" look different?

I would enjoy having something like virtual_midi resembling virtual_oss, so I'm in.

Is this what I was calling an "OSS MIDI server"?

probonopd avatar Aug 02 '21 20:08 probonopd

You maybe also need to add a devfs rule for the umidi* devices, to change permissions or ownership.

Yes, I would like the last plugged in MIDI device to be symlinked to /dev/midi with permissions that allow everyone to use it. What is the best way to do this?

This won't work when you have multiple MIDI devices. Attaching or removing any MIDI device will mess with /dev/midi :-(

the best would be to implement a midi server for FreeBSD of some kind

Yes, I understand. I was trying to send MIDI commands to /dev/midi while fluidsynth was using it, but it did not let me to. I guess this is where the MIDI server would come in.

Yes, /dev/umidiX.Y can only be opened once. You got it.

I just put the ALSA MIDI sequencer server into FreeBSD ports

Is the ALSA MIDI server related to the ALSA stack in any way other than the name?

The ALSA MIDI API is supported by libasound.so . It is a separate API from the audio interface.

Would an "OSS MIDI server" look different?

I would enjoy having something like virtual_midi resembling virtual_oss, so I'm in.

Is this what I was calling an "OSS MIDI server"?

The ALSA MIDI sequencer server is already BSD licensed, so I would recommend going down that route instead of re-inventing the wheel. Why do we need yet another MIDI API?

There is a manual page "man alsa-seq-server" which explains some examples how to use it. It also supports hot-plug of MIDI devices. Basically you just pre-specify the device names, and then the alsa-seq-server will automagically attach / detach. This can be improved, but I'd like to have some help on that.

--HPS

hselasky avatar Aug 03 '21 08:08 hselasky

Regarding LMMS, opened a ticket upstream: https://github.com/LMMS/lmms/issues/6263

probonopd avatar Jan 09 '22 15:01 probonopd

As one step toward making MIDI keyboards "just work" on helloSystem, I wonder whether we need to start some daemon(s) whenever we detect a new /dev/umidi* device node (e.g., using devd). Similar to what automount does for disks. For example, we could start jack_umidi -C /dev/umidi* each time such a device node appears. Possibly we would need to do the same for alsa-seq-server -d /dev/umidi*?

Apparently as soon as we run e.g., jack_umidi, the device becomes unavailable for other sound systems:

FreeBSD% sudo ln -sf /dev/umidi*.0 /dev/midi

FreeBSD% fluidsynth -m oss -a oss dx7/AR\ DX7\ Clean\ Analog.sf2
/dev/midi: Device busy
Failed to create the MIDI thread; no MIDI input
will be available. You can access the synthesizer 
through the console.

So we need a way for umidi-supporting applications like fluidsynth, and for jack_umidi and alsa-seq-server (and possibly even more sound systems like PulseAudio, Pipewire and whatnot) to listen to the MIDI messages all at the same time. Can't be that hard, can it?

For it to make any kind of difference, though, all ports and packages in FreeBSD would need to have JACK and PulseAudio support enabled, which currently seems not to be the case at least for MuseScore and LMMS.

On the Mac, you open GarageBand, plug in the USB MIDI keyboard (yes, even in this order) and a dialog will say that a new MIDI controller has been found and is now available. You can start playing right away. No fiddling around! This is our benchmark.

The whole MIDI situation in FreeBSD is currently really frustrating because "nothing works" plug and play (similar to how Xorg felt over 20 years ago). Can we fix it?

probonopd avatar Jan 17 '22 21:01 probonopd

As for MuseScore:

It seems like no one has systematically tested whether MIDI keyboards work with the music applications in FreeBSD ports and packages?

https://www.freshports.org/audio/musescore/ suggests that ALSA, JACK, and PulseAudio are all disabled.

===> The following configuration options are available for musescore-3.6.1_2:
     ALSA=off: ALSA audio architecture support
     JACK=off: JACK audio server support
     PORTAUDIO=on: PortAudio library support
     PULSEAUDIO=off: PulseAudio sound server support
     WEBENGINE=on: Use WebEngine in the welcome panel

So how is MuseScore supposed to work with hardware MIDI controllers as inputs on FreeBSD using PortAudio? What does the user have to do to make it work? Or is using hardware MIDI controllers via PortAudio simply broken altogether?

probonopd avatar Jan 17 '22 21:01 probonopd

Hi,

I made some improvements to alsa-seq-server , including an rc.d file:

https://cgit.freebsd.org/ports/commit/?id=75a7c03777f8a809a35ebaa04c2cbf716a11f656

--HPS

hselasky avatar Jan 23 '22 14:01 hselasky

Hello @hselasky, does this mean that when it is started as a service, then alsa-seq-server will handle all umidi devices? Also those plugged in after alsa-seq-server started?

probonopd avatar Jan 23 '22 15:01 probonopd

@probonopd : Yes. It will consume all /dev/umidi devices.

hselasky avatar Jan 23 '22 21:01 hselasky

Very cool. Thank you so much @hselasky. This will make things easier!

probonopd avatar Jan 23 '22 21:01 probonopd

@probonopd : Some updates. Make sure you get the latest version from FreeBSD ports as of today.

hselasky avatar Jan 27 '22 12:01 hselasky

@probonopd : Maybe we can do some investigation which ports should have ALSA MIDI enabled by default.

hselasky avatar Jan 27 '22 12:01 hselasky

@mekanix : FYI

hselasky avatar Jan 27 '22 12:01 hselasky

D'oh! At least for fluidsynth the solution is really simple:

sudo ln -s /dev/umidi0.0 /dev/midi
fluidsynth -m oss -a oss ~/Desktop/MuseScore_General.sf2

So a first step would probably be to just put this symlink in place by default on helloSystem.

fluidsynth has a special mode where it can run as a server, but only when using ALSA MIDI. Not sure if they support JACK.

midipp has also been updated to support ALSA MIDI.

--HPS

hselasky avatar Jan 27 '22 12:01 hselasky

@hselasky your change to alsa-seq-server works for me, and indeed does improve things a lot in terms of plug-and-play "it just works":

# Become root
sudo su

# Update ports tree
portsnap fetch update
# Updating from Tue Jan 18 09:48:36 CET 2022 to Fri Jan 28 17:05:19 CET 2022.

# Go to alsa-seq-server port
cd /usr/ports/audio/alsa-seq-server

# Install all build dependencies for this port
make build-depends-list | cut -c 12- | xargs pkg install -y

# Build the port, make a package, and install it
make
make package
pkg add -f ./work/pkg/alsa-seq-server-1.0.5.pkg

# Start the alsa-seq-server process
service alsa_seq_server onestart

When I now do the following:

  • Attach MIDI keyboard via USB to the computer
  • Launch a self-compiled version (not the one from FreeBSD packages) of lmms with ALSA support enabled
  • Select "ALSA Sequencer" in the lmms settings
  • Restart lmms

then I can successfully click on the "gears" icon e.g., next to TripleOscillator, and select my MIDI keyboard as an input. And it does work!

I am now thinking of enabling the alsa_seq_server service by default on helloSystem (the reasoning is: helloSystem should be plug-and-play, JACK is not plug-and-play and people who can configure JACK can probably figure out what they need to change).

But will this break applications like fluidsynth?

fluidsynth has a special mode where it can run as a server, but only when using ALSA MIDI. Not sure if they support JACK.

man fluidsynth just says

  -s, --server
    Start FluidSynth as a server process

unfortunately without any explanation what "server process" means in this context. I was assuming that this means it will run as a background daemon, but it might mean something completely different altogether.

probonopd avatar Jan 28 '22 17:01 probonopd

@probonopd : Maybe we can do some investigation which ports should have ALSA MIDI enabled by default.

This post will be updated as we find more applications.

  • [ ] audio/lmms (known to work with alsa-seq-server if compiled with ALSA)
  • [x] audio/musescore (see below)
  • [x] audio/midipp (see below)
  • [ ] audio/fluidsynth

I checked all audio ports that contain "ALSA" in their Makefile:

FreeBSD% find audio -name Makefile -exec grep -H -r "ALSA" {} \; | cut -d ":" -f 1 | sort | uniq

Then I checked which ones of those reference midi in their source code. This gives the following candidates, in addition to the already known ones above:

  • [ ] audio/ecasound
  • [ ] audio/hydrogen
  • [ ] audio/kmix
  • [ ] audio/linuxsampler
  • [ ] audio/muse-sequencer
  • [ ] audio/ocp
  • [ ] audio/pd
  • [ ] audio/qmidinet
  • [ ] audio/qtractor
  • [ ] audio/wildmidi
  • [ ] audio/zmusic
  • [ ] audio/zynaddsubfx

Looks like we have to search even outside of the audio/ ports directory:

  • [ ] emulators/wine (see below)
  • [ ] ...

probonopd avatar Jan 28 '22 17:01 probonopd

But will this break applications like fluidsynth? Not at all.

The -s option basically means start an ALSA client. You'll see fluidsynth show up in "aconnect -l"

hselasky avatar Jan 28 '22 17:01 hselasky

audio/midipp also works with ALSA now.

hselasky avatar Jan 28 '22 17:01 hselasky

Compiled MuseScore with ALSA support from Ports. Can select ALSA but keybord input does not seem to work. Maybe something more needs to be changed in the MuseScore port?

image

probonopd avatar Jan 28 '22 20:01 probonopd

Can WINE be made work with MIDI keyboards as inputs?

I would like to run https://asb2m10.github.io/dexed/, a multi platform, multi format synth that is closely modeled on the Yamaha DX7. Unfortunately it is not available natively for FreeBSD and the Linux version seems to crash when being launched in the Linuxulator. The standalone Windows exe does run in WINE though, and I do hear sounds. Only thing missing is MIDI input. Can it be achieved?

To reproduce:

  • Install wine and winetricks from FreeBSD packages
  • Attach USB MIDI keyboard
  • Download https://github.com/asb2m10/dexed/releases/download/v0.9.6/dexed-0.9.6-win.zip
  • Unizip
  • wine ./dexed-0.9.6-win.exe and install with default settings
  • wine "$HOME/.wine/drive_c/Program Files/Dexed/Dexed.exe"
  • Press some keys on the on-screen keyboard. You should hear something
  • Click "Options" in the upper-left corner of the window, select "Audio/MIDI settings"
  • Notice that "Active MIDI inputs" is empty
  • Try to get a USB MIDI keyboard to work - how?

Possibly need to run winetricks sound=alsa. But when I do this, then under "Audio" in winecfg it says "Selected driver: (None)". This can be reverted back to the original "Selected driver: wineoss.drv" by running winetricks sound=oss. Does this mean that WINE also needs to be compiled with ALSA support specifically? Seems so! Currently it has CONFIGURE_ARGS+= --without-alsa set.

Or is there a way to get MIDI keyboards to work in WINE using OSS only?

probonopd avatar Jan 29 '22 12:01 probonopd