diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index d8638afcf..2bf3dfb7c 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -39,15 +39,17 @@ EXTERN_CVAR (Float, timidity_mastervolume) // A device that provides a WinMM-like MIDI streaming interface ------------- -#ifndef _WIN32 -struct MIDIHDR +struct MidiHeader { uint8_t *lpData; - DWORD dwBufferLength; - DWORD dwBytesRecorded; - MIDIHDR *lpNext; + uint32_t dwBufferLength; + uint32_t dwBytesRecorded; + MidiHeader *lpNext; }; + +#ifndef _WIN32 + enum { MOD_MIDIPORT = 1, @@ -92,12 +94,12 @@ public: virtual int GetTechnology() const = 0; virtual int SetTempo(int tempo) = 0; virtual int SetTimeDiv(int timediv) = 0; - virtual int StreamOut(MIDIHDR *data) = 0; - virtual int StreamOutSync(MIDIHDR *data) = 0; + virtual int StreamOut(MidiHeader *data) = 0; + virtual int StreamOutSync(MidiHeader *data) = 0; virtual int Resume() = 0; virtual void Stop() = 0; - virtual int PrepareHeader(MIDIHDR *data); - virtual int UnprepareHeader(MIDIHDR *data); + virtual int PrepareHeader(MidiHeader *data); + virtual int UnprepareHeader(MidiHeader *data); virtual bool FakeVolume(); virtual bool Pause(bool paused) = 0; virtual bool NeedThreadedCallback(); @@ -125,12 +127,12 @@ public: int GetTechnology() const; int SetTempo(int tempo); int SetTimeDiv(int timediv); - int StreamOut(MIDIHDR *data); - int StreamOutSync(MIDIHDR *data); + int StreamOut(MidiHeader *data); + int StreamOutSync(MidiHeader *data); int Resume(); void Stop(); - int PrepareHeader(MIDIHDR *data); - int UnprepareHeader(MIDIHDR *data); + int PrepareHeader(MidiHeader *data); + int UnprepareHeader(MidiHeader *data); bool FakeVolume(); bool NeedThreadedCallback(); bool Pause(bool paused); @@ -142,6 +144,8 @@ protected: HMIDISTRM MidiOut; UINT DeviceID; DWORD SavedVolume; + MIDIHDR WinMidiHeaders[2]; + int HeaderIndex; bool VolumeWorks; void (*Callback)(unsigned int, void *); @@ -162,11 +166,11 @@ public: virtual int GetTechnology() const override; virtual int SetTempo(int tempo) override; virtual int SetTimeDiv(int timediv) override; - virtual int StreamOut(MIDIHDR *data) override; - virtual int StreamOutSync(MIDIHDR *data) override; + virtual int StreamOut(MidiHeader *data) override; + virtual int StreamOutSync(MidiHeader *data) override; virtual int Resume() override; virtual void Stop() override; - virtual int PrepareHeader(MIDIHDR* data) override; + virtual int PrepareHeader(MidiHeader* data) override; virtual bool FakeVolume() override { return true; } virtual bool Pause(bool paused) override; virtual bool Preprocess(MIDIStreamer *song, bool looping) override; @@ -201,8 +205,8 @@ public: bool Pause(bool paused); int Resume(); void Stop(); - int StreamOut(MIDIHDR *data); - int StreamOutSync(MIDIHDR *data); + int StreamOut(MidiHeader *data); + int StreamOutSync(MidiHeader *data); int SetTempo(int tempo); int SetTimeDiv(int timediv); FString GetStats(); @@ -275,8 +279,8 @@ public: int GetTechnology() const; int SetTempo(int tempo); int SetTimeDiv(int timediv); - int StreamOut(MIDIHDR *data); - int StreamOutSync(MIDIHDR *data); + int StreamOut(MidiHeader *data); + int StreamOutSync(MidiHeader *data); int Resume(); void Stop(); bool Pause(bool paused); @@ -288,7 +292,7 @@ protected: double Division; double SamplesPerTick; double NextTickIn; - MIDIHDR *Events; + MidiHeader *Events; bool Started; DWORD Position; int SampleRate; @@ -541,7 +545,7 @@ protected: MIDIDevice *MIDI; DWORD Events[2][MAX_EVENTS*3]; - MIDIHDR Buffer[2]; + MidiHeader Buffer[2]; int BufferNum; int EndQueued; bool VolumeChanged; diff --git a/src/sound/music_audiotoolbox_mididevice.cpp b/src/sound/music_audiotoolbox_mididevice.cpp index 8d36a0f5a..c9d075922 100644 --- a/src/sound/music_audiotoolbox_mididevice.cpp +++ b/src/sound/music_audiotoolbox_mididevice.cpp @@ -114,12 +114,12 @@ int AudioToolboxMIDIDevice::SetTimeDiv(int timediv) return 0; } -int AudioToolboxMIDIDevice::StreamOut(MIDIHDR* data) +int AudioToolboxMIDIDevice::StreamOut(MidiHeader* data) { return 0; } -int AudioToolboxMIDIDevice::StreamOutSync(MIDIHDR* data) +int AudioToolboxMIDIDevice::StreamOutSync(MidiHeader* data) { return 0; } @@ -170,9 +170,9 @@ void AudioToolboxMIDIDevice::Stop() AT_MIDI_CHECK_ERROR(MusicPlayerStop(m_player)); } -int AudioToolboxMIDIDevice::PrepareHeader(MIDIHDR* data) +int AudioToolboxMIDIDevice::PrepareHeader(MidiHeader* data) { - MIDIHDR* events = data; + MidiHeader* events = data; DWORD position = 0; while (nullptr != events) diff --git a/src/sound/music_midistream.cpp b/src/sound/music_midistream.cpp index 58214d1a7..be1ad1924 100644 --- a/src/sound/music_midistream.cpp +++ b/src/sound/music_midistream.cpp @@ -96,6 +96,7 @@ MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args) #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) @@ -124,6 +125,7 @@ MIDIStreamer::MIDIStreamer(const char *dumpname, EMidiDevice type) #endif MIDI(0), Division(0), InitialTempo(500000), DeviceType(type), DumpFilename(dumpname) { + memset(Buffer, 0, sizeof(Buffer)); #ifdef _WIN32 BufferDoneEvent = NULL; ExitEvent = NULL; @@ -989,9 +991,9 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time) } events = MakeEvents(events, max_event_p, max_time); } - memset(&Buffer[buffer_num], 0, sizeof(MIDIHDR)); - Buffer[buffer_num].lpData = (LPSTR)Events[buffer_num]; - Buffer[buffer_num].dwBufferLength = DWORD((LPSTR)events - Buffer[buffer_num].lpData); + memset(&Buffer[buffer_num], 0, sizeof(MidiHeader)); + Buffer[buffer_num].lpData = (uint8_t *)Events[buffer_num]; + Buffer[buffer_num].dwBufferLength = uint32_t((uint8_t *)events - Buffer[buffer_num].lpData); Buffer[buffer_num].dwBytesRecorded = Buffer[buffer_num].dwBufferLength; if (0 != (i = MIDI->PrepareHeader(&Buffer[buffer_num]))) { @@ -1021,9 +1023,9 @@ int MIDIStreamer::FillStopBuffer(int buffer_num) events[2] = MEVT_NOP << 24; events += 3; - memset(&Buffer[buffer_num], 0, sizeof(MIDIHDR)); - Buffer[buffer_num].lpData = (LPSTR)Events[buffer_num]; - Buffer[buffer_num].dwBufferLength = DWORD((LPSTR)events - Buffer[buffer_num].lpData); + memset(&Buffer[buffer_num], 0, sizeof(MidiHeader)); + Buffer[buffer_num].lpData = (uint8_t*)Events[buffer_num]; + Buffer[buffer_num].dwBufferLength = DWORD((uint8_t*)events - Buffer[buffer_num].lpData); Buffer[buffer_num].dwBytesRecorded = Buffer[buffer_num].dwBufferLength; if (0 != (i = MIDI->PrepareHeader(&Buffer[buffer_num]))) { @@ -1456,7 +1458,7 @@ bool MIDIDevice::Preprocess(MIDIStreamer *song, bool looping) // //========================================================================== -int MIDIDevice::PrepareHeader(MIDIHDR *header) +int MIDIDevice::PrepareHeader(MidiHeader *header) { return 0; } @@ -1469,7 +1471,7 @@ int MIDIDevice::PrepareHeader(MIDIHDR *header) // //========================================================================== -int MIDIDevice::UnprepareHeader(MIDIHDR *header) +int MIDIDevice::UnprepareHeader(MidiHeader *header) { return 0; } diff --git a/src/sound/music_pseudo_mididevice.cpp b/src/sound/music_pseudo_mididevice.cpp index 388c31931..2f79b2a2f 100644 --- a/src/sound/music_pseudo_mididevice.cpp +++ b/src/sound/music_pseudo_mididevice.cpp @@ -177,7 +177,7 @@ bool PseudoMIDIDevice::Pause(bool paused) // //========================================================================== -int PseudoMIDIDevice::StreamOutSync(MIDIHDR *header) +int PseudoMIDIDevice::StreamOutSync(MidiHeader *header) { assert(0); return 0; @@ -189,7 +189,7 @@ int PseudoMIDIDevice::StreamOutSync(MIDIHDR *header) // //========================================================================== -int PseudoMIDIDevice::StreamOut(MIDIHDR *header) +int PseudoMIDIDevice::StreamOut(MidiHeader *header) { assert(0); return 0; diff --git a/src/sound/music_softsynth_mididevice.cpp b/src/sound/music_softsynth_mididevice.cpp index d0e8b7ef5..7073f3991 100644 --- a/src/sound/music_softsynth_mididevice.cpp +++ b/src/sound/music_softsynth_mididevice.cpp @@ -238,7 +238,7 @@ void SoftSynthMIDIDevice::Stop() // //========================================================================== -int SoftSynthMIDIDevice::StreamOutSync(MIDIHDR *header) +int SoftSynthMIDIDevice::StreamOutSync(MidiHeader *header) { CritSec.Enter(); StreamOut(header); @@ -255,7 +255,7 @@ int SoftSynthMIDIDevice::StreamOutSync(MIDIHDR *header) // //========================================================================== -int SoftSynthMIDIDevice::StreamOut(MIDIHDR *header) +int SoftSynthMIDIDevice::StreamOut(MidiHeader *header) { header->lpNext = NULL; if (Events == NULL) @@ -266,7 +266,7 @@ int SoftSynthMIDIDevice::StreamOut(MIDIHDR *header) } else { - MIDIHDR **p; + MidiHeader **p; for (p = &Events; *p != NULL; p = &(*p)->lpNext) { } diff --git a/src/sound/music_win_mididevice.cpp b/src/sound/music_win_mididevice.cpp index f6b9bc21c..9af76038f 100644 --- a/src/sound/music_win_mididevice.cpp +++ b/src/sound/music_win_mididevice.cpp @@ -75,6 +75,8 @@ WinMIDIDevice::WinMIDIDevice(int dev_id) { DeviceID = MAX(dev_id, 0); MidiOut = 0; + HeaderIndex = 0; + memset(WinMidiHeaders, 0, sizeof(WinMidiHeaders)); } //========================================================================== @@ -323,9 +325,11 @@ bool WinMIDIDevice::Pause(bool paused) // //========================================================================== -int WinMIDIDevice::StreamOut(MIDIHDR *header) +int WinMIDIDevice::StreamOut(MidiHeader *header) { - return midiStreamOut(MidiOut, header, sizeof(MIDIHDR)); + auto syshdr = (MIDIHDR*)header->lpNext; + assert(syshdr == &WinMidiHeaders[0] || syshdr == &WinMidiHeaders[1]); + return midiStreamOut(MidiOut, syshdr, sizeof(MIDIHDR)); } //========================================================================== @@ -334,9 +338,11 @@ int WinMIDIDevice::StreamOut(MIDIHDR *header) // //========================================================================== -int WinMIDIDevice::StreamOutSync(MIDIHDR *header) +int WinMIDIDevice::StreamOutSync(MidiHeader *header) { - return midiStreamOut(MidiOut, header, sizeof(MIDIHDR)); + auto syshdr = (MIDIHDR*)header->lpNext; + assert(syshdr == &WinMidiHeaders[0] || syshdr == &WinMidiHeaders[1]); + return midiStreamOut(MidiOut, syshdr, sizeof(MIDIHDR)); } //========================================================================== @@ -345,9 +351,19 @@ int WinMIDIDevice::StreamOutSync(MIDIHDR *header) // //========================================================================== -int WinMIDIDevice::PrepareHeader(MIDIHDR *header) +int WinMIDIDevice::PrepareHeader(MidiHeader *header) { - return midiOutPrepareHeader((HMIDIOUT)MidiOut, header, sizeof(MIDIHDR)); + // This code depends on the driving implementation only having two buffers that get passed alternatingly. + // If there were more buffers this would require more intelligent handling. + assert(header->lpNext == nullptr); + MIDIHDR *syshdr = &WinMidiHeaders[HeaderIndex ^= 1]; + memset(syshdr, 0, sizeof(MIDIHDR)); + syshdr->lpData = (LPSTR)header->lpData; + syshdr->dwBufferLength = header->dwBufferLength; + syshdr->dwBytesRecorded = header->dwBytesRecorded; + // this device does not use the lpNext pointer to link MIDI events so use it to point to the system data structure. + header->lpNext = (MidiHeader*)syshdr; + return midiOutPrepareHeader((HMIDIOUT)MidiOut, syshdr, sizeof(MIDIHDR)); } //========================================================================== @@ -356,9 +372,19 @@ int WinMIDIDevice::PrepareHeader(MIDIHDR *header) // //========================================================================== -int WinMIDIDevice::UnprepareHeader(MIDIHDR *header) +int WinMIDIDevice::UnprepareHeader(MidiHeader *header) { - return midiOutUnprepareHeader((HMIDIOUT)MidiOut, header, sizeof(MIDIHDR)); + auto syshdr = (MIDIHDR*)header->lpNext; + if (syshdr != nullptr) + { + assert(syshdr == &WinMidiHeaders[0] || syshdr == &WinMidiHeaders[1]); + header->lpNext = nullptr; + return midiOutUnprepareHeader((HMIDIOUT)MidiOut, syshdr, sizeof(MIDIHDR)); + } + else + { + return MMSYSERR_NOERROR; + } } //==========================================================================