MIDI input menu has no "None" option

• Mar 29, 2019 - 10:28
Reported version
S3 - Major
won't fix

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.

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.


Sorry, I did not have much time to work on it.
I think it mostly work, but I didn't test it a lot.
I only have a doubt regarding automatically avoiding same MIDI input and output.
As the code is written at the moment in the PR, it chooses an empty (="no device") MIDI input device if the MIDI output is set to a user-chosen value and the auto-grab would have taken this device as input. This can lead to a problem in this situation:
- use or create 2 MIDI devices: A and B
- open MuseScore and select A as input and B as output; save preferences (i.e. click "ok" in the preferences dialog); close MuseScore
- open MuseScore: A is input and B is output, as expected; close MuseScore
- delete/unplug/remove device A, so that only B is left
- open MuseScore: B is chosen as output, while input is left blank (autograb tries to take B, but it coincides with output). If the preference dialog is not open during this session of MuseScore, the saved preferences remain A for input and B for output, but if the preference dialog is opened and closed with ok, even without looking at the I/O tab, the saved preferences become "no device" for input and B for output, and when opening again MuseScore even after replugging/recreating device A (when MuseScore was closed), it would take B as output and "no device" as input (i.e. the saved values).

Maybe I am overthinking about this quirk (the current behavior has B automatically chosen for both input and output), but do you see a possible different solution?
In principle, when the autograb would result in the same input and output, the code could set the output to "no device", and "no device" is the usual default for MIDI output; I had chosen to set the input to "no device" since I am expecting the output in that case to have been explicitly chosen by the user in the previous MuseScore session.

(I hope what I said is understandable: English is not my first language and I find that explaining the full situation is difficult also in my mother tongue, Italian)

In reply to by ABL

I thought autograb was only about INPUT. Do either of you (ABL or Ziya) see a need for autograb output? It would seem to me "never autograb for input, or allow to be set for input, a device which is currently (in fact if dialog is not open, or in the dialog if it is open) chosen for output, and never allow to be set for output something which is currently chosen as input" is the needed policy. The result is so bad (app or OS crash possible) that it is really important (and 3.0 acted that way, without the possibility of "None", if I recall); it is not a convenience but a crash bug.

Yes, in the PR autograb is only for input if it the saved preferences are:
- exactly empty, or
- referring to a missing device.
This is basically the same behavior as current MuseScore releases.
In the PR the code, when it sees that the input value it tries to autograb is the same as the output, it puts this input to none.

I saw that you had opened a thread in the forum; sorry that I had not seen. The build to be tested is the one in this comment:
(there are Windows 64 and Mac binaries)
Please let me know if you can download it, and if it works as expected.
[ you could also try to reproduce the scenario I try to describe in https://musescore.org/en/node/286900#comment-922704 and tell me what you think in this case ]

Thank you for your help :-)

I tried a couple of times to recreate your complex case, but the Mac IAC Bus applet would not let me "recreate" "IAC Bus1" while #2 existed. I don't think it's hugely important that it recognize the reappearance of a device which has disappeared when a conflicting match with an existing choice obscured it. Anyone who knows enough to juggle midi devices in these ways will know to select what they want explicitly. I did try several normal scenarios of connection and disconnection and restart, and all seemed to work properly. The only thing that disturbed me is when I set up, in the dialog, without OK, input and output in the same device, it (a) let me do so (b) did not complain. Ziya?

Thank you both for the testing and the feedback.
I chose an empty string ("" or " ") on purpose to avoid an additional string to be translated (and in the output case, the "no device" case was already an empty string).

Under Windows I am using loopMidi to setup different virtual MIDI ports. In the code the warning about the same input and output is triggered only if the interface is "CoreMIDI" and the complete name contains the string "IAC" (see https://github.com/musescore/MuseScore/blob/5c882aa2de83d6226a9d66cd188… ), and it is shown only after saving the preferences (i.e. after clicking "ok" in the dialog). For LoopMIDI the virtual ports are named "MMSystem,", so no warning is issued when selecting the same port since no "CoreMIDI" nor "IAC" are present in the inteface+name strings.

Do you think the warning should be extended to all cases in which the MIDI input is the same as the MIDI output (i.e. not only for CoreMIDI IAC)? In principle the code change should be pretty straightforward.
Otherwise, if you agree, I think we can push the PR for code review and eventually merging.

In reply to by ABL

An empty string is also understandable.
I've said this for the following reason: Users can report "MIDI input appears to be empty".
Because there was no difference between: "disabled" and "available but empty".
But, if this is a problem, of course, leave it empty.

Sorry for the very long silence from my side, but I have very little time to work on this PR during these weeks.
I saw that BSG asked for the status of the PR in https://musescore.org/en/node/291237
I think that the PR mainly works, except for complex corner cases, but probably users who could experience those corner cases (which require a preference to be explicitly set in a previous session by the user, and a plug-and-unplug/close-and-restart game with MIDI devices) are skilled enough to quickly resolve them.

Since the preferences are saved as strings (usually the name of the MIDI device), I don't know if a translatable string for the "no-device" case could maybe give problems: when loading the preferences we have to compare to the translated string as well and translators have to make sure that they are exactly the same; and the option would probably not be recognized if MuseScore language is changed exactly between saving a translated "no-device" preference and re-loading it.

Which is a pretty sure sign that nothing has happened ;-)
The PR though has recently been updated and rebased for 3.x, so it might make it into 3.6 ?

Ah, that. Difference between Qt 5.9 (ued tor the 32-bit Windows version and the Linux version too) and 5.15 (used by the 64-bit Windows version and the macOS version) apparently, but I can't reproduce.

In reply to by Jojo-Schmitz

It doesn't matter if it's 32 or 64 bit when writing notes (engraving). I'm using the 32-bit version for note-writing because the palettes are visible.
Software hiccups when playing some works containing too many notes/instruments at the same time on 32bit. then I have to open the 64bit version to listen.

I have to install the Linux version as well. Maybe I'll use it now.
Thank you for keeping, maintaining, and updating version 3.x.