- refactored the MIDI list code.

Let's hope nothing got broken on the Linux side, the recent submission's code was not usable.
This commit is contained in:
Christoph Oelckers 2020-01-02 14:21:26 +01:00
parent f442d2dc54
commit 8898448014
6 changed files with 119 additions and 171 deletions

View file

@ -130,21 +130,19 @@ int AlsaSequencer::EnumerateDevices() {
if (!filter(pinfo)) { if (!filter(pinfo)) {
continue; continue;
} }
externalDevices.emplace_back();
internalDevices.emplace_back(); internalDevices.emplace_back();
auto & item = externalDevices.back();
auto & itemInternal = internalDevices.back(); auto & itemInternal = internalDevices.back();
itemInternal.ID = item.ID = index++; itemInternal.ID = index++;
const char *name = snd_seq_port_info_get_name(pinfo); const char *name = snd_seq_port_info_get_name(pinfo);
int portNumber = snd_seq_port_info_get_port(pinfo); int portNumber = snd_seq_port_info_get_port(pinfo);
if(!name) { if(!name) {
std::ostringstream out; std::ostringstream out;
out << "MIDI Port " << clientID << ":" << portNumber; out << "MIDI Port " << clientID << ":" << portNumber;
itemInternal.Name = item.Name = out.str(); itemInternal.Name = out.str();
} }
else { else {
itemInternal.Name = item.Name = name; itemInternal.Name = name;
} }
itemInternal.ClientID = clientID; itemInternal.ClientID = clientID;
itemInternal.PortNumber = portNumber; itemInternal.PortNumber = portNumber;
@ -159,8 +157,4 @@ const std::vector<MidiOutDeviceInternal> & AlsaSequencer::GetInternalDevices()
return internalDevices; return internalDevices;
} }
const std::vector<MidiOutDevice> & AlsaSequencer::GetDevices() {
return externalDevices;
}
#endif #endif

View file

@ -65,7 +65,6 @@ public:
} }
int EnumerateDevices(); int EnumerateDevices();
const std::vector<MidiOutDevice> &GetDevices();
const std::vector<MidiOutDeviceInternal> &GetInternalDevices(); const std::vector<MidiOutDeviceInternal> &GetInternalDevices();
snd_seq_t *handle = nullptr; snd_seq_t *handle = nullptr;
@ -75,7 +74,6 @@ public:
private: private:
std::vector<MidiOutDeviceInternal> internalDevices; std::vector<MidiOutDeviceInternal> internalDevices;
std::vector<MidiOutDevice> externalDevices;
}; };
#endif #endif

View file

@ -31,6 +31,11 @@
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** **
*/ */
#ifdef _WIN32
#include <Windows.h>
#include <mmsystem.h>
#endif
#include <algorithm> #include <algorithm>
#include "timidity/timidity.h" #include "timidity/timidity.h"
#include "timiditypp/timidity.h" #include "timiditypp/timidity.h"
@ -140,22 +145,85 @@ int ZMusic_EnumerateMidiDevices()
#endif #endif
} }
#if 0
const std::vector<MidiOutDevice> &ZMusic_GetMidiDevices() struct MidiDeviceList
{ {
std::vector<MidiOutDevice> devices;
~MidiDeviceList()
{
for (auto& device : devices)
{
free(device.Name);
}
}
void Build()
{
#ifdef HAVE_OPN
devices.push_back({ strdup("libOPN"), -8, MIDIDEV_FMSYNTH });
#endif
#ifdef HAVE_ADL
devices.push_back({ strdup("libADL"), -7, MIDIDEV_FMSYNTH });
#endif
#ifdef HAVE_WILDMIDI
devices.push_back({ strdup("WildMidi"), -6, MIDIDEV_SWSYNTH });
#endif
#ifdef HAVE_FLUIDSYNTH
devices.push_back({ strdup("FluidSynth"), -5, MIDIDEV_SWSYNTH });
#endif
#ifdef HAVE_GUS
devices.push_back({ strdup("GUS Emulation"), -4, MIDIDEV_SWSYNTH });
#endif
#ifdef HAVE_OPL
devices.push_back({ strdup("OPL Synth Emulation"), -3, MIDIDEV_FMSYNTH });
#endif
#ifdef HAVE_TIMIDITY
devices.push_back({ strdup("TiMidity++"), -2, MIDIDEV_SWSYNTH });
#endif
#ifdef HAVE_SYSTEM_MIDI #ifdef HAVE_SYSTEM_MIDI
#ifdef __linux__ #ifdef __linux__
auto & sequencer = AlsaSequencer::Get(); auto& sequencer = AlsaSequencer::Get();
return sequencer.GetDevices(); auto& dev = sequencer.GetDevices();
#elif _WIN32 for (auto& d : dev)
// TODO: move the weird stuff from music_midi_base.cpp here, or at least to this lib and call it here {
return {}; MidiOutDevice mdev = { strdup(d.Name.c_str()), d.ID, MIDIDEV_MAPPER }; // fixme: Correctly determine the type of the device.
#endif devices.push_back(mdev);
#else }
return {}; #elif _WIN32
UINT nummididevices = midiOutGetNumDevs();
for (uint32_t id = 0; id < nummididevices; ++id)
{
MIDIOUTCAPSW caps;
MMRESULT res;
res = midiOutGetDevCapsW(id, &caps, sizeof(caps));
if (res == MMSYSERR_NOERROR)
{
auto len = wcslen(caps.szPname);
int size_needed = WideCharToMultiByte(CP_UTF8, 0, caps.szPname, (int)len, nullptr, 0, nullptr, nullptr);
char* outbuf = (char*)malloc(size_needed + 1);
WideCharToMultiByte(CP_UTF8, 0, caps.szPname, (int)len, outbuf, size_needed, nullptr, nullptr);
outbuf[size_needed] = 0;
MidiOutDevice mdev = { outbuf, id, caps.wTechnology };
devices.push_back(mdev);
}
}
#endif #endif
#endif
}
};
static MidiDeviceList devlist;
DLL_EXPORT const MidiOutDevice* ZMusic_GetMidiDevices(int* pAmount)
{
if (devlist.devices.size() == 0) devlist.Build();
if (pAmount) *pAmount = (int)devlist.devices.size();
return devlist.devices.data();
} }
#endif
template<class valtype> template<class valtype>

View file

@ -189,6 +189,13 @@ struct ZMusicCustomReader
void (*close)(struct ZMusicCustomReader* handle); void (*close)(struct ZMusicCustomReader* handle);
}; };
struct MidiOutDevice
{
char *Name;
int ID;
int Technology;
};
struct Callbacks struct Callbacks
{ {
// Callbacks the client can install to capture messages from the backends // Callbacks the client can install to capture messages from the backends
@ -288,7 +295,7 @@ extern "C"
DLL_IMPORT void FindLoopTags(const uint8_t* data, size_t size, uint32_t* start, bool* startass, uint32_t* end, bool* endass); DLL_IMPORT void FindLoopTags(const uint8_t* data, size_t size, uint32_t* start, bool* startass, uint32_t* end, bool* endass);
// The rest of the decoder interface is only useful for streaming music. // The rest of the decoder interface is only useful for streaming music.
DLL_IMPORT const MidiOutDevice *ZMusic_GetMidiDevices(int *pAmount);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -68,8 +68,6 @@ int nomusic = 0;
#ifdef _WIN32 #ifdef _WIN32
void I_InitMusicWin32();
#include "musicformats/win32/i_cd.h" #include "musicformats/win32/i_cd.h"
//========================================================================== //==========================================================================
// //
@ -274,12 +272,6 @@ void I_InitMusic (void)
nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound"); nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound");
// TODO: remove, move functionality to ZMusic_EnumerateMidiDevices
#ifdef _WIN32
I_InitMusicWin32 ();
#endif // _WIN32
//ZMusic_EnumerateMidiDevices();
snd_mididevice.Callback(); snd_mididevice.Callback();
Callbacks callbacks{}; Callbacks callbacks{};

View file

@ -3,6 +3,7 @@
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2010 Randy Heit ** Copyright 1998-2010 Randy Heit
** Copyright 2005-2020 Christoph Oelckers
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
@ -31,13 +32,6 @@
** **
*/ */
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#endif
#include "c_dispatch.h" #include "c_dispatch.h"
#include "v_text.h" #include "v_text.h"
@ -48,54 +42,17 @@
#define DEF_MIDIDEV -5 #define DEF_MIDIDEV -5
EXTERN_CVAR(Int, snd_mididevice) EXTERN_CVAR(Int, snd_mididevice)
static uint32_t nummididevices;
#define NUM_DEF_DEVICES 7 void I_BuildMIDIMenuList(FOptionValues* opt)
static void AddDefaultMidiDevices(FOptionValues *opt)
{ {
FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(NUM_DEF_DEVICES)]; int amount;
pair[0].Text = "FluidSynth"; auto list = ZMusic_GetMidiDevices(&amount);
pair[0].Value = -5.0;
pair[1].Text = "TiMidity++";
pair[1].Value = -2.0;
pair[2].Text = "WildMidi";
pair[2].Value = -6.0;
pair[3].Text = "GUS";
pair[3].Value = -4.0;
pair[4].Text = "OPL Synth Emulation";
pair[4].Value = -3.0;
pair[5].Text = "libADL";
pair[5].Value = -7.0;
pair[6].Text = "libOPN";
pair[6].Value = -8.0;
} for (int i = 0; i < amount; i++)
#ifdef _WIN32
void I_InitMusicWin32 ()
{
nummididevices = midiOutGetNumDevs ();
}
void I_BuildMIDIMenuList (FOptionValues *opt)
{
AddDefaultMidiDevices(opt);
for (uint32_t id = 0; id < nummididevices; ++id)
{ {
MIDIOUTCAPS caps; FOptionValues::Pair* pair = &opt->mValues[opt->mValues.Reserve(1)];
MMRESULT res; pair->Text = list[i].Name;
pair->Value = (float)list[i].ID;
res = midiOutGetDevCaps (id, &caps, sizeof(caps));
assert(res == MMSYSERR_NOERROR);
if (res == MMSYSERR_NOERROR)
{
FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(1)];
pair->Text = caps.szPname;
pair->Value = (float)id;
}
} }
} }
@ -116,112 +73,44 @@ static void PrintMidiDevice (int id, const char *name, uint16_t tech, uint32_t s
case MIDIDEV_WAVETABLE: Printf ("WAVETABLE"); break; case MIDIDEV_WAVETABLE: Printf ("WAVETABLE"); break;
case MIDIDEV_SWSYNTH: Printf ("SWSYNTH"); break; case MIDIDEV_SWSYNTH: Printf ("SWSYNTH"); break;
} }
if (support & MIDICAPS_CACHE)
{
Printf (" CACHE");
}
if (support & MIDICAPS_LRVOLUME)
{
Printf (" LRVOLUME");
}
if (support & MIDICAPS_STREAM)
{
Printf (" STREAM");
}
if (support & MIDICAPS_VOLUME)
{
Printf (" VOLUME");
}
Printf (TEXTCOLOR_NORMAL "\n"); Printf (TEXTCOLOR_NORMAL "\n");
} }
CCMD (snd_listmididevices) CCMD (snd_listmididevices)
{ {
UINT id; int amount;
MIDIOUTCAPS caps; auto list = ZMusic_GetMidiDevices(&amount);
MMRESULT res;
PrintMidiDevice(-8, "libOPN", MIDIDEV_FMSYNTH, 0); for (int i = 0; i < amount; i++)
PrintMidiDevice(-7, "libADL", MIDIDEV_FMSYNTH, 0);
PrintMidiDevice (-6, "WildMidi", MIDIDEV_SWSYNTH, 0);
PrintMidiDevice (-5, "FluidSynth", MIDIDEV_SWSYNTH, 0);
PrintMidiDevice (-4, "Gravis Ultrasound Emulation", MIDIDEV_SWSYNTH, 0);
PrintMidiDevice (-3, "Emulated OPL FM Synth", MIDIDEV_FMSYNTH, 0);
PrintMidiDevice (-2, "TiMidity++", MIDIDEV_SWSYNTH, 0);
if (nummididevices != 0)
{ {
for (id = 0; id < nummididevices; ++id) PrintMidiDevice(list[i].ID, list[i].Name, list[i].Technology, 0);
{
FString text;
res = midiOutGetDevCaps (id, &caps, sizeof(caps));
if (res == MMSYSERR_NODRIVER)
text = "<Driver not installed>";
else if (res == MMSYSERR_NOMEM)
text = "<No memory for description>";
else if (res == MMSYSERR_NOERROR)
text = caps.szPname;
else
continue;
PrintMidiDevice (id, text, caps.wTechnology, caps.dwSupport);
}
} }
} }
#else // _WIN32
void I_BuildMIDIMenuList (FOptionValues *opt)
{
AddDefaultMidiDevices(opt);
#if 0
auto devices = ZMusic_GetMidiDevices();
for (auto & device: devices)
{
FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(1)];
pair->Text = device.Name.c_str();
pair->Value = (float)device.ID;
}
#endif
}
CCMD (snd_listmididevices)
{
Printf("%s-8. libOPN\n", -8 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-7. libADL\n", -7 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-6. WildMidi\n", -6 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-4. Gravis Ultrasound Emulation\n", -4 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-3. Emulated OPL FM Synth\n", -3 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : "");
#if 0
auto devices = ZMusic_GetMidiDevices();
for (auto & device: devices)
{
Printf("%s%d. %s\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : "", device.ID, device.Name.c_str());
}
#endif
}
#endif
CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
{ {
//auto devices = ZMusic_GetMidiDevices(); int amount;
//if ((self >= (signed)devices.size()) || (self < -8)) auto list = ZMusic_GetMidiDevices(&amount);
if ((self >= (signed)nummididevices) || (self < -8))
bool found = false;
// The list is not necessarily contiguous so we need to check each entry.
for (int i = 0; i < amount; i++)
{
if (self == list[i].ID)
{
found = true;
break;
}
}
if (!found)
{ {
// Don't do repeated message spam if there is no valid device. // Don't do repeated message spam if there is no valid device.
if (self != 0) if (self != 0 && self != -1)
{ {
Printf("ID out of range. Using default device.\n"); Printf("ID out of range. Using default device.\n");
} }
self = DEF_MIDIDEV; if (self != DEF_MIDIDEV) self = DEF_MIDIDEV;
return;
}
else if (self == -1)
{
self = DEF_MIDIDEV;
return; return;
} }
bool change = ChangeMusicSetting(zmusic_snd_mididevice, nullptr, self); bool change = ChangeMusicSetting(zmusic_snd_mididevice, nullptr, self);