From 5374eed06dd1ea3b456be884af8ac5badc3d84d6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 10 Mar 2017 19:03:58 +0100 Subject: [PATCH] - cleaned up the interdependencies between the MIDIStreamer and the WinMIDIDevice classes. A major part of this device's implementation details about how to handle the callback were not encapsulated by the device class at all, they were #ifdef'd into the streamer class. This puts everything into the device class which now exposes a clean interface to the rest of the game with no special handling aside from calling two additional virtual functions that are empty for the other devices --- src/sound/i_musicinterns.h | 8 +- src/sound/i_sound.cpp | 2 + src/sound/music_hmi_midiout.cpp | 4 - src/sound/music_midistream.cpp | 281 ++--------------------------- src/sound/music_mus_midiout.cpp | 5 - src/sound/music_smf_midiout.cpp | 4 - src/sound/music_win_mididevice.cpp | 223 +++++++++++++++++++---- src/sound/music_xmi_midiout.cpp | 4 - 8 files changed, 215 insertions(+), 316 deletions(-) diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index c658da61b..7f42ef208 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -74,7 +74,8 @@ public: virtual int UnprepareHeader(MidiHeader *data); virtual bool FakeVolume(); virtual bool Pause(bool paused) = 0; - virtual bool NeedThreadedCallback(); + virtual void InitPlayback(); + virtual bool Update(); virtual void PrecacheInstruments(const uint16_t *instruments, int count); virtual void TimidityVolumeChanged(); virtual void FluidSettingInt(const char *setting, int value); @@ -357,21 +358,20 @@ public: void FluidSettingStr(const char *setting, const char *value); void WildMidiSetOption(int opt, int set); void CreateSMF(TArray &file, int looplimit=0); + int ServiceEvent(); protected: MIDIStreamer(const char *dumpname, EMidiDevice type); - bool CheckExitEvent(); void OutputVolume (uint32_t volume); int FillBuffer(int buffer_num, int max_events, uint32_t max_time); int FillStopBuffer(int buffer_num); uint32_t *WriteStopNotes(uint32_t *events); - int ServiceEvent(); int VolumeControllerChange(int channel, int volume); int ClampLoopCount(int loopcount); void SetTempo(int new_tempo); static EMidiDevice SelectMIDIDevice(EMidiDevice devtype); - MIDIDevice *CreateMIDIDevice(EMidiDevice devtype) const; + MIDIDevice *CreateMIDIDevice(EMidiDevice devtype); static void Callback(void *userdata); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 672ada638..64eefcbb8 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -122,6 +122,8 @@ CUSTOM_CVAR (Float, snd_sfxvolume, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOIN } } +class MIDIStreamer; + class NullSoundRenderer : public SoundRenderer { public: diff --git a/src/sound/music_hmi_midiout.cpp b/src/sound/music_hmi_midiout.cpp index c0dfa3bf7..f5322d2c1 100644 --- a/src/sound/music_hmi_midiout.cpp +++ b/src/sound/music_hmi_midiout.cpp @@ -131,10 +131,6 @@ extern char MIDI_CommonLengths[15]; HMISong::HMISong (FileReader &reader, EMidiDevice type, const char *args) : MIDIStreamer(type, args), MusHeader(0), Tracks(0) { - if (!CheckExitEvent()) - { - return; - } int len = reader.GetLength(); if (len < 0x100) { // Way too small to be HMI. diff --git a/src/sound/music_midistream.cpp b/src/sound/music_midistream.cpp index e75fe0844..7a19277f6 100644 --- a/src/sound/music_midistream.cpp +++ b/src/sound/music_midistream.cpp @@ -36,15 +36,6 @@ #include "i_midi_win32.h" -/* -#ifdef _WIN32 -DWORD PlayerLoop(); - -HANDLE PlayerThread; -HANDLE ExitEvent; -HANDLE BufferDoneEvent; -#endif -*/ #include "i_musicinterns.h" #include "templates.h" @@ -73,8 +64,6 @@ EXTERN_CVAR(Float, snd_musicvolume) EXTERN_CVAR(Int, snd_mididevice) #ifdef _WIN32 -DWORD WINAPI PlayerProc(LPVOID lpParameter); - extern unsigned mididevice; #endif @@ -105,27 +94,9 @@ static const uint8_t StaticMIDIhead[] = MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args) : -#ifdef _WIN32 - //PlayerThread(0), ExitEvent(0), BufferDoneEvent(0), -#endif MIDI(0), Division(0), InitialTempo(500000), DeviceType(type), Args(args) { memset(Buffer, 0, sizeof(Buffer)); - /* -#ifdef _WIN32 - BufferDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (BufferDoneEvent == NULL) - { - Printf(PRINT_BOLD, "Could not create buffer done event for MIDI playback\n"); - } - ExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (ExitEvent == NULL) - { - Printf(PRINT_BOLD, "Could not create exit event for MIDI playback\n"); - return; - } -#endif -*/ } //========================================================================== @@ -136,18 +107,9 @@ MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args) MIDIStreamer::MIDIStreamer(const char *dumpname, EMidiDevice type) : -#ifdef _WIN32 - //PlayerThread(0), ExitEvent(0), BufferDoneEvent(0), -#endif MIDI(0), Division(0), InitialTempo(500000), DeviceType(type), DumpFilename(dumpname) { memset(Buffer, 0, sizeof(Buffer)); - /* -#ifdef _WIN32 - BufferDoneEvent = NULL; - ExitEvent = NULL; -#endif -*/ } //========================================================================== @@ -159,18 +121,6 @@ MIDIStreamer::MIDIStreamer(const char *dumpname, EMidiDevice type) MIDIStreamer::~MIDIStreamer() { Stop(); - /* -#ifdef _WIN32 - if (ExitEvent != NULL) - { - CloseHandle(ExitEvent); - } - if (BufferDoneEvent != NULL) - { - CloseHandle(BufferDoneEvent); - } -#endif -*/ if (MIDI != NULL) { delete MIDI; @@ -198,11 +148,7 @@ bool MIDIStreamer::IsMIDI() const bool MIDIStreamer::IsValid() const { -#ifdef _WIN32 - return /*ExitEvent != NULL &&*/ Division != 0; -#else return Division != 0; -#endif } //========================================================================== @@ -278,7 +224,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device) // //========================================================================== -MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const +MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) { switch (devtype) { @@ -331,7 +277,6 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const void MIDIStreamer::Play(bool looping, int subsong) { - DWORD tid; EMidiDevice devtype; m_Status = STATE_Stopped; @@ -359,10 +304,6 @@ void MIDIStreamer::Play(bool looping, int subsong) MIDI = CreateMIDIDevice(devtype); } -#ifndef _WIN32 - assert(MIDI == NULL || MIDI->NeedThreadedCallback() == false); -#endif - if (MIDI == NULL || 0 != MIDI->Open(Callback, this)) { Printf(PRINT_BOLD, "Could not open MIDI out device\n"); @@ -393,27 +334,7 @@ void MIDIStreamer::Play(bool looping, int subsong) } else { - /* -#ifdef _WIN32 - if (MIDI->NeedThreadedCallback()) - { - PlayerThread = CreateThread(NULL, 0, PlayerProc, this, 0, &tid); - if (PlayerThread == NULL) - { - Printf ("Creating MIDI thread failed\n"); - Stop(); - } - else - { - m_Status = STATE_Playing; - } - } - else -#endif -*/ - { - m_Status = STATE_Playing; - } + m_Status = STATE_Playing; } } @@ -440,12 +361,7 @@ void MIDIStreamer::StartPlayback() MusicVolumeChanged(); // set volume to current music's properties OutputVolume(Volume); - /* -#ifdef _WIN32 - ResetEvent(ExitEvent); - ResetEvent(BufferDoneEvent); -#endif -*/ + MIDI->InitPlayback(); // Fill the initial buffers for the song. BufferNum = 0; @@ -532,17 +448,6 @@ void MIDIStreamer::Stop() { EndQueued = 4; - /* -#ifdef _WIN32 - if (PlayerThread != NULL) - { - SetEvent(ExitEvent); - WaitForSingleObject(PlayerThread, INFINITE); - CloseHandle(PlayerThread); - PlayerThread = NULL; - } -#endif -*/ if (MIDI != NULL && MIDI->IsOpen()) { MIDI->Stop(); @@ -714,10 +619,6 @@ int MIDIStreamer::VolumeControllerChange(int channel, int volume) // // MIDIStreamer :: Callback Static // -// Signals the BufferDoneEvent to prepare the next buffer. The buffer is not -// prepared in the callback directly, because it's generally still in use by -// the MIDI streamer when this callback is executed. -// //========================================================================== void MIDIStreamer::Callback(void *userdata) @@ -728,18 +629,7 @@ void MIDIStreamer::Callback(void *userdata) { return; } - /* -#ifdef _WIN32 - if (self->PlayerThread != NULL) - { - SetEvent(self->BufferDoneEvent); - } - else -#endif -*/ - { - self->ServiceEvent(); - } + self->ServiceEvent(); } //========================================================================== @@ -753,128 +643,9 @@ void MIDIStreamer::Callback(void *userdata) void MIDIStreamer::Update() { - /* -#ifdef _WIN32 - // If the PlayerThread is signalled, then it's dead. - if (PlayerThread != NULL && - WaitForSingleObject(PlayerThread, 0) == WAIT_OBJECT_0) - { - static const char *const MMErrorCodes[] = - { - "No error", - "Unspecified error", - "Device ID out of range", - "Driver failed enable", - "Device already allocated", - "Device handle is invalid", - "No device driver present", - "Memory allocation error", - "Function isn't supported", - "Error value out of range", - "Invalid flag passed", - "Invalid parameter passed", - "Handle being used simultaneously on another thread", - "Specified alias not found", - "Bad registry database", - "Registry key not found", - "Registry read error", - "Registry write error", - "Registry delete error", - "Registry value not found", - "Driver does not call DriverCallback", - "More data to be returned", - }; - static const char *const MidiErrorCodes[] = - { - "MIDI header not prepared", - "MIDI still playing something", - "MIDI no configured instruments", - "MIDI hardware is still busy", - "MIDI port no longer connected", - "MIDI invalid MIF", - "MIDI operation unsupported with open mode", - "MIDI through device 'eating' a message", - }; - DWORD code = 0xABADCAFE; - GetExitCodeThread(PlayerThread, &code); - CloseHandle(PlayerThread); - PlayerThread = NULL; - Printf ("MIDI playback failure: "); - if (code < countof(MMErrorCodes)) - { - Printf("%s\n", MMErrorCodes[code]); - } - else if (code >= MIDIERR_BASE && code < MIDIERR_BASE + countof(MidiErrorCodes)) - { - Printf("%s\n", MidiErrorCodes[code - MIDIERR_BASE]); - } - else - { - Printf("%08x\n", code); - } - Stop(); - } -#endif -*/ + if (!MIDI->Update()) Stop(); } -//========================================================================== -// -// MIDIStreamer :: PlayerProc Static -// -// Entry point for the player thread. -// -//========================================================================== - -#ifdef _WIN32 -DWORD WINAPI PlayerProc(LPVOID lpParameter) -{ -// return ((MIDIStreamer *)lpParameter)->PlayerLoop(); - return 0; -} -#endif - -//========================================================================== -// -// MIDIStreamer :: PlayerLoop -// -// Services MIDI playback events. -// -//========================================================================== -/* - -#ifdef _WIN32 -DWORD MIDIStreamer::PlayerLoop() -{ - HANDLE events[2] = { BufferDoneEvent, ExitEvent }; - int res; - - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - - for (;;) - { - switch (WaitForMultipleObjects(2, events, FALSE, INFINITE)) - { - case WAIT_OBJECT_0: - if (0 != (res = ServiceEvent())) - { - return res; - } - break; - - case WAIT_OBJECT_0 + 1: - return 0; - - default: - // Should not happen. - return MMSYSERR_ERROR; - } - } - return 0; -} -#endif -*/ - //========================================================================== // // MIDIStreamer :: ServiceEvent @@ -913,8 +684,8 @@ fill: switch (res & 3) { case SONG_MORE: - if ((MIDI->NeedThreadedCallback() && 0 != (res = MIDI->StreamOutSync(&Buffer[BufferNum]))) || - (!MIDI->NeedThreadedCallback() && 0 != (res = MIDI->StreamOut(&Buffer[BufferNum])))) + res = MIDI->StreamOut(&Buffer[BufferNum]); + if (res != 0) { return res; } @@ -1433,27 +1204,6 @@ bool MIDIStreamer::SetMIDISubsong(int subsong) return subsong == 0; } -//========================================================================== -// -// MIDIStreamer :: CheckExitEvent -// -// -// -//========================================================================== - -bool MIDIStreamer::CheckExitEvent() -{ - /* -#ifdef _WIN32 - if (ExitEvent == NULL) - { - return false; - } -#endif -*/ - return true; -} - //========================================================================== // // MIDIDevice stubs. @@ -1545,16 +1295,23 @@ bool MIDIDevice::FakeVolume() //========================================================================== // -// MIDIDevice :: NeedThreadedCallabck // -// Most implementations can service the callback directly rather than using -// a separate thread. // //========================================================================== -bool MIDIDevice::NeedThreadedCallback() +void MIDIDevice::InitPlayback() { - return false; +} + +//========================================================================== +// +// +// +//========================================================================== + +bool MIDIDevice::Update() +{ + return true; } //========================================================================== diff --git a/src/sound/music_mus_midiout.cpp b/src/sound/music_mus_midiout.cpp index bf1270252..955c293a7 100644 --- a/src/sound/music_mus_midiout.cpp +++ b/src/sound/music_mus_midiout.cpp @@ -96,11 +96,6 @@ static const uint8_t CtrlTranslate[15] = MUSSong2::MUSSong2 (FileReader &reader, EMidiDevice type, const char *args) : MIDIStreamer(type, args), MusHeader(0), MusBuffer(0) { - if (!CheckExitEvent()) - { - return; - } - uint8_t front[32]; int start; diff --git a/src/sound/music_smf_midiout.cpp b/src/sound/music_smf_midiout.cpp index 39555dcb4..32de991b3 100644 --- a/src/sound/music_smf_midiout.cpp +++ b/src/sound/music_smf_midiout.cpp @@ -108,10 +108,6 @@ MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type, const char *args) int p; int i; - if (!CheckExitEvent()) - { - return; - } SongLen = reader.GetLength(); MusHeader = new uint8_t[SongLen]; if (reader.Read(MusHeader, SongLen) != SongLen) diff --git a/src/sound/music_win_mididevice.cpp b/src/sound/music_win_mididevice.cpp index cb5987830..5682d71ac 100644 --- a/src/sound/music_win_mididevice.cpp +++ b/src/sound/music_win_mididevice.cpp @@ -34,19 +34,7 @@ #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#define USE_WINDOWS_DWORD -#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0400 -#undef _WIN32_WINNT -#endif -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 -#endif -#ifndef USE_WINDOWS_DWORD -#define USE_WINDOWS_DWORD -#endif -#include -#include +#include "i_midi_win32.h" // HEADER FILES ------------------------------------------------------------ @@ -92,13 +80,16 @@ public: int PrepareHeader(MidiHeader *data); int UnprepareHeader(MidiHeader *data); bool FakeVolume(); - bool NeedThreadedCallback(); bool Pause(bool paused); + void InitPlayback() override; + bool Update() override; void PrecacheInstruments(const uint16_t *instruments, int count); + DWORD PlayerLoop(); -protected: +//protected: static void CALLBACK CallbackFunc(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD); + MIDIStreamer *Streamer; HMIDISTRM MidiOut; UINT DeviceID; DWORD SavedVolume; @@ -108,6 +99,12 @@ protected: MidiCallback Callback; void *CallbackData; + + HANDLE BufferDoneEvent; + HANDLE ExitEvent; + HANDLE PlayerThread; + + }; // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -128,6 +125,18 @@ WinMIDIDevice::WinMIDIDevice(int dev_id) MidiOut = 0; HeaderIndex = 0; memset(WinMidiHeaders, 0, sizeof(WinMidiHeaders)); + + BufferDoneEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (BufferDoneEvent == nullptr) + { + Printf(PRINT_BOLD, "Could not create buffer done event for MIDI playback\n"); + } + ExitEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (ExitEvent == nullptr) + { + Printf(PRINT_BOLD, "Could not create exit event for MIDI playback\n"); + } + PlayerThread = nullptr; } //========================================================================== @@ -139,6 +148,15 @@ WinMIDIDevice::WinMIDIDevice(int dev_id) WinMIDIDevice::~WinMIDIDevice() { Close(); + + if (ExitEvent != nullptr) + { + CloseHandle(ExitEvent); + } + if (BufferDoneEvent != nullptr) + { + CloseHandle(BufferDoneEvent); + } } //========================================================================== @@ -153,7 +171,7 @@ int WinMIDIDevice::Open(MidiCallback callback, void *userdata) Callback = callback; CallbackData = userdata; - if (MidiOut == NULL) + if (MidiOut == nullptr) { err = midiStreamOpen(&MidiOut, &DeviceID, 1, (DWORD_PTR)CallbackFunc, (DWORD_PTR)this, CALLBACK_FUNCTION); @@ -185,10 +203,10 @@ int WinMIDIDevice::Open(MidiCallback callback, void *userdata) void WinMIDIDevice::Close() { - if (MidiOut != NULL) + if (MidiOut != nullptr) { midiStreamClose(MidiOut); - MidiOut = NULL; + MidiOut = nullptr; } } @@ -200,7 +218,7 @@ void WinMIDIDevice::Close() bool WinMIDIDevice::IsOpen() const { - return MidiOut != NULL; + return MidiOut != nullptr; } //========================================================================== @@ -244,6 +262,19 @@ int WinMIDIDevice::SetTimeDiv(int timediv) return midiStreamProperty(MidiOut, (LPBYTE)&data, MIDIPROP_SET | MIDIPROP_TIMEDIV); } +//========================================================================== +// +// MIDIStreamer :: PlayerProc Static +// +// Entry point for the player thread. +// +//========================================================================== + +DWORD WINAPI PlayerProc(LPVOID lpParameter) +{ + return ((WinMIDIDevice *)lpParameter)->PlayerLoop(); +} + //========================================================================== // // WinMIDIDevice :: Resume @@ -252,7 +283,31 @@ int WinMIDIDevice::SetTimeDiv(int timediv) int WinMIDIDevice::Resume() { - return midiStreamRestart(MidiOut); + DWORD tid; + int ret = midiStreamRestart(MidiOut); + if (ret == 0) + { + PlayerThread = CreateThread(nullptr, 0, PlayerProc, this, 0, &tid); + if (PlayerThread == nullptr) + { + Printf("Creating MIDI thread failed\n"); + Stop(); + return MMSYSERR_NOTSUPPORTED; + } + } + return ret; +} + +//========================================================================== +// +// WinMIDIDevice :: InitPlayback +// +//========================================================================== + +void WinMIDIDevice::InitPlayback() +{ + ResetEvent(ExitEvent); + ResetEvent(BufferDoneEvent); } //========================================================================== @@ -263,6 +318,14 @@ int WinMIDIDevice::Resume() void WinMIDIDevice::Stop() { + if (PlayerThread != nullptr) + { + SetEvent(ExitEvent); + WaitForSingleObject(PlayerThread, INFINITE); + CloseHandle(PlayerThread); + PlayerThread = nullptr; + } + midiStreamStop(MidiOut); midiOutReset((HMIDIOUT)MidiOut); if (VolumeWorks) @@ -271,6 +334,40 @@ void WinMIDIDevice::Stop() } } +//========================================================================== +// +// MIDIStreamer :: PlayerLoop +// +// Services MIDI playback events. +// +//========================================================================== + +DWORD WinMIDIDevice::PlayerLoop() +{ + HANDLE events[2] = { BufferDoneEvent, ExitEvent }; + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + + for (;;) + { + switch (WaitForMultipleObjects(2, events, FALSE, INFINITE)) + { + case WAIT_OBJECT_0: + if (Callback != nullptr) Callback(CallbackData); + break; + + case WAIT_OBJECT_0 + 1: + return 0; + + default: + // Should not happen. + return MMSYSERR_ERROR; + } + } + return 0; +} + + //========================================================================== // // WinMIDIDevice :: PrecacheInstruments @@ -391,9 +488,7 @@ int WinMIDIDevice::StreamOut(MidiHeader *header) int WinMIDIDevice::StreamOutSync(MidiHeader *header) { - auto syshdr = (MIDIHDR*)header->lpNext; - assert(syshdr == &WinMidiHeaders[0] || syshdr == &WinMidiHeaders[1]); - return midiStreamOut(MidiOut, syshdr, sizeof(MIDIHDR)); + return StreamOut(header); } //========================================================================== @@ -454,15 +549,71 @@ bool WinMIDIDevice::FakeVolume() //========================================================================== // -// WinMIDIDevice :: NeedThreadedCallback -// -// When using the MM system, the callback can't yet touch the buffer, so -// the real processing needs to happen in a different thread. +// WinMIDIDevice :: Update // //========================================================================== -bool WinMIDIDevice::NeedThreadedCallback() +bool WinMIDIDevice::Update() { + // If the PlayerThread is signalled, then it's dead. + if (PlayerThread != nullptr && + WaitForSingleObject(PlayerThread, 0) == WAIT_OBJECT_0) + { + static const char *const MMErrorCodes[] = + { + "No error", + "Unspecified error", + "Device ID out of range", + "Driver failed enable", + "Device already allocated", + "Device handle is invalid", + "No device driver present", + "Memory allocation error", + "Function isn't supported", + "Error value out of range", + "Invalid flag passed", + "Invalid parameter passed", + "Handle being used simultaneously on another thread", + "Specified alias not found", + "Bad registry database", + "Registry key not found", + "Registry read error", + "Registry write error", + "Registry delete error", + "Registry value not found", + "Driver does not call DriverCallback", + "More data to be returned", + }; + static const char *const MidiErrorCodes[] = + { + "MIDI header not prepared", + "MIDI still playing something", + "MIDI no configured instruments", + "MIDI hardware is still busy", + "MIDI port no longer connected", + "MIDI invalid MIF", + "MIDI operation unsupported with open mode", + "MIDI through device 'eating' a message", + }; + DWORD code = 0xABADCAFE; + GetExitCodeThread(PlayerThread, &code); + CloseHandle(PlayerThread); + PlayerThread = nullptr; + Printf("MIDI playback failure: "); + if (code < countof(MMErrorCodes)) + { + Printf("%s\n", MMErrorCodes[code]); + } + else if (code >= MIDIERR_BASE && code < MIDIERR_BASE + countof(MidiErrorCodes)) + { + Printf("%s\n", MidiErrorCodes[code - MIDIERR_BASE]); + } + else + { + Printf("%08x\n", code); + } + return false; + } return true; } @@ -475,9 +626,9 @@ bool WinMIDIDevice::NeedThreadedCallback() void CALLBACK WinMIDIDevice::CallbackFunc(HMIDIOUT hOut, UINT uMsg, DWORD_PTR dwInstance, DWORD dwParam1, DWORD dwParam2) { WinMIDIDevice *self = (WinMIDIDevice *)dwInstance; - if (self->Callback != NULL && uMsg == MOM_DONE) + if (uMsg == MOM_DONE) { - self->Callback(self->CallbackData); + SetEvent(self->BufferDoneEvent); } } @@ -524,9 +675,9 @@ static bool IgnoreMIDIVolume(UINT id) // Now try to create an IMMDeviceEnumerator interface. If it succeeds, // we know we're using the new audio stack introduced with Vista and // should ignore this MIDI device's volume control. - if (SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, + if (SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&enumerator)) - && enumerator != NULL) + && enumerator != nullptr) { enumerator->Release(); return true; @@ -540,7 +691,13 @@ static bool IgnoreMIDIVolume(UINT id) MIDIDevice *CreateWinMIDIDevice(int mididevice) { - return new WinMIDIDevice(mididevice); + auto d = new WinMIDIDevice(mididevice); + if (d->BufferDoneEvent == nullptr || d->ExitEvent == nullptr) + { + delete d; + return nullptr; + } + return d; } #endif diff --git a/src/sound/music_xmi_midiout.cpp b/src/sound/music_xmi_midiout.cpp index 9f16098ed..fd595cb09 100644 --- a/src/sound/music_xmi_midiout.cpp +++ b/src/sound/music_xmi_midiout.cpp @@ -111,10 +111,6 @@ extern char MIDI_CommonLengths[15]; XMISong::XMISong (FileReader &reader, EMidiDevice type, const char *args) : MIDIStreamer(type, args), MusHeader(0), Songs(0) { - if (!CheckExitEvent()) - { - return; - } SongLen = reader.GetLength(); MusHeader = new uint8_t[SongLen]; if (reader.Read(MusHeader, SongLen) != SongLen)