From 67936a26304834d00a13592296b5f5ac1789aaa4 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 10 Sep 2017 07:03:41 -0400 Subject: [PATCH 1/6] - added: m_showinputgrid == '-1' allows for on-screen keyboard to never show, even when using a mouse --- src/menu/menu.cpp | 2 +- wadsrc/static/zscript/menu/textentermenu.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 65a5d5a99..db0fd2efb 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -65,7 +65,7 @@ CVAR (Float, mouse_sensitivity, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, show_messages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, show_obituaries, true, CVAR_ARCHIVE) -CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR (Int, m_showinputgrid, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, m_blockcontrollers, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) diff --git a/wadsrc/static/zscript/menu/textentermenu.txt b/wadsrc/static/zscript/menu/textentermenu.txt index 69a6694f3..db38896b3 100644 --- a/wadsrc/static/zscript/menu/textentermenu.txt +++ b/wadsrc/static/zscript/menu/textentermenu.txt @@ -63,7 +63,7 @@ class TextEnterMenu : Menu mEnterString = textbuffer; mEnterSize = maxlen < 0 ? 0x7fffffff : maxlen; mSizeMode = sizemode; - mInputGridOkay = showgrid || m_showinputgrid; + mInputGridOkay = (showgrid && (m_showinputgrid == 0)) || (m_showinputgrid >= 1); if (mEnterString.Length() > 0) { InputGridX = INPUTGRID_WIDTH - 1; From 5b3fbfde6da145782b15e9c8eb950ebb50424499 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 1 Sep 2017 18:54:35 -0700 Subject: [PATCH 2/6] Read all data from the Timidity++ pipe For non-Windows systems, read() may be non-blocking and can return less than the requested amount if the timidity process hasn't written enough audio yet. --- .../music_timiditypp_mididevice.cpp | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index fb30192d7..ee836efec 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -672,7 +672,6 @@ bool TimidityPPMIDIDevice::FillStream(SoundStream *stream, void *buff, int len, } } #else - ssize_t got; fd_set rfds; struct timeval tv; @@ -697,11 +696,26 @@ bool TimidityPPMIDIDevice::FillStream(SoundStream *stream, void *buff, int len, } // fprintf(stderr,"something\n"); - got = read(song->WavePipe[0], (uint8_t *)buff, len); - if (got < len) - { - memset((uint8_t *)buff+got, 0, len-got); - } + ssize_t got = 0; + do { + ssize_t r = read(song->WavePipe[0], (uint8_t*)buff+got, len-got); + if(r < 0) + { + if(errno == EWOULDBLOCK || errno == EAGAIN) + { + FD_ZERO(&rfds); + FD_SET(song->WavePipe[0], &rfds); + tv.tv_sec = 0; + tv.tv_usec = 50; + select(1, &rfds, NULL, NULL, &tv); + continue; + } + break; + } + got += r; + } while(got < len); + if(got < len) + memset((uint8_t*)buff+got, 0, len-got); #endif return true; } From 8f8c2ef2efd77367e707e93f0a67111d7a118044 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 1 Sep 2017 10:22:33 -0700 Subject: [PATCH 3/6] Build Timidity++ args separately on non-Windows Rather than building a command line that's going to be manually split into individual arguments passed to execvp, build the individual arguments directly. --- .../music_timiditypp_mididevice.cpp | 142 ++++++++---------- 1 file changed, 65 insertions(+), 77 deletions(-) diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index ee836efec..cc0c3684d 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -34,6 +34,8 @@ #include "i_midi_win32.h" +#include +#include #include "i_musicinterns.h" #include "c_cvars.h" @@ -46,6 +48,7 @@ #include #include +#include #include #include @@ -81,14 +84,16 @@ protected: HANDLE ReadWavePipe; HANDLE WriteWavePipe; HANDLE ChildProcess; + FString CommandLine; + size_t LoopPos; bool Validated; bool ValidateTimidity(); #else // _WIN32 int WavePipe[2]; pid_t ChildProcess; #endif - FString CommandLine; - size_t LoopPos; + FString ExeName; + bool Looping; static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata); #ifdef _WIN32 @@ -162,20 +167,24 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) #ifdef _WIN32 ReadWavePipe(INVALID_HANDLE_VALUE), WriteWavePipe(INVALID_HANDLE_VALUE), ChildProcess(INVALID_HANDLE_VALUE), - Validated(false) + Validated(false), #else - ChildProcess(-1) + ChildProcess(-1), #endif + Looping(false) { #ifndef _WIN32 WavePipe[0] = WavePipe[1] = -1; #endif if (args == NULL || *args == 0) args = timidity_exe; + ExeName = args; +#ifdef _WIN32 CommandLine.Format("%s %s -EFchorus=%s -EFreverb=%s -s%d ", args, *timidity_extargs, *timidity_chorus, *timidity_reverb, *timidity_frequency); +#endif if (DiskName == NULL) { @@ -229,14 +238,17 @@ bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping) bool success; FILE *f; - if (CommandLine.IsEmpty()) + if (ExeName.IsEmpty()) { return false; } // Tell TiMidity++ whether it should loop or not +#ifdef _WIN32 CommandLine.LockBuffer()[LoopPos] = looping ? 'l' : ' '; CommandLine.UnlockBuffer(); +#endif + Looping = looping; // Write MIDI song to temporary file song->CreateSMF(midi, looping ? 0 : 1); @@ -327,12 +339,15 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata) Printf(PRINT_BOLD, "If your soundcard cannot play more than one\n" "wave at a time, you will hear no music.\n"); } +#ifdef _WIN32 else { CommandLine += "-o - -Ors"; } +#endif } +#ifdef _WIN32 if (pipeSize == 0) { CommandLine += "-Od"; @@ -349,6 +364,7 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata) CommandLine += " -idl "; CommandLine += DiskName.GetName(); +#endif return 0; } @@ -456,6 +472,7 @@ bool TimidityPPMIDIDevice::ValidateTimidity() bool TimidityPPMIDIDevice::LaunchTimidity () { +#ifdef _WIN32 if (CommandLine.IsEmpty()) { return false; @@ -463,7 +480,6 @@ bool TimidityPPMIDIDevice::LaunchTimidity () DPrintf (DMSG_NOTIFY, "cmd: \x1cG%s\n", CommandLine.GetChars()); -#ifdef _WIN32 STARTUPINFO startup = { sizeof(startup), }; PROCESS_INFORMATION procInfo; @@ -509,6 +525,11 @@ bool TimidityPPMIDIDevice::LaunchTimidity () } return false; #else + if (ExeName.IsEmpty()) + { + return false; + } + if (WavePipe[0] != -1 && WavePipe[1] == -1 && Stream != NULL) { // Timidity was previously launched, so the write end of the pipe @@ -523,78 +544,50 @@ bool TimidityPPMIDIDevice::LaunchTimidity () } int forkres; + wordexp_t words; glob_t glb; // Get timidity executable path - int spaceIdx = 0; - int spaceInExePathCount = -1; - FString TimidityExe; - do - { - spaceIdx = CommandLine.IndexOf(' ', spaceIdx); - TimidityExe = CommandLine.Left(spaceIdx); - glob(TimidityExe.GetChars(), 0, NULL, &glb); - spaceIdx += 1; - spaceInExePathCount += 1; - } while (spaceIdx != 0 && glb.gl_pathc == 0); - if (spaceIdx == 0) - { - TimidityExe = FString("timidity"); // Maybe it's in your PATH? - spaceInExePathCount = 0; - } - globfree(&glb); + const char *exename = "timidity"; // Fallback default + glob(ExeName.GetChars(), 0, NULL, &glb); + if(glb.gl_pathc != 0) + exename = glb.gl_pathv[0]; + // Get user-defined extra args + wordexp(timidity_extargs, &words, WRDE_NOCMD); - int strCount = 1; - for (spaceIdx = 0; spaceIdx < static_cast(CommandLine.Len()); spaceIdx++) - { - if (CommandLine[spaceIdx] == ' ') - { - ++strCount; - if (CommandLine[spaceIdx+1] == ' ') - { - --strCount; - } - } - } - strCount -= spaceInExePathCount; + std::string chorusarg = std::string("-EFchorus=") + *timidity_chorus; + std::string reverbarg = std::string("-EFreverb=") + *timidity_reverb; + std::string sratearg = std::string("-s") + std::to_string(*timidity_frequency); + std::string outfilearg = "-o"; // An extra "-" is added later + std::string outmodearg = "-Or"; + outmodearg += timidity_8bit ? "u8" : "s1"; + outmodearg += timidity_stereo ? "S" : "M"; + if(timidity_byteswap) outmodearg += "x"; + std::string ifacearg = "-id"; + if(Looping) ifacearg += "l"; - char** TimidityArgs = new char*[strCount + 1]; - TimidityArgs[strCount] = NULL; + std::vector arglist; + arglist.push_back(exename); + for(size_t i = 0;i < words.we_wordc;i++) + arglist.push_back(words.we_wordv[i]); + arglist.push_back(chorusarg.c_str()); + arglist.push_back(reverbarg.c_str()); + arglist.push_back(sratearg.c_str()); + arglist.push_back(outfilearg.c_str()); + arglist.push_back("-"); + arglist.push_back(outmodearg.c_str()); + arglist.push_back(ifacearg.c_str()); + arglist.push_back(DiskName.GetName()); - spaceIdx = CommandLine.IndexOf(' '); - int curSpace = spaceIdx, i = 1; - - TimidityArgs[0] = new char[TimidityExe.Len() + 1]; - TimidityArgs[0][TimidityExe.Len()] = 0; - strcpy(TimidityArgs[0], TimidityExe.GetChars()); - - int argLen; - while (curSpace != -1) - { - curSpace = CommandLine.IndexOf(' ', spaceIdx); - if (curSpace != spaceIdx) - { - argLen = curSpace - spaceIdx + 1; - if (argLen < 0) - { - argLen = CommandLine.Len() - curSpace; - } - TimidityArgs[i] = new char[argLen]; - TimidityArgs[i][argLen-1] = 0; - strcpy(TimidityArgs[i], CommandLine.Mid(spaceIdx, curSpace - spaceIdx).GetChars()); - i += 1; - } - spaceIdx = curSpace + 1; - } - - DPrintf(DMSG_NOTIFY, "Timidity EXE: \x1cG%s\n", TimidityExe.GetChars()); - for (i = 0; i < strCount; i++) - { - DPrintf(DMSG_NOTIFY, "arg %d: \x1cG%s\n", i, TimidityArgs[i]); - } + DPrintf(DMSG_NOTIFY, "Timidity EXE: \x1cG%s\n", exename); + int i = 1; + std::for_each(arglist.begin()+1, arglist.end(), + [&i](const char *arg) + { DPrintf(DMSG_NOTIFY, "arg %d: \x1cG%s\n", i++, arg); } + ); + arglist.push_back(nullptr); forkres = fork (); - if (forkres == 0) { close (WavePipe[0]); @@ -603,7 +596,7 @@ bool TimidityPPMIDIDevice::LaunchTimidity () // freopen ("/dev/null", "w", stderr); close (WavePipe[1]); - execvp (TimidityExe.GetChars(), TimidityArgs); + execvp (exename, const_cast(arglist.data())); fprintf(stderr,"execvp failed: %s\n", strerror(errno)); _exit (0); // if execvp succeeds, we never get here } @@ -624,12 +617,7 @@ bool TimidityPPMIDIDevice::LaunchTimidity () }*/ } - for (i = 0; i < strCount; i++) - { - delete [] TimidityArgs[i]; - } - - delete [] TimidityArgs; + wordfree(&words); globfree (&glb); return ChildProcess != -1; #endif // _WIN32 From 49df5a7f163d78a75ef4fb7d84f931ce6eafe895 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 6 Sep 2017 14:48:43 -0700 Subject: [PATCH 4/6] Add a cvar for the timidity++ config file --- .../mididevices/music_timiditypp_mididevice.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index cc0c3684d..69c7f7315 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -123,6 +123,7 @@ CUSTOM_CVAR(String, timidity_exe, "timidity", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) } CVAR (String, timidity_extargs, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // extra args to pass to Timidity +CVAR (String, timidity_config, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, timidity_chorus, "0", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, timidity_reverb, "0", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, timidity_stereo, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -184,6 +185,12 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) CommandLine.Format("%s %s -EFchorus=%s -EFreverb=%s -s%d ", args, *timidity_extargs, *timidity_chorus, *timidity_reverb, *timidity_frequency); + if (**timidity_config != '\0') + { + CommandLine += "-c \""; + CommandLine += timidity_config; + CommandLine += "\" "; + } #endif if (DiskName == NULL) @@ -570,6 +577,11 @@ bool TimidityPPMIDIDevice::LaunchTimidity () arglist.push_back(exename); for(size_t i = 0;i < words.we_wordc;i++) arglist.push_back(words.we_wordv[i]); + if(**timidity_config != '\0') + { + arglist.push_back("-c"); + arglist.push_back(timidity_config); + } arglist.push_back(chorusarg.c_str()); arglist.push_back(reverbarg.c_str()); arglist.push_back(sratearg.c_str()); From 1b1f8d605fc7068cd2236611b5dba4c13010999b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 17 May 2017 15:51:43 -0700 Subject: [PATCH 5/6] Add menu entries for selecting the timidity config --- src/menu/menudef.cpp | 8 ++++++++ wadsrc/static/language.enu | 1 + wadsrc/static/menudef.txt | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index e7818d849..d97705b34 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -1386,6 +1386,7 @@ static void InitMusicMenus() DMenuDescriptor **gusmenu = MenuDescriptors.CheckKey("GusConfigMenu"); DMenuDescriptor **timiditymenu = MenuDescriptors.CheckKey("TimidityExeMenu"); DMenuDescriptor **wildmidimenu = MenuDescriptors.CheckKey("WildMidiConfigMenu"); + DMenuDescriptor **timiditycfgmenu = MenuDescriptors.CheckKey("TimidityConfigMenu"); DMenuDescriptor **fluidmenu = MenuDescriptors.CheckKey("FluidPatchsetMenu"); const char *key, *value; @@ -1426,6 +1427,11 @@ static void InitMusicMenus() auto it = CreateOptionMenuItemCommand(key, FStringf("wildmidi_config %s", NicePath(value).GetChars()), true); static_cast(*wildmidimenu)->mItems.Push(it); } + if (timiditycfgmenu != nullptr) + { + auto it = CreateOptionMenuItemCommand(key, FStringf("timidity_config \"%s\"", NicePath(value).GetChars()), true); + static_cast(*timiditycfgmenu)->mItems.Push(it); + } } } } @@ -1437,6 +1443,8 @@ static void InitMusicMenus() if (it != nullptr) d->mItems.Delete(d->mItems.Find(it)); it = d->GetItem("WildMidiConfigMenu"); if (it != nullptr) d->mItems.Delete(d->mItems.Find(it)); + it = d->GetItem("TimidityConfigMenu"); + if (it != nullptr) d->mItems.Delete(d->mItems.Find(it)); } #ifdef _WIN32 // Different Timidity paths only make sense if they can be stored in arbitrary paths with local configs (i.e. not if things are done the Linux way) if (GameConfig->SetSection("TimidityExes")) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 1edd84500..3c20a7bfd 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2163,6 +2163,7 @@ ADVSNDMNU_REVERB = "Reverb"; ADVSNDMNU_FLUIDVOICES = "MIDI voices"; ADVSNDMNU_TIMIDITY = "Timidity++"; ADVSNDMNU_TIMIDITYEXE = "Path for executable"; +ADVSNDMNU_TIMIDITYCONFIG = "Timidity config file"; ADVSNDMNU_TIMIDITYCHORUS = "Chorus"; ADVSNDMNU_TIMIDITYVOLUME = "Relative volume"; ADVSNDMNU_WILDMIDI = "WildMidi"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 978774c4c..b95d53852 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1680,6 +1680,8 @@ OptionMenu AdvSoundOptions protected { SubMenu "$ADVSNDMNU_SELCONFIG", "TimidityExeMenu" } + TextField "$ADVSNDMNU_TIMIDITYCONFIG", "timidity_config" + SubMenu "$ADVSNDMNU_SELCONFIG", "TimidityConfigMenu" Option "$ADVSNDMNU_REVERB", "timidity_reverb", "OnOff" Option "$ADVSNDMNU_TIMIDITYCHORUS", "timidity_chorus", "OnOff" Slider "$ADVSNDMNU_TIMIDITYVOLUME", "timidity_mastervolume", 0, 4, 0.2, 1 @@ -1705,6 +1707,11 @@ OptionMenu TimidityExeMenu protected Title "$ADVSNDMNU_SELCONFIG" } +OptionMenu TimidityConfigMenu protected +{ + Title "$ADVSNDMNU_SELCONFIG" +} + OptionMenu FluidPatchsetMenu protected { Title "$ADVSNDMNU_SELCONFIG" From 666198dec8e4649d7d7e3f4c19f72c8ec59169e2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 6 Sep 2017 15:46:34 -0700 Subject: [PATCH 6/6] Don't allow Timidity++ pipes less than 20ms This prevents Timidity++ from playing externally, so it now always goes through the sound system. Aside from the issues relating to controlling playback, that functionality has been busted for who knows how long anyway since Open() always tries to create a pipe and sound stream regardless of the calculated size. --- .../music_timiditypp_mididevice.cpp | 59 +++++++------------ 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index 69c7f7315..335265326 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -143,9 +143,9 @@ CUSTOM_CVAR (Float, timidity_mastervolume, 1.0f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR (Int, timidity_pipe, 90, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { // pipe size in ms - if (timidity_pipe < 0) - { // a negative size makes no sense - timidity_pipe = 0; + if (self < 20) + { // Don't allow pipes less than 20ms + self = 20; } } @@ -317,49 +317,31 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata) #endif { Printf(PRINT_BOLD, "Could not create a data pipe for TiMidity++.\n"); - pipeSize = 0; + return 1; } - else + + Stream = GSnd->CreateStream(FillStream, pipeSize, + (timidity_stereo ? 0 : SoundStream::Mono) | + (timidity_8bit ? SoundStream::Bits8 : 0), + timidity_frequency, this); + if (Stream == NULL) { - Stream = GSnd->CreateStream(FillStream, pipeSize, - (timidity_stereo ? 0 : SoundStream::Mono) | - (timidity_8bit ? SoundStream::Bits8 : 0), - timidity_frequency, this); - if (Stream == NULL) - { - Printf(PRINT_BOLD, "Could not create music stream.\n"); - pipeSize = 0; + Printf(PRINT_BOLD, "Could not create music stream.\n"); #ifdef _WIN32 - CloseHandle(WriteWavePipe); - CloseHandle(ReadWavePipe); - ReadWavePipe = WriteWavePipe = INVALID_HANDLE_VALUE; + CloseHandle(WriteWavePipe); + CloseHandle(ReadWavePipe); + ReadWavePipe = WriteWavePipe = INVALID_HANDLE_VALUE; #else - close(WavePipe[1]); - close(WavePipe[0]); - WavePipe[0] = WavePipe[1] = -1; + close(WavePipe[1]); + close(WavePipe[0]); + WavePipe[0] = WavePipe[1] = -1; #endif - } + return 1; } - - if (pipeSize == 0) - { - Printf(PRINT_BOLD, "If your soundcard cannot play more than one\n" - "wave at a time, you will hear no music.\n"); - } -#ifdef _WIN32 - else - { - CommandLine += "-o - -Ors"; - } -#endif } #ifdef _WIN32 - if (pipeSize == 0) - { - CommandLine += "-Od"; - } - + CommandLine += "-o - -Ors"; CommandLine += timidity_stereo ? 'S' : 'M'; CommandLine += timidity_8bit ? '8' : '1'; if (timidity_byteswap) @@ -775,8 +757,7 @@ int TimidityPPMIDIDevice::Resume() { if (LaunchTimidity()) { - // Assume success if not mixing with the sound system - if (Stream == NULL || Stream->Play(true, timidity_mastervolume)) + if (Stream != NULL && Stream->Play(true, timidity_mastervolume)) { Started = true; return 0;