Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend MIDI auto connect #1023

Merged
merged 12 commits into from
Sep 11, 2022
44 changes: 42 additions & 2 deletions src/drivers/fluid_winmidi.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@
* and forward these messages on distinct MIDI channels set.
* 1.1)For example, if the user chooses 2 devices at index 0 and 1, the user
* must specify this by putting the name "0;1" in midi.winmidi.device setting.
* We get a fictif device composed of real devices (0,1). This fictif device
* We get a fictive device composed of real devices (0,1). This fictive device
* behaves like a device with 32 MIDI channels whose messages are forwarded to
* driver output as this:
* - MIDI messages from real device 0 are output to MIDI channels set 0 to 15.
* - MIDI messages from real device 1 are output to MIDI channels set 15 to 31.
* The above example assumes the setting synth.midi-channels value 32, but the
* default value for this setting is 16, in which case there will be no mapping.
*
* 1.2)Now another example with the name "1;0". The driver will forward
* MIDI messages as this:
Expand All @@ -57,6 +59,13 @@
* or use the multi device naming "0" (specifying only device index 0).
* Both naming choice allows the driver to handle the same single device.
*
* 3)If the device name is "default" and the setting "midi.autoconnect" is enabled,
* then all the available devices are opened, applying the appropriate channel
* mappings to each device (the first device is mapped to the 16 first channels,
* the second one to the next 16 channels, and so on with the limit of the
* synth.midi-channels setting. After arriving to the channels limit, the mapping
* restars with the channels 1-16.
* If the device name is specified, then midi.autoconnect setting is ignored.
*/

#include "fluidsynth_priv.h"
Expand Down Expand Up @@ -458,6 +467,22 @@ fluid_winmidi_parse_device_name(fluid_winmidi_driver_t *dev, char *dev_name)
return dev_count;
}

static void fluid_winmidi_autoconnect_build_name(char *name)
{
int i, j, n = 0;
int num = midiInGetNumDevs();
if (num < 11) {
pedrolcl marked this conversation as resolved.
Show resolved Hide resolved
memset(name, 0, MAXPNAMELEN);
for(i=0; i<num; ++i) {
char x[4];
j = snprintf(x, 4, "%d;", i);
strncat(name, x, j);
n += j;
}
name[n-1] = 0;
}
}

/*
* new_fluid_winmidi_driver
*/
Expand All @@ -469,6 +494,9 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
MMRESULT res;
int i, j;
int max_devices; /* maximum number of devices to handle */
int autoconnect_inputs = 0;
int midi_channels = 16;
int ch_map = 0;
char strError[MAXERRORLENGTH];
char dev_name[MAXPNAMELEN];

Expand All @@ -486,6 +514,13 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
FLUID_STRCPY(dev_name, "default");
}

fluid_settings_getint(settings, "midi.autoconnect", &autoconnect_inputs);
fluid_settings_getint(settings, "synth.midi-channels", &midi_channels);

if ((strcmp(dev_name, "default") == 0) && (autoconnect_inputs != 0)) {
fluid_winmidi_autoconnect_build_name(dev_name);
}

/* parse device name, get the maximum number of devices to handle */
max_devices = fluid_winmidi_parse_device_name(NULL, dev_name);

Expand Down Expand Up @@ -519,7 +554,12 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
device_infos_t *dev_infos = &dev->dev_infos[i];
dev_infos->dev = dev; /* driver structure */
dev_infos->midi_num = i; /* device order number */
dev_infos->channel_map = i * 16; /* map from input to output */
dev_infos->channel_map = ch_map; /* map from input to output */
/* calculate the next channel mapping, up to synth.midi-channels */
ch_map += 16;
if (ch_map >= midi_channels) {
ch_map = 0;
}
FLUID_LOG(FLUID_DBG, "opening device at index %d", dev_infos->dev_idx);
res = midiInOpen(&dev_infos->hmidiin, dev_infos->dev_idx,
(DWORD_PTR) fluid_winmidi_callback,
Expand Down