diff options
| author | Eero Tamminen <oak@helsinkinet.fi> | 2021-12-14 19:14:04 (GMT) |
|---|---|---|
| committer | Eero Tamminen <oak@helsinkinet.fi> | 2021-12-15 18:38:52 (GMT) |
| commit | eb4722a54d41d5ca41b2bdb771a66504934b5d28 (patch) | |
| tree | 74e9356e8cff8e6bbbf12a7327b8698896acfc69 | |
| parent | 7fd4e221bf11c09cab4b626c2527298fe14db533 (diff) | |
| download | hatari-eb4722a54d41d5ca41b2bdb771a66504934b5d28.zip hatari-eb4722a54d41d5ca41b2bdb771a66504934b5d28.tar.gz | |
Improve code for PortMidi devices handling
Get rid of several PortMidi related global variables by rewriting
related SDL GUI code, to query device file names from PortMidi on each
device change.
Unfortunately this does not help Hatari being able to use MIDI devices
added while it is running, because getting current PortMidi to rescan
devices would require calling Pm_Terminate() and Pm_Initialize().
However, that would mess current MIDI connection state, so Hatari will
do that only on startup. I.e. seeing new MIDI device still needs
Hatari restart.
PortMidi promises not to change device indeces after PmInitialize(),
but if a future version could append new devices after existing ones,
new devices would now show up in Hatari without need for re-start.
| -rw-r--r-- | src/gui-sdl/dlgDevice.c | 69 | ||||
| -rw-r--r-- | src/includes/midi.h | 5 | ||||
| -rw-r--r-- | src/midi.c | 129 |
3 files changed, 81 insertions, 122 deletions
diff --git a/src/gui-sdl/dlgDevice.c b/src/gui-sdl/dlgDevice.c index 5a5048e..d0908d8 100644 --- a/src/gui-sdl/dlgDevice.c +++ b/src/gui-sdl/dlgDevice.c @@ -14,6 +14,7 @@ const char DlgDevice_fileid[] = "Hatari dlgDevice.c"; #include "dialog.h" #include "sdlgui.h" #include "file.h" +#include "midi.h" /* needed only with PortMidi */ #include "screen.h" @@ -97,24 +98,6 @@ static SGOBJ devicedlg[] = }; -#ifdef HAVE_PORTMIDI -#include "midi.h" -static int midiInput = -1; -static int midiOutput = -1; - -static void setupMidiControls(void) -{ - const char *inportName,*outportName; - midiInput = Midi_Host_GetPortIndex(ConfigureParams.Midi.sMidiInPortName, true); - midiOutput = Midi_Host_GetPortIndex(ConfigureParams.Midi.sMidiOutPortName, false); - inportName = (midiInput < 0) ? "Off" : ConfigureParams.Midi.sMidiInPortName; - outportName = (midiOutput < 0) ? "Off" : ConfigureParams.Midi.sMidiOutPortName; - File_ShrinkName(dlgMidiInName, inportName, devicedlg[DEVDLG_MIDIINNAME].w); - File_ShrinkName(dlgMidiOutName, outportName, devicedlg[DEVDLG_MIDIOUTNAME].w); -} -#endif - - /*-----------------------------------------------------------------------*/ /** * Show and process the "Device" dialog. @@ -123,7 +106,7 @@ void Dialog_DeviceDlg(void) { int but; #ifdef HAVE_PORTMIDI - const char* portName; + const char *name, *midiInName, *midiOutName; #endif SDLGui_CenterDlg(devicedlg); @@ -151,7 +134,11 @@ void Dialog_DeviceDlg(void) File_ShrinkName(dlgMidiInName, ConfigureParams.Midi.sMidiInFileName, devicedlg[DEVDLG_MIDIINNAME].w); File_ShrinkName(dlgMidiOutName, ConfigureParams.Midi.sMidiOutFileName, devicedlg[DEVDLG_MIDIOUTNAME].w); #else - setupMidiControls(); + midiInName = Midi_Host_GetPortName(ConfigureParams.Midi.sMidiInPortName, 0, true); + File_ShrinkName(dlgMidiInName, midiInName ? midiInName : "Off", devicedlg[DEVDLG_MIDIINNAME].w); + + midiOutName = Midi_Host_GetPortName(ConfigureParams.Midi.sMidiOutPortName, 0, false); + File_ShrinkName(dlgMidiOutName, midiOutName ? midiOutName : "Off", devicedlg[DEVDLG_MIDIOUTNAME].w); #endif /* The devices dialog main loop */ @@ -194,37 +181,31 @@ void Dialog_DeviceDlg(void) break; #else case DEVDLG_PREVIN: - if (midiInput >= 0) - { - midiInput--; - portName = (midiInput == -1) ? "Off" : Midi_Host_GetPortName(midiInput, true); - if (portName) - File_ShrinkName(dlgMidiInName, portName, devicedlg[DEVDLG_MIDIINNAME].w); - } + midiInName = Midi_Host_GetPortName(midiInName, -1, true); + File_ShrinkName(dlgMidiInName, midiInName ? midiInName : "Off", + devicedlg[DEVDLG_MIDIINNAME].w); break; case DEVDLG_NEXTIN: - portName = Midi_Host_GetPortName(midiInput + 1, true); - if (portName) + name = Midi_Host_GetPortName(midiInName, +1, true); + if (name) { - midiInput++; - File_ShrinkName(dlgMidiInName, portName, devicedlg[DEVDLG_MIDIINNAME].w); + midiInName = name; + File_ShrinkName(dlgMidiInName, midiInName, + devicedlg[DEVDLG_MIDIINNAME].w); } break; case DEVDLG_PREVOUT: - if (midiOutput >= 0) - { - midiOutput--; - portName = (midiOutput == -1) ? "Off" : Midi_Host_GetPortName(midiOutput, false); - if (portName) - File_ShrinkName(dlgMidiOutName, portName, devicedlg[DEVDLG_MIDIOUTNAME].w); - } + midiOutName = Midi_Host_GetPortName(midiOutName, -1, false); + File_ShrinkName(dlgMidiOutName, midiOutName ? midiOutName : "Off", + devicedlg[DEVDLG_MIDIOUTNAME].w); break; case DEVDLG_NEXTOUT: - portName = Midi_Host_GetPortName(midiOutput + 1, false); - if (portName) + name = Midi_Host_GetPortName(midiOutName, +1, false); + if (name) { - midiOutput++; - File_ShrinkName(dlgMidiOutName, portName, devicedlg[DEVDLG_MIDIOUTNAME].w); + midiOutName = name; + File_ShrinkName(dlgMidiOutName, midiOutName, + devicedlg[DEVDLG_MIDIOUTNAME].w); } break; #endif @@ -239,8 +220,8 @@ void Dialog_DeviceDlg(void) ConfigureParams.Midi.bEnableMidi = (devicedlg[DEVDLG_MIDIENABLE].state & SG_SELECTED); #ifdef HAVE_PORTMIDI assert(sizeof(dlgMidiInName) <= sizeof(ConfigureParams.Midi.sMidiInPortName)); - strcpy(ConfigureParams.Midi.sMidiInPortName, dlgMidiInName); + strcpy(ConfigureParams.Midi.sMidiInPortName, midiInName ? midiInName : "Off"); assert(sizeof(dlgMidiOutName) <= sizeof(ConfigureParams.Midi.sMidiOutPortName)); - strcpy(ConfigureParams.Midi.sMidiOutPortName, dlgMidiOutName); + strcpy(ConfigureParams.Midi.sMidiOutPortName, midiOutName ? midiOutName : "Off"); #endif } diff --git a/src/includes/midi.h b/src/includes/midi.h index e9f776e..48a8569 100644 --- a/src/includes/midi.h +++ b/src/includes/midi.h @@ -19,7 +19,8 @@ extern void Midi_Control_WriteByte(void); extern void Midi_Data_WriteByte(void); extern void Midi_InterruptHandler_Update(void); -extern const char* Midi_Host_GetPortName(int index, bool forInput); -extern int Midi_Host_GetPortIndex(const char* portName, bool forInput); +#ifdef HAVE_PORTMIDI +extern const char* Midi_Host_GetPortName(const char *name, int offset, bool forInput); +#endif #endif @@ -72,10 +72,6 @@ static FILE *pMidiFhOut = NULL; /* File handle used for Midi output */ #define INPUT_BUFFER_SIZE 1024 // PortMidi handles buffering static PmStream* midiIn = NULL; // current midi input port static PmStream* midiOut = NULL; // current midi output port -static int numInputs = 0; // number of available input ports -static int numOutputs = 0; // number of available output ports -static const PmDeviceInfo** inports = NULL; // array of available input ports -static const PmDeviceInfo** outports = NULL; // array of available output ports static bool Midi_Host_SwitchPort(const char* portName, bool forInput); static int Midi_GetDataLength(Uint8 status); @@ -372,58 +368,25 @@ static bool Midi_Host_Open(void) ConfigureParams.Midi.sMidiInFileName); } #else - /* Need to always get MIDI device info, for MIDI setup dialog */ - int i; - int iindex = 0; - int oindex = 0; - int numPorts = 0; - + int i, ports; if (Pm_Initialize() != pmNoError) { LOG_TRACE(TRACE_MIDI, "MIDI: PortMidi initialization failed\n"); return false; } - // -- get rid of earlier portmidi descriptor arrays (if allocated) - // -- the information may be stale (USB Midi etc) - if (inports) - free (inports); - if (outports) - free (outports); - inports = outports = NULL; - numInputs = numOutputs = 0; - - // -- count number of input and output ports - numPorts = Pm_CountDevices(); - for (i = 0; i < numPorts; i++) + // -- log available ports + ports = Pm_CountDevices(); + for (i = 0; i < ports; i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); - if (info->input) - numInputs++; - else if (info->output) - numOutputs++; - } - - // -- allocate descriptor arrays - inports = malloc(numInputs * sizeof(PmDeviceInfo*)); - outports = malloc(numOutputs * sizeof(PmDeviceInfo*)); - - // -- populate descriptor arrays - for (i = 0; i < numPorts; i++) - { - const PmDeviceInfo* info = Pm_GetDeviceInfo(i); - if (info) - { - LOG_TRACE(TRACE_MIDI, "MIDI: device %d: '%s'\n", i, info->name); - if (info->input) - inports[iindex++] = info; - if (info->output) - outports[oindex++] = info; - } - else - LOG_TRACE(TRACE_MIDI, "MIDI: info disappeared for device %d!\n", i); + if (!info) + continue; + LOG_TRACE(TRACE_MIDI, "MIDI: %s %d: '%s'\n", + info->input ? "input " : "output", i, info->name); } // -- open input and output ports according to configuration + // -- ignore errors to avoid MIDI being disabled if (ConfigureParams.Midi.sMidiInPortName[0]) Midi_Host_SwitchPort(ConfigureParams.Midi.sMidiInPortName, true); if (ConfigureParams.Midi.sMidiOutPortName[0]) @@ -458,42 +421,57 @@ static void Midi_Host_Close(void) -/* ---------------------------------------------------------------------------- */ -/** - * returns port name for input or output port at 'index' - */ -const char* Midi_Host_GetPortName(int index, bool forInput) -{ #ifdef HAVE_PORTMIDI - if (forInput && index < numInputs) - return inports[index]->name; - else if (!forInput && index < numOutputs) - return outports[index]->name; -#endif - - return NULL; -} - -/* ---------------------------------------------------------------------------- */ /** - * returns port descriptor array index for input or output 'portName' + * Returns port name if there's one matching the given port name + * with given offset and direction. + * + * Offset interpretation: + * 0: return matching device name + * <0: return name of device before matching one + * >0: return name of device after matching one + * + * As special case, for NULL name with positive offset, + * name of the first port in correct direction is returned. */ -int Midi_Host_GetPortIndex(const char* portName, bool forInput) +const char* Midi_Host_GetPortName(const char *name, int offset, bool forInput) { -#ifdef HAVE_PORTMIDI - int i = 0; - int numPorts = forInput ? numInputs : numOutputs; - const PmDeviceInfo** ports = forInput ? inports : outports; + const PmDeviceInfo* info; + const char *prev = NULL; + bool prev_matched = false; + int i, count; - if (ports) + // -- find port with given offset from named one + count = Pm_CountDevices(); + for (i = 0; i < count; i++) { - for (i = 0; i < numPorts; i++) - if (!strcmp(portName, ports[i]->name)) - return i; + info = Pm_GetDeviceInfo(i); + if (!info) + continue; + if (forInput && !info->input) + continue; + if (!forInput && info->input) + continue; + if (!name) + { + if (offset <= 0) + return NULL; + return info->name; + } + if (!strcmp(info->name, name)) + { + if (!offset) + return name; + if (offset < 0) + return prev; + prev_matched = true; + continue; + } + if (prev_matched) + return info->name; + prev = info->name; } -#endif - - return -1; + return NULL; } /** @@ -502,7 +480,6 @@ int Midi_Host_GetPortIndex(const char* portName, bool forInput) * matches beginning of the device name, is used. Returns true for * success, false otherwise */ -#ifdef HAVE_PORTMIDI static bool Midi_Host_SwitchPort(const char* portName, bool forInput) { int i, prefixmatch, len, count; |
