mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
midi: open MIDI devices only when a core requests the interface
drivers_init enumerated and opened the MIDI devices on every start, whether or not a core would ever use them. With the default WinMM driver and "Microsoft GS Wavetable Synth" output that means a MIDI stream for every Windows user, and on Windows 11 the first WinMM MIDI call after boot starts the Windows MIDI Service and blocks until it is up. That is the slow first launch in #19247. Keep driver selection in drivers_init, and enumerate and open the devices when a core calls GET_MIDI_INTERFACE. The request survives driver reinits (SET_SYSTEM_AV_INFO, audio latency changes) and is dropped when the core is unloaded. The menu device lists are filled on demand without opening a device. Frame Delay no longer relies on the MIDI stream holding the timer period down since5c30a403be, and the WASAPI workaround for it was removed in8d4bccac55. Fixes #19247
This commit is contained in:
1 parent
cb8a7083fb
commit
fa876218d1
3 files changed
+110
-60
No files matched your search
@@ -230,6 +230,9 @@ bool midi_driver_set_volume(unsigned volume);
|
||||
bool midi_driver_set_input(const char *input);
|
||||
bool midi_driver_set_output(void *data, const char *output);
|
||||
|
||||
/* Opens the devices on behalf of a core, now or at the next driver init */
|
||||
void midi_driver_request(void);
|
||||
|
||||
/**
|
||||
* midi_driver_get_event_size:
|
||||
* This is a convenience function for finding out the size of the event based
|
||||
|
||||
+106
-60
@@ -589,6 +589,8 @@ static midi_event_t rarch_midi_drv_output_event; /* ptr alignment */
|
||||
static bool rarch_midi_drv_input_enabled;
|
||||
static bool rarch_midi_drv_output_enabled;
|
||||
static bool rarch_midi_drv_output_pending;
|
||||
static bool rarch_midi_drv_inited;
|
||||
static bool rarch_midi_drv_requested;
|
||||
|
||||
static void null_midi_free(void *p) { }
|
||||
static void *null_midi_init(const char *input, const char *output) { return (void*)-1; }
|
||||
@@ -651,13 +653,46 @@ static const void *midi_driver_find_handle(int index)
|
||||
return midi_drivers[index];
|
||||
}
|
||||
|
||||
/* Not done at driver init: the first WinMM MIDI call after boot
|
||||
* can block for seconds while Windows starts its MIDI service. */
|
||||
static bool midi_driver_enum_devices(void)
|
||||
{
|
||||
union string_list_elem_attr attr = {0};
|
||||
|
||||
if (!rarch_midi_drv_inited)
|
||||
return false;
|
||||
if (rarch_midi_drv_inputs)
|
||||
return true;
|
||||
|
||||
rarch_midi_drv_inputs = string_list_new();
|
||||
rarch_midi_drv_outputs = string_list_new();
|
||||
|
||||
if ( rarch_midi_drv_inputs
|
||||
&& rarch_midi_drv_outputs
|
||||
&& string_list_append_n(rarch_midi_drv_inputs, MIDI_DRIVER_OFF, STRLEN_CONST(MIDI_DRIVER_OFF), attr)
|
||||
&& string_list_append_n(rarch_midi_drv_outputs, MIDI_DRIVER_OFF, STRLEN_CONST(MIDI_DRIVER_OFF), attr)
|
||||
&& midi_drv->get_avail_inputs(rarch_midi_drv_inputs)
|
||||
&& midi_drv->get_avail_outputs(rarch_midi_drv_outputs))
|
||||
return true;
|
||||
|
||||
if (rarch_midi_drv_inputs)
|
||||
string_list_free(rarch_midi_drv_inputs);
|
||||
if (rarch_midi_drv_outputs)
|
||||
string_list_free(rarch_midi_drv_outputs);
|
||||
rarch_midi_drv_inputs = NULL;
|
||||
rarch_midi_drv_outputs = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct string_list *midi_driver_get_avail_inputs(void)
|
||||
{
|
||||
midi_driver_enum_devices();
|
||||
return rarch_midi_drv_inputs;
|
||||
}
|
||||
|
||||
struct string_list *midi_driver_get_avail_outputs(void)
|
||||
{
|
||||
midi_driver_enum_devices();
|
||||
return rarch_midi_drv_outputs;
|
||||
}
|
||||
|
||||
@@ -796,89 +831,68 @@ static void midi_driver_free(void)
|
||||
|
||||
rarch_midi_drv_input_enabled = false;
|
||||
rarch_midi_drv_output_enabled = false;
|
||||
rarch_midi_drv_inited = false;
|
||||
}
|
||||
|
||||
static bool midi_driver_init(void *data)
|
||||
static bool midi_driver_open(settings_t *settings)
|
||||
{
|
||||
union string_list_elem_attr
|
||||
attr = {0};
|
||||
bool ret = true;
|
||||
settings_t *settings = (settings_t*)data;
|
||||
bool ret = true;
|
||||
|
||||
rarch_midi_drv_inputs = string_list_new();
|
||||
rarch_midi_drv_outputs = string_list_new();
|
||||
if (rarch_midi_drv_data)
|
||||
return true;
|
||||
|
||||
if (!rarch_midi_drv_inputs || !rarch_midi_drv_outputs)
|
||||
ret = false;
|
||||
else if (!string_list_append_n(rarch_midi_drv_inputs, MIDI_DRIVER_OFF, STRLEN_CONST(MIDI_DRIVER_OFF), attr) ||
|
||||
!string_list_append_n(rarch_midi_drv_outputs, MIDI_DRIVER_OFF, STRLEN_CONST(MIDI_DRIVER_OFF), attr))
|
||||
if (!midi_driver_enum_devices())
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
char * input = NULL;
|
||||
char * output = NULL;
|
||||
|
||||
midi_drv = midi_driver_find_driver(
|
||||
settings->arrays.midi_driver);
|
||||
|
||||
if (strcmp(midi_drv->ident, settings->arrays.midi_driver))
|
||||
if (string_is_not_equal(settings->arrays.midi_input, MIDI_DRIVER_OFF))
|
||||
{
|
||||
configuration_set_string(settings,
|
||||
settings->arrays.midi_driver, midi_drv->ident);
|
||||
if (string_list_find_elem(rarch_midi_drv_inputs, settings->arrays.midi_input))
|
||||
input = settings->arrays.midi_input;
|
||||
else
|
||||
{
|
||||
RARCH_WARN("[MIDI] Input device \"%s\" unavailable.\n",
|
||||
settings->arrays.midi_input);
|
||||
configuration_set_string(settings,
|
||||
settings->arrays.midi_input, MIDI_DRIVER_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (!midi_drv->get_avail_inputs(rarch_midi_drv_inputs))
|
||||
ret = false;
|
||||
else if (!midi_drv->get_avail_outputs(rarch_midi_drv_outputs))
|
||||
if (string_is_not_equal(settings->arrays.midi_output, MIDI_DRIVER_OFF))
|
||||
{
|
||||
if (string_list_find_elem(rarch_midi_drv_outputs, settings->arrays.midi_output))
|
||||
output = settings->arrays.midi_output;
|
||||
else
|
||||
{
|
||||
RARCH_WARN("[MIDI] Output device \"%s\" unavailable.\n",
|
||||
settings->arrays.midi_output);
|
||||
configuration_set_string(settings,
|
||||
settings->arrays.midi_output, MIDI_DRIVER_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
rarch_midi_drv_data = midi_drv->init(input, output);
|
||||
if (!rarch_midi_drv_data)
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
if (string_is_not_equal(settings->arrays.midi_input, MIDI_DRIVER_OFF))
|
||||
{
|
||||
if (string_list_find_elem(rarch_midi_drv_inputs, settings->arrays.midi_input))
|
||||
input = settings->arrays.midi_input;
|
||||
else
|
||||
{
|
||||
RARCH_WARN("[MIDI] Input device \"%s\" unavailable.\n",
|
||||
settings->arrays.midi_input);
|
||||
configuration_set_string(settings,
|
||||
settings->arrays.midi_input, MIDI_DRIVER_OFF);
|
||||
}
|
||||
}
|
||||
rarch_midi_drv_input_enabled = (input != NULL);
|
||||
rarch_midi_drv_output_enabled = (output != NULL);
|
||||
|
||||
if (string_is_not_equal(settings->arrays.midi_output, MIDI_DRIVER_OFF))
|
||||
{
|
||||
if (string_list_find_elem(rarch_midi_drv_outputs, settings->arrays.midi_output))
|
||||
output = settings->arrays.midi_output;
|
||||
else
|
||||
{
|
||||
RARCH_WARN("[MIDI] Output device \"%s\" unavailable.\n",
|
||||
settings->arrays.midi_output);
|
||||
configuration_set_string(settings,
|
||||
settings->arrays.midi_output, MIDI_DRIVER_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
rarch_midi_drv_data = midi_drv->init(input, output);
|
||||
if (!rarch_midi_drv_data)
|
||||
if (!midi_driver_init_io_buffers())
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
rarch_midi_drv_input_enabled = (input != NULL);
|
||||
rarch_midi_drv_output_enabled = (output != NULL);
|
||||
if (input)
|
||||
RARCH_LOG("[MIDI] Input device: \"%s\".\n", input);
|
||||
|
||||
if (!midi_driver_init_io_buffers())
|
||||
ret = false;
|
||||
else
|
||||
if (output)
|
||||
{
|
||||
if (input)
|
||||
RARCH_LOG("[MIDI] Input device: \"%s\".\n", input);
|
||||
|
||||
if (output)
|
||||
{
|
||||
RARCH_LOG("[MIDI] Output device: \"%s\".\n", output);
|
||||
midi_driver_set_volume(settings->uints.midi_volume);
|
||||
}
|
||||
RARCH_LOG("[MIDI] Output device: \"%s\".\n", output);
|
||||
midi_driver_set_volume(settings->uints.midi_volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -893,6 +907,33 @@ static bool midi_driver_init(void *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool midi_driver_init(void *data)
|
||||
{
|
||||
settings_t *settings = (settings_t*)data;
|
||||
|
||||
midi_drv = midi_driver_find_driver(
|
||||
settings->arrays.midi_driver);
|
||||
|
||||
if (strcmp(midi_drv->ident, settings->arrays.midi_driver))
|
||||
{
|
||||
configuration_set_string(settings,
|
||||
settings->arrays.midi_driver, midi_drv->ident);
|
||||
}
|
||||
|
||||
rarch_midi_drv_inited = true;
|
||||
|
||||
if (rarch_midi_drv_requested)
|
||||
return midi_driver_open(settings);
|
||||
return true;
|
||||
}
|
||||
|
||||
void midi_driver_request(void)
|
||||
{
|
||||
rarch_midi_drv_requested = true;
|
||||
if (rarch_midi_drv_inited)
|
||||
midi_driver_open(config_get_ptr());
|
||||
}
|
||||
|
||||
bool midi_driver_set_input(const char *input)
|
||||
{
|
||||
if (!rarch_midi_drv_data)
|
||||
@@ -1965,7 +2006,12 @@ void driver_uninit(int flags, enum driver_lifetime_flags lifetime_flags)
|
||||
#endif
|
||||
|
||||
if (flags & DRIVER_MIDI_MASK)
|
||||
{
|
||||
midi_driver_free();
|
||||
/* Reopen after a reinit, not after the core is unloaded */
|
||||
if (!(lifetime_flags & DRIVER_LIFETIME_RESET))
|
||||
rarch_midi_drv_requested = false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
cpu_scaling_driver_free();
|
||||
|
||||
@@ -3440,6 +3440,7 @@ bool runloop_environment_cb(unsigned cmd, void *data)
|
||||
|
||||
if (midi_interface)
|
||||
{
|
||||
midi_driver_request();
|
||||
midi_interface->input_enabled = midi_driver_input_enabled;
|
||||
midi_interface->output_enabled = midi_driver_output_enabled;
|
||||
midi_interface->read = midi_driver_read;
|
||||
|
||||
Reference in new issue
Block a user