summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEero Tamminen <oak@helsinkinet.fi>2021-12-14 19:14:04 (GMT)
committerEero Tamminen <oak@helsinkinet.fi>2021-12-15 18:38:52 (GMT)
commiteb4722a54d41d5ca41b2bdb771a66504934b5d28 (patch)
tree74e9356e8cff8e6bbbf12a7327b8698896acfc69
parent7fd4e221bf11c09cab4b626c2527298fe14db533 (diff)
downloadhatari-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.c69
-rw-r--r--src/includes/midi.h5
-rw-r--r--src/midi.c129
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
diff --git a/src/midi.c b/src/midi.c
index 7b0b95e..19b346c 100644
--- a/src/midi.c
+++ b/src/midi.c
@@ -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;