From 930de248fd2cf19177c18269374742ec7ed8903c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 30 Mar 2008 00:04:09 +0000 Subject: [PATCH] - Applied Const's Makefile.linux changes. - Made the OPL MIDI synth available from Linux. SVN r866 (trunk) --- Makefile.linux | 20 ++++--- docs/rh-log.txt | 4 ++ src/oplsynth/music_opl_mididevice.cpp | 38 +++++++++++- src/s_advsound.cpp | 2 +- src/sound/i_musicinterns.h | 29 +++++++--- src/sound/music_midi_midiout.cpp | 7 +-- src/sound/music_midistream.cpp | 83 +++++++++++++++++++++------ src/sound/music_win_mididevice.cpp | 25 ++++++++ 8 files changed, 164 insertions(+), 44 deletions(-) diff --git a/Makefile.linux b/Makefile.linux index d4b32152c..077c56d0e 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -1,5 +1,5 @@ # created on 4/12/2006 by James Bentler - + FMOD_PREFIX = /usr/local CXX ?= g++ CC ?= gcc @@ -67,7 +67,7 @@ OBJS = $(addprefix $(OBJDIR)/,$(AOBJFILES)) $(COBJS) all: $(ZDOOMBIN) toolsandpk3 zdoom.pk3 -$(ZDOOMBIN): ccdv updaterev $(OBJDIR) $(OBJS) snes_spc/libsnes_spc.a +$(ZDOOMBIN): ccdv updaterev src/xlat/xlat_parser.h src/xlat/xlat_parser.c $(OBJDIR) $(OBJS) snes_spc/libsnes_spc.a $(CCDV) $(CXX) $(LDFLAGS) $(OBJDIR)/autostart.o \ $(filter-out %/autostart.o %/autozend.o,$(OBJS)) \ snes_spc/libsnes_spc.a $(OBJDIR)/autozend.o -o $(ZDOOMBIN) @@ -101,22 +101,22 @@ toolsandpk3: ccdv tools/makewad/makewad tools/dehsupp/dehsupp tools/lemon/lemon zdoom.pk3: toolsandpk3 ln -sf wadsrc/zdoom.pk3 ./ -snes_spc/libsnes_spc.a: +snes_spc/libsnes_spc.a: ccdv $(MAKE) -C snes_spc/ -tools/makewad/makewad: +tools/makewad/makewad: ccdv $(MAKE) -C tools/makewad/ -tools/dehsupp/dehsupp: +tools/dehsupp/dehsupp: ccdv $(MAKE) -C tools/dehsupp/ -tools/lemon/lemon: +tools/lemon/lemon: ccdv $(MAKE) -C tools/lemon/ updaterev: tools/updaterevision/updaterevision @tools/updaterevision/updaterevision . src/svnrevision.h -tools/updaterevision/updaterevision: +tools/updaterevision/updaterevision: ccdv $(MAKE) -C tools/updaterevision .PHONY : clean cleandeps cleanobjs distclean toolsandpk3 cleantools updaterev @@ -124,11 +124,14 @@ tools/updaterevision/updaterevision: clean: cleanobjs rm -f $(ZDOOMDEBUG) $(ZDOOM) $(ZDOOM).map rm -f ccdv + @$(MAKE) -C snes_spc clean cleantools: + @$(MAKE) -C wadsrc clean @$(MAKE) -C tools/makewad clean @$(MAKE) -C tools/dehsupp clean - @$(MAKE) -C tools/xlatcc clean + @$(MAKE) -C tools/updaterevision clean + @$(MAKE) -C tools/lemon clean cleandebug: rm -f $(ZDOOMDEBUG) $(DEBUGOBJ)/*.o $(DEBUGOBJ)/*.d @@ -141,6 +144,7 @@ cleanrelease: # I could use a recursive delete instead, but that could be dangerous... distclean: clean cleandeps -rmdir $(RELEASEOBJ) $(DEBUGOBJ) + rm -f zdoom.pk3 cleandeps: rm -f $(RELEASEOBJ)/*.d $(DEBUGOBJ)/*.d diff --git a/docs/rh-log.txt b/docs/rh-log.txt index be6638080..34e0293e1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +March 29, 2008 +- Applied Const's Makefile.linux changes. +- Made the OPL MIDI synth available from Linux. + March 29, 2008 (Changes by Graf Zahl) - Added SnowKate709's A_DamageMaster/A_DamageChildren patch. - Added a SFX_TRANSFERAMBUSHFLAG for A_SpawnItemEx. diff --git a/src/oplsynth/music_opl_mididevice.cpp b/src/oplsynth/music_opl_mididevice.cpp index e8383c371..6921b9414 100644 --- a/src/oplsynth/music_opl_mididevice.cpp +++ b/src/oplsynth/music_opl_mididevice.cpp @@ -103,7 +103,7 @@ OPLMIDIDevice::~OPLMIDIDevice() // //========================================================================== -int OPLMIDIDevice::Open(void (*callback)(UINT, void *, DWORD, DWORD), void *userdata) +int OPLMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata) { if (io == NULL || io->OPLinit(TwoChips + 1, uint(OPL_SAMPLE_RATE))) { @@ -245,15 +245,34 @@ void OPLMIDIDevice::Stop() } } +//========================================================================== +// +// OPLMIDIDevice :: StreamOutSync +// +// This version is called from the main game thread and needs to +// synchronize with the player thread. +// +//========================================================================== + +int OPLMIDIDevice::StreamOutSync(MIDIHDR *header) +{ + Serialize(); + StreamOut(header); + Unserialize(); + return 0; +} + //========================================================================== // // OPLMIDIDevice :: StreamOut // +// This version is called from the player thread so does not need to +// arbitrate for access to the Events pointer. +// //========================================================================== int OPLMIDIDevice::StreamOut(MIDIHDR *header) { - Serialize(); header->lpNext = NULL; if (Events == NULL) { @@ -269,7 +288,6 @@ int OPLMIDIDevice::StreamOut(MIDIHDR *header) { } *p = header; } - Unserialize(); return 0; } @@ -309,6 +327,20 @@ bool OPLMIDIDevice::FakeVolume() return false; } +//========================================================================== +// +// OPLMIDIDevice :: NeedThreadedCallabck +// +// OPL can service the callback directly rather than using a separate +// thread. +// +//========================================================================== + +bool OPLMIDIDevice::NeedThreadedCallback() +{ + return false; +} + //========================================================================== // // OPLMIDIDevice :: Pause diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 8fc923cc5..3ab80215f 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -535,7 +535,7 @@ static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc) sfx->bRandomHeader = false; sfx->link = sfxinfo_t::NO_LINK; sfx->bTentative = false; - if (sfx->NearLimit < 0) sfx->NearLimit = 2; + if (sfx->NearLimit == (BYTE)-1) sfx->NearLimit = 2; //sfx->PitchMask = CurrentPitchMask; } else diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index a26992747..c94324138 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -56,8 +56,6 @@ public: bool m_NotStartedYet; // Song has been created but not yet played }; -#ifdef _WIN32 - // A device that provides a WinMM-like MIDI streaming interface ------------- #ifndef _WIN32 @@ -80,6 +78,8 @@ enum MOD_SWSYNTH }; +typedef BYTE *LPSTR; + #define MEVT_TEMPO ((BYTE)1) #define MEVT_NOP ((BYTE)2) #define MEVT_LONGMSG ((BYTE)128) @@ -103,16 +103,19 @@ public: 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 Resume() = 0; virtual void Stop() = 0; virtual int PrepareHeader(MIDIHDR *data) = 0; virtual int UnprepareHeader(MIDIHDR *data) = 0; virtual bool FakeVolume() = 0; virtual bool Pause(bool paused) = 0; + virtual bool NeedThreadedCallback() = 0; }; // WinMM implementation of a MIDI output device ----------------------------- +#ifdef _WIN32 class WinMIDIDevice : public MIDIDevice { public: @@ -125,11 +128,13 @@ public: int SetTempo(int tempo); int SetTimeDiv(int timediv); int StreamOut(MIDIHDR *data); + int StreamOutSync(MIDIHDR *data); int Resume(); void Stop(); int PrepareHeader(MIDIHDR *data); int UnprepareHeader(MIDIHDR *data); bool FakeVolume(); + bool NeedThreadedCallback(); bool Pause(bool paused); protected: @@ -143,6 +148,7 @@ protected: void (*Callback)(unsigned int, void *, DWORD, DWORD); void *CallbackData; }; +#endif // OPL implementation of a MIDI output device ------------------------------- @@ -158,11 +164,13 @@ public: int SetTempo(int tempo); int SetTimeDiv(int timediv); int StreamOut(MIDIHDR *data); + int StreamOutSync(MIDIHDR *data); int Resume(); void Stop(); int PrepareHeader(MIDIHDR *data); int UnprepareHeader(MIDIHDR *data); bool FakeVolume(); + bool NeedThreadedCallback(); bool Pause(bool paused); protected: @@ -202,14 +210,13 @@ public: void Update(); protected: - static DWORD WINAPI PlayerProc (LPVOID lpParameter); - static void Callback(UINT uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2); - DWORD PlayerLoop(); + static void Callback(unsigned int uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2); + void OutputVolume (DWORD volume); int FillBuffer(int buffer_num, int max_events, DWORD max_time); bool ServiceEvent(); int VolumeControllerChange(int channel, int volume); - + // Virtuals for subclasses to override virtual void CheckCaps(); virtual void DoInitialSetup() = 0; @@ -229,11 +236,16 @@ protected: SONG_ERROR }; - MIDIDevice *MIDI; +#ifdef _WIN32 + static DWORD WINAPI PlayerProc (LPVOID lpParameter); + DWORD PlayerLoop(); + HANDLE PlayerThread; HANDLE ExitEvent; HANDLE BufferDoneEvent; +#endif + MIDIDevice *MIDI; DWORD Events[2][MAX_EVENTS*3]; MIDIHDR Buffer[2]; int BufferNum; @@ -248,6 +260,7 @@ protected: BYTE ChannelVolumes[16]; DWORD Volume; bool UseOPLDevice; + bool CallbackIsThreaded; }; // MUS file played with a MIDI stream --------------------------------------- @@ -300,8 +313,6 @@ protected: WORD DesignationMask; }; -#endif /* _WIN32 */ - // Anything supported by FMOD out of the box -------------------------------- class StreamSong : public MusInfo diff --git a/src/sound/music_midi_midiout.cpp b/src/sound/music_midi_midiout.cpp index 333c15740..6df981c94 100644 --- a/src/sound/music_midi_midiout.cpp +++ b/src/sound/music_midi_midiout.cpp @@ -35,8 +35,6 @@ ** have them sound right. */ -#ifdef _WIN32 - // HEADER FILES ------------------------------------------------------------ #include "i_musicinterns.h" @@ -110,10 +108,12 @@ MIDISong2::MIDISong2 (FILE *file, char *musiccache, int len, bool opl) int p; int i; +#ifdef _WIN32 if (ExitEvent == NULL) { return; } +#endif MusHeader = new BYTE[len]; if (file != NULL) { @@ -722,9 +722,8 @@ MIDISong2::TrackInfo *MIDISong2::FindNextDue () void MIDISong2::SetTempo(int new_tempo) { - if (MMSYSERR_NOERROR == MIDI->SetTempo(new_tempo)) + if (0 == MIDI->SetTempo(new_tempo)) { Tempo = new_tempo; } } -#endif diff --git a/src/sound/music_midistream.cpp b/src/sound/music_midistream.cpp index fa959c2ab..fcd50d709 100644 --- a/src/sound/music_midistream.cpp +++ b/src/sound/music_midistream.cpp @@ -32,8 +32,6 @@ ** */ -#ifdef _WIN32 - // HEADER FILES ------------------------------------------------------------ #include "i_musicinterns.h" @@ -55,7 +53,9 @@ EXTERN_CVAR(Float, snd_musicvolume) +#ifdef _WIN32 extern UINT mididevice; +#endif // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -70,9 +70,13 @@ extern UINT mididevice; //========================================================================== MIDIStreamer::MIDIStreamer(bool opl) -: MIDI(0), PlayerThread(0), ExitEvent(0), BufferDoneEvent(0), +: MIDI(0), +#ifdef _WIN32 + PlayerThread(0), ExitEvent(0), BufferDoneEvent(0), +#endif Division(0), InitialTempo(500000), UseOPLDevice(opl) { +#ifdef _WIN32 BufferDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (BufferDoneEvent == NULL) { @@ -84,6 +88,7 @@ MIDIStreamer::MIDIStreamer(bool opl) Printf(PRINT_BOLD, "Could not create exit event for MIDI playback\n"); return; } +#endif } //========================================================================== @@ -95,6 +100,7 @@ MIDIStreamer::MIDIStreamer(bool opl) MIDIStreamer::~MIDIStreamer() { Stop(); +#ifdef _WIN32 if (ExitEvent != NULL) { CloseHandle(ExitEvent); @@ -103,6 +109,7 @@ MIDIStreamer::~MIDIStreamer() { CloseHandle(BufferDoneEvent); } +#endif if (MIDI != NULL) { delete MIDI; @@ -130,7 +137,11 @@ bool MIDIStreamer::IsMIDI() const bool MIDIStreamer::IsValid() const { +#ifdef _WIN32 return ExitEvent != NULL && Division != 0; +#else + return Division != 0; +#endif } //========================================================================== @@ -164,14 +175,20 @@ void MIDIStreamer::Play (bool looping) InitialPlayback = true; assert(MIDI == NULL); - if (UseOPLDevice) - { - MIDI = new OPLMIDIDevice; - } - else +#ifdef _WIN32 + if (!UseOPLDevice) { MIDI = new WinMIDIDevice(mididevice); } + else +#endif + { + MIDI = new OPLMIDIDevice; + } + +#ifndef _WIN32 + assert(MIDI->NeedThreadedCallback() == false); +#endif if (0 != MIDI->Open(Callback, this)) { @@ -192,8 +209,10 @@ void MIDIStreamer::Play (bool looping) MusicVolumeChanged(); // set volume to current music's properties +#ifdef _WIN32 ResetEvent(ExitEvent); ResetEvent(BufferDoneEvent); +#endif // Fill the initial buffers for the song. BufferNum = 0; @@ -202,7 +221,7 @@ void MIDIStreamer::Play (bool looping) int res = FillBuffer(BufferNum, MAX_EVENTS, MAX_TIME); if (res == SONG_MORE) { - if (0 != MIDI->StreamOut(&Buffer[BufferNum])) + if (0 != MIDI->StreamOutSync(&Buffer[BufferNum])) { Printf ("Initial midiStreamOut failed\n"); Stop(); @@ -231,13 +250,22 @@ void MIDIStreamer::Play (bool looping) } else { - PlayerThread = CreateThread(NULL, 0, PlayerProc, this, 0, &tid); - if (PlayerThread == NULL) +#ifdef _WIN32 + if (MIDI->NeedThreadedCallback()) { - Printf ("Creating MIDI thread failed\n"); - Stop(); + 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; } @@ -297,13 +325,15 @@ void MIDIStreamer::Resume () void MIDIStreamer::Stop () { EndQueued = 2; - if (PlayerThread) +#ifdef _WIN32 + if (PlayerThread != NULL) { SetEvent(ExitEvent); WaitForSingleObject(PlayerThread, INFINITE); CloseHandle(PlayerThread); PlayerThread = NULL; } +#endif if (MIDI != NULL && MIDI->IsOpen()) { MIDI->Stop(); @@ -399,7 +429,7 @@ int MIDIStreamer::VolumeControllerChange(int channel, int volume) // //========================================================================== -void MIDIStreamer::Callback(UINT uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2) +void MIDIStreamer::Callback(unsigned int uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2) { MIDIStreamer *self = (MIDIStreamer *)userdata; @@ -409,7 +439,17 @@ void MIDIStreamer::Callback(UINT uMsg, void *userdata, DWORD dwParam1, DWORD dwP } if (uMsg == MOM_DONE) { - SetEvent(self->BufferDoneEvent); +#ifdef _WIN32 + if (self->PlayerThread != NULL) + { + SetEvent(self->BufferDoneEvent); + } + else +#else + { + self->ServiceEvent(); + } +#endif } } @@ -424,6 +464,7 @@ void MIDIStreamer::Callback(UINT uMsg, void *userdata, DWORD dwParam1, DWORD dwP void MIDIStreamer::Update() { +#ifdef _WIN32 // If the PlayerThread is signalled, then it's dead. if (PlayerThread != NULL && WaitForSingleObject(PlayerThread, 0) == WAIT_OBJECT_0) @@ -433,6 +474,7 @@ void MIDIStreamer::Update() Printf ("MIDI playback failure\n"); Stop(); } +#endif } //========================================================================== @@ -443,10 +485,12 @@ void MIDIStreamer::Update() // //========================================================================== +#ifdef _WIN32 DWORD WINAPI MIDIStreamer::PlayerProc (LPVOID lpParameter) { return ((MIDIStreamer *)lpParameter)->PlayerLoop(); } +#endif //========================================================================== // @@ -456,6 +500,7 @@ DWORD WINAPI MIDIStreamer::PlayerProc (LPVOID lpParameter) // //========================================================================== +#ifdef _WIN32 DWORD MIDIStreamer::PlayerLoop() { HANDLE events[2] = { BufferDoneEvent, ExitEvent }; @@ -482,6 +527,7 @@ DWORD MIDIStreamer::PlayerLoop() } } } +#endif //========================================================================== // @@ -507,7 +553,8 @@ fill: switch (FillBuffer(BufferNum, MAX_EVENTS, MAX_TIME)) { case SONG_MORE: - if (0 != MIDI->StreamOut(&Buffer[BufferNum])) + if ((MIDI->NeedThreadedCallback() && 0 != MIDI->StreamOutSync(&Buffer[BufferNum])) || + (!MIDI->NeedThreadedCallback() && 0 != MIDI->StreamOut(&Buffer[BufferNum]))) { return true; } @@ -641,5 +688,3 @@ MIDIDevice::MIDIDevice() MIDIDevice::~MIDIDevice() { } - -#endif diff --git a/src/sound/music_win_mididevice.cpp b/src/sound/music_win_mididevice.cpp index f164f6a2e..56080ec32 100644 --- a/src/sound/music_win_mididevice.cpp +++ b/src/sound/music_win_mididevice.cpp @@ -228,6 +228,17 @@ int WinMIDIDevice::StreamOut(MIDIHDR *header) return midiStreamOut(MidiOut, header, sizeof(MIDIHDR)); } +//========================================================================== +// +// WinMIDIDevice :: StreamOutSync +// +//========================================================================== + +int WinMIDIDevice::StreamOutSync(MIDIHDR *header) +{ + return midiStreamOut(MidiOut, header, sizeof(MIDIHDR)); +} + //========================================================================== // // WinMIDIDevice :: PrepareHeader @@ -264,6 +275,20 @@ bool WinMIDIDevice::FakeVolume() return true; } +//========================================================================== +// +// 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. +// +//========================================================================== + +bool WinMIDIDevice::NeedThreadedCallback() +{ + return true; +} + //========================================================================== // // WinMIDIDevice :: CallbackFunc static