MIDI input menu has no "None" option

• Mar 29, 2019 - 10:28
Reported version
S3 - Major
PR created

In MuseScore 3,

As long as a MIDI input device is available, MuseScore will grab it. There is no way to say "I don't wan't any MIDI input device"; the MIDI Input control in "Preferences" has no "None"/blank option like the MIDI Output menu has.

You might ask, "why is this problem? Just don't supply any input.", but if you have midi loopbacks set up, it is a big problem, and you have to set up extra ones just to placate this bug.

There is a subtlety here, too. Because of this bug (feature?), a person attaching a midi input device, say, a keyboard, doesn't have to use Preferences to select it -- MS "grabs" it, and if it didn't do so, there would be an additional step in using a midi keyboard not now necessary, i.e., to select it in Preferences.

Well, if that's a problem, then one might presume that it can continue grabbing midi input devices as available, for that reason alone, but one should be able to say "no, I wish you hadn't grabbed that", and select "none", but that creates a problem on restart if it grabs a midi device that is a loopback that, as very likely, has been chosen as MIDI output. The clean solution is to require explicit selection of a MIDI Input device and stopping this grabbing behavior, with default "none". Maybe it should simply avoid choosing the same input device as output device (as it warns you about now), but you still need a "none" option if it grabs it for input before you set it up as output.

So this is controversial.


Maybe we could add an initial "None" item, but set instead the default value to the first actual device, so that the current behavior would remain the same (i.e. when pluggin a MIDI input device, it is activated by default), but one could easily set the input MIDI to None if needed.
What do you think?

Apparently, the code does not look very difficult to be changed, since a "None" item is already added for the MIDI output, here: https://github.com/musescore/MuseScore/blob/b18bf8add326e95db17b47333ed…

As a matter of fact, since "changes on this page require a restart of MuseScore", the blank/none option would be meaningless unless it were remembered on restart. What Ziya says is exactly right -- for those who use MIDI routing programs, this bug is a nightmare.

I would like a "none" and use it all times, as I don't own any MIDI device, nor would be able to enter notes with it.
But it'd be enough if the setting of the MIDI button would be saved.

Right now it supplies "None" to lucky souls like you who have no MIDI input-capable devices attached, but not to us who have any (including loopBacks and other routing software).

Let me make clear that I use "None" and "blank" interchangeably in this context. We don't have either and they're the same thing. Under the current proposal, if you have a MIDI loop-back set up, you would start MuseScore and it would be chosen as input, and you'd have to select "none" for input before using it as output (or get the present warning that you're going to crash the system if you try). And it'd have to remember that you did that so it would not crash when it came up after a successful shutdown (currently impossible with midi output enabled).

Status active PR created

I tried a tentative implementation here:

I had to change the default to "none" input device, similar to the output case. The drawback is that users would have to go to the preference dialog and set the input device instead of this being automatically recognized and picked up by MuseScore.

I think this PR must be thoroughly tested (I am not an expert of midi input/output) before (possible) merging.

I'll go further than that, as the originator of this request (although Ziya and I are an army of 2 now)! I would just love this, "default none", but this is controversial. When you do choose a real midi source, will it persist through shutdown/restart? That might not be so bad for "fans of auto-midi-grab", but it's a documentation change. I'd really like to hear from Marc, Mike, Jojo and others whose design input I deem crucial about whether this is OK. I intend to test it thoroughly, that it meets its intended function, but we gotta agree on that. Guys?

Yes, the preference is saved and reloaded (as it happens at the moment if one has different midi input devices): the device is searched by its name (saved as a text string).

The current default is an empty string, but in the code there is an instruction which read:
if (inputId == -1)
inputId = Pm_GetDefaultInputDeviceID();

so basically: if the saved preference for midi input is none (so that the index is left at its default value -1), then take the first (?) useful midi input. This would overwrite the case of a default empty string in the preferences, even in the case in which the empty string was chosen on purpose; that's why I deleted those two lines in the PR.

This will be hard to document, because someone will say "Hey, it's failing to grab my midi keyboard. Why was that taken out? Can this be fixed?" and the reason will be hard to explain. It's "because it can inappropriately grab some device that was intended for some other application", at simplest.

(If I understand it correctly) I disagree with this implementation. The conflicting use cases are:
- running MuseScore with a MIDI device connected and wanting to use the device in MuseScore
- running MuseScore with a MIDI device connected and not wanting to use the device in MuseScore

I believe it's a safe bet that the first of the two is far more common. To put the onus on users of the first case to explicitly set the connected MIDI device would therefore be inappropriate. In fact, I'm sure users assume MuseScore automatically uses a connected MIDI device and would be annoyed if it were not to.

In reply to by RobFog

Suppose you have more than one midi device. Suppose you have a midi device that you want to use for output to another program, and not have it automatically tangle itself in a loop. Suppose you want another program to use that midi device. There is no way to get around this behavior than to construct two midi routing channels, one as a "sacrifice" to this bug. In the current proposal, the people with the midi device will have to select it once, and the connection will be remembered through restarts. That is neither onerous nor unexpectable.

The problem is that the inputId is computed with respect to all and only the physical devices, so any name string not matching the name of a physical device would result into -1 (=pmNoDevice ), and therefore overwritten by inputId = Pm_GetDefaultInputDeviceID().
But on the other hand, we could add a special case, something like
if (preferences.getString(PREF_IO_PORTMIDI_INPUTDEVICE) == "chosen bogus value")
inputId = -1;

where "chosen bogus value" could be "none" or "empty" or " " (a space, not an empty string).
Maybe it is better with a space, so that there a translation would not be needed.
I will try this route and see if it works as expected.

I updated the PR so that the default behavior is the same as the current one: a midi input device is automatically grabbed unless it is explicitly manually set to none in the preferences.

If one chooses "none midi input device" (i.e. "empty" field in the dropdown menu) and at the end of the session closes MuseScore, then:
- if the following time MuseScore is opened with a midi device present, this preference (i.e. no input midi device) is remembered in such following session;
- if the following time MuseScore is opened without a midi device, then the preferences are reset to their default value, and the next time MuseScore is openend with a midi device it is automatically grabbed and a "none midi input" in that case must be again manually selected.

I think thorough tests are needed to see if I managed to cover all possible cases.

Suggestion: don't let it ever "grab" for midi input any name which is selected for midi output. I saw it do this once.

In principle, it should grab the first available input midi device only after a "reset" of the midi device preferences, but in that case the default output device would be null!
The code should behave exactly as it is currently behaving in 3.0.5. It should set the same device for both input and output only if the user sets them like this.
Do you know how to reproduce such a case?
In principle it should be the case in which the output device preference is kept, while the input one is reset. Maybe (?) it could be the case in which there is an output device which is not an input device and no other input devices, so that the input device list is empty and the output device is chosen by the user as that specific device; and then after closing and before the next session that device becomes also an input device, so it is listed in the input device list and automatically grabbed (since the saved value is really empty => reset of the preference), while the output device relies on the saved preference, which as well points to the same device. Does it somehow make sense?
In that case, however, the current 3.0.5 behavior should be the same. And then, the only other "available" input device would be the "none" device.

I don't really know how to implement such automatic exception; at the moment I am simply relying on Pm_GetDefaultInputDeviceID() for input grabbing.

The thing we dearly do not want is for it to create a loop in the operating system and crash when a note is sent into an infinite loop. It already knows that and warns you if you try to do that by erroneous setting of the MIDI input and output devices, so it should even less do it by itself.

In reply to by ABL

I tested it:

MIDI Output works well and behaves as expected.

MIDI Input is a bit strange.
try01: At the first launch: it automatically assigned a MIDI device.
oper01: I set it as None.
try02: At the second launch: No MIDI device assigned; this is nice.
try03: At the third launch: it automatically assigned a MIDI device again; Grrr!
go to oper01;

Note: Regardless of how the setting is made, the MIDI-Input icon on the Home screen is always on. Turning-off isn't working. At the next launch, it becomes "open" again.

Thank you all for the tests.
From what you see, it seems that during the second launch the " " (=none) preference is overwritten by "" (=empty). I will have a look at it (maybe it needs a special case handling), but most probably I will not be able to do this before Friday or Saturday.

I think I managed to solve all the resetting issues (hopefully) and updated the PR.
The main problem was that if both input and output were set to none, then the mididriver was not initialized and therefore the MIDI input/output preference values were saved as empty strings and thus reset at next start.
Here are test builds:
- Windows 64bit: https://drive.google.com/open?id=1qbVCyd95rlPdy8gfjBSnN7uxur4foWcx
- MacOS: https://drive.google.com/open?id=1fWbLFgc5XZXMpbCD96YduRetMCOFqRvN

In the case of an automatically fetched MIDI input equal to a user-set MIDI ouput, I chose to keep the output and set the input to none (since the output is the value which came from a user choice). This can happen for example when using 2 MIDI device, -1- for input and -2- for output, and then before the following MuseScore launch disconnecting only -1-, so that -2- would be the first option auto-grab could see.