From 889844801476ab7bbcf18fda06b7ab1b46acb2f1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Jan 2020 14:21:26 +0100 Subject: [PATCH] - refactored the MIDI list code. Let's hope nothing got broken on the Linux side, the recent submission's code was not usable. --- .../zmusic/mididevices/music_alsa_state.cpp | 12 +- .../zmusic/mididevices/music_alsa_state.h | 2 - libraries/zmusic/zmusic/configuration.cpp | 92 ++++++++-- libraries/zmusic/zmusic/zmusic.h | 9 +- src/sound/music/i_music.cpp | 8 - src/sound/music/music_midi_base.cpp | 167 +++--------------- 6 files changed, 119 insertions(+), 171 deletions(-) diff --git a/libraries/zmusic/mididevices/music_alsa_state.cpp b/libraries/zmusic/mididevices/music_alsa_state.cpp index 064b38038..bac72a24f 100644 --- a/libraries/zmusic/mididevices/music_alsa_state.cpp +++ b/libraries/zmusic/mididevices/music_alsa_state.cpp @@ -130,21 +130,19 @@ int AlsaSequencer::EnumerateDevices() { if (!filter(pinfo)) { continue; } - externalDevices.emplace_back(); internalDevices.emplace_back(); - auto & item = externalDevices.back(); auto & itemInternal = internalDevices.back(); - itemInternal.ID = item.ID = index++; + itemInternal.ID = index++; const char *name = snd_seq_port_info_get_name(pinfo); int portNumber = snd_seq_port_info_get_port(pinfo); if(!name) { std::ostringstream out; out << "MIDI Port " << clientID << ":" << portNumber; - itemInternal.Name = item.Name = out.str(); + itemInternal.Name = out.str(); } else { - itemInternal.Name = item.Name = name; + itemInternal.Name = name; } itemInternal.ClientID = clientID; itemInternal.PortNumber = portNumber; @@ -159,8 +157,4 @@ const std::vector & AlsaSequencer::GetInternalDevices() return internalDevices; } -const std::vector & AlsaSequencer::GetDevices() { - return externalDevices; -} - #endif diff --git a/libraries/zmusic/mididevices/music_alsa_state.h b/libraries/zmusic/mididevices/music_alsa_state.h index 3955bdc2c..a84f4f5c3 100644 --- a/libraries/zmusic/mididevices/music_alsa_state.h +++ b/libraries/zmusic/mididevices/music_alsa_state.h @@ -65,7 +65,6 @@ public: } int EnumerateDevices(); - const std::vector &GetDevices(); const std::vector &GetInternalDevices(); snd_seq_t *handle = nullptr; @@ -75,7 +74,6 @@ public: private: std::vector internalDevices; - std::vector externalDevices; }; #endif diff --git a/libraries/zmusic/zmusic/configuration.cpp b/libraries/zmusic/zmusic/configuration.cpp index 0ac1664cc..cc93dd5ec 100644 --- a/libraries/zmusic/zmusic/configuration.cpp +++ b/libraries/zmusic/zmusic/configuration.cpp @@ -31,6 +31,11 @@ **--------------------------------------------------------------------------- ** */ + +#ifdef _WIN32 +#include +#include +#endif #include #include "timidity/timidity.h" #include "timiditypp/timidity.h" @@ -140,22 +145,85 @@ int ZMusic_EnumerateMidiDevices() #endif } -#if 0 -const std::vector &ZMusic_GetMidiDevices() + +struct MidiDeviceList { + std::vector 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 __linux__ - auto & sequencer = AlsaSequencer::Get(); - return sequencer.GetDevices(); - #elif _WIN32 - // TODO: move the weird stuff from music_midi_base.cpp here, or at least to this lib and call it here - return {}; - #endif -#else - return {}; +#ifdef __linux__ + auto& sequencer = AlsaSequencer::Get(); + auto& dev = sequencer.GetDevices(); + for (auto& d : dev) + { + MidiOutDevice mdev = { strdup(d.Name.c_str()), d.ID, MIDIDEV_MAPPER }; // fixme: Correctly determine the type of the device. + devices.push_back(mdev); + } +#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 + } + +}; + +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 diff --git a/libraries/zmusic/zmusic/zmusic.h b/libraries/zmusic/zmusic/zmusic.h index f1f533bc2..56a61749d 100644 --- a/libraries/zmusic/zmusic/zmusic.h +++ b/libraries/zmusic/zmusic/zmusic.h @@ -189,6 +189,13 @@ struct ZMusicCustomReader void (*close)(struct ZMusicCustomReader* handle); }; +struct MidiOutDevice +{ + char *Name; + int ID; + int Technology; +}; + struct Callbacks { // 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); // The rest of the decoder interface is only useful for streaming music. - + DLL_IMPORT const MidiOutDevice *ZMusic_GetMidiDevices(int *pAmount); #ifdef __cplusplus } diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index a52d82899..2208fc79c 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -68,8 +68,6 @@ int nomusic = 0; #ifdef _WIN32 -void I_InitMusicWin32(); - #include "musicformats/win32/i_cd.h" //========================================================================== // @@ -274,12 +272,6 @@ void I_InitMusic (void) 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(); Callbacks callbacks{}; diff --git a/src/sound/music/music_midi_base.cpp b/src/sound/music/music_midi_base.cpp index 1fb6a55bf..f45bffcd2 100644 --- a/src/sound/music/music_midi_base.cpp +++ b/src/sound/music/music_midi_base.cpp @@ -3,6 +3,7 @@ ** **--------------------------------------------------------------------------- ** Copyright 1998-2010 Randy Heit +** Copyright 2005-2020 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -31,13 +32,6 @@ ** */ -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include -#include -#endif - #include "c_dispatch.h" #include "v_text.h" @@ -48,54 +42,17 @@ #define DEF_MIDIDEV -5 EXTERN_CVAR(Int, snd_mididevice) -static uint32_t nummididevices; -#define NUM_DEF_DEVICES 7 - -static void AddDefaultMidiDevices(FOptionValues *opt) +void I_BuildMIDIMenuList(FOptionValues* opt) { - FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(NUM_DEF_DEVICES)]; - pair[0].Text = "FluidSynth"; - 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; + int amount; + auto list = ZMusic_GetMidiDevices(&amount); -} - -#ifdef _WIN32 - -void I_InitMusicWin32 () -{ - nummididevices = midiOutGetNumDevs (); -} - -void I_BuildMIDIMenuList (FOptionValues *opt) -{ - AddDefaultMidiDevices(opt); - - for (uint32_t id = 0; id < nummididevices; ++id) + for (int i = 0; i < amount; i++) { - MIDIOUTCAPS caps; - MMRESULT res; - - 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; - } + FOptionValues::Pair* pair = &opt->mValues[opt->mValues.Reserve(1)]; + pair->Text = list[i].Name; + pair->Value = (float)list[i].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_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"); } CCMD (snd_listmididevices) { - UINT id; - MIDIOUTCAPS caps; - MMRESULT res; + int amount; + auto list = ZMusic_GetMidiDevices(&amount); - PrintMidiDevice(-8, "libOPN", MIDIDEV_FMSYNTH, 0); - 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 (int i = 0; i < amount; i++) { - for (id = 0; id < nummididevices; ++id) - { - FString text; - res = midiOutGetDevCaps (id, &caps, sizeof(caps)); - if (res == MMSYSERR_NODRIVER) - text = ""; - else if (res == MMSYSERR_NOMEM) - text = ""; - else if (res == MMSYSERR_NOERROR) - text = caps.szPname; - else - continue; - - PrintMidiDevice (id, text, caps.wTechnology, caps.dwSupport); - } + PrintMidiDevice(list[i].ID, list[i].Name, list[i].Technology, 0); } } -#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) { - //auto devices = ZMusic_GetMidiDevices(); - //if ((self >= (signed)devices.size()) || (self < -8)) - if ((self >= (signed)nummididevices) || (self < -8)) + int amount; + auto list = ZMusic_GetMidiDevices(&amount); + + 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. - if (self != 0) + if (self != 0 && self != -1) { Printf("ID out of range. Using default device.\n"); } - self = DEF_MIDIDEV; - return; - } - else if (self == -1) - { - self = DEF_MIDIDEV; + if (self != DEF_MIDIDEV) self = DEF_MIDIDEV; return; } bool change = ChangeMusicSetting(zmusic_snd_mididevice, nullptr, self);