cleanup of MIDI code dependencies

* make the critical section local to the respective platform instead of polluting everything with system specific symbols.
* moved system specific class declarations into the source file instead of having them in the global header.

This commit temporarily disables the Windows system device because it cannot be done without polluting the global header and still needs a bit of refactoring.
This commit is contained in:
Christoph Oelckers 2017-03-10 16:12:52 +01:00
parent d75e09f545
commit 8d6fe24945
23 changed files with 456 additions and 378 deletions

View file

@ -602,6 +602,7 @@ endif()
# Start defining source files for ZDoom
set( PLAT_WIN32_SOURCES
win32/eaxedit.cpp
win32/critsec.cpp
win32/fb_d3d9.cpp
win32/fb_d3d9_wipe.cpp
win32/fb_ddraw.cpp
@ -626,6 +627,7 @@ set( PLAT_POSIX_SOURCES
posix/i_steam.cpp )
set( PLAT_SDL_SOURCES
posix/sdl/crashcatcher.c
posix/sdl/critsec.cpp
posix/sdl/hardware.cpp
posix/sdl/i_gui.cpp
posix/sdl/i_input.cpp

View file

@ -19,7 +19,7 @@ typedef int INTBOOL;
#define GUID_DEFINED
typedef struct _GUID
{
DWORD Data1;
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
@ -46,7 +46,7 @@ union QWORD_UNION
#define FRACUNIT (1<<FRACBITS)
typedef int32_t fixed_t;
typedef DWORD dsfixed_t; // fixedpt used by span drawer
typedef uint32_t dsfixed_t; // fixedpt used by span drawer
#define FIXED_MAX (signed)(0x7fffffff)
#define FIXED_MIN (signed)(0x80000000)

View file

@ -33,9 +33,25 @@
#include "critsec.h"
#include <pthread.h>
class FInternalCriticalSection
{
public:
FInternalCriticalSection();
~FInternalCriticalSection();
void Enter();
void Leave();
private:
pthread_mutex_t m_mutex;
};
// TODO: add error handling
FCriticalSection::FCriticalSection()
FInternalCriticalSection::FInternalCriticalSection()
{
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
@ -46,17 +62,38 @@ FCriticalSection::FCriticalSection()
pthread_mutexattr_destroy(&attributes);
}
FCriticalSection::~FCriticalSection()
FInternalCriticalSection::~FInternalCriticalSection()
{
pthread_mutex_destroy(&m_mutex);
}
void FCriticalSection::Enter()
void FInternalCriticalSection::Enter()
{
pthread_mutex_lock(&m_mutex);
}
void FCriticalSection::Leave()
void FInternalCriticalSection::Leave()
{
pthread_mutex_unlock(&m_mutex);
}
FInternalCriticalSection *CreateCriticalSection()
{
return new FInternalCriticalSection();
}
void DeleteCriticalSection(FInternalCriticalSection *c)
{
delete c;
}
void EnterCriticalSection(FInternalCriticalSection *c)
{
c->Enter();
}
void LeaveCriticalSection(FInternalCriticalSection *c)
{
c->Leave();
}

View file

@ -1,53 +0,0 @@
/*
** critsec.h
**
**---------------------------------------------------------------------------
** Copyright 2014 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef CRITSEC_H
#define CRITSEC_H
#include <pthread.h>
class FCriticalSection
{
public:
FCriticalSection();
~FCriticalSection();
void Enter();
void Leave();
private:
pthread_mutex_t m_mutex;
};
#endif

View file

@ -2,17 +2,14 @@
// object similar to a mutex but optimized for access by threads belonging to
// only one process, hence the class name.)
#ifndef CRITSEC_H
#define CRITSEC_H
#include "SDL.h"
#include "SDL_thread.h"
#include "i_system.h"
class FCriticalSection
class FInternalCriticalSection
{
public:
FCriticalSection()
FSDLCriticalSection()
{
CritSec = SDL_CreateMutex();
if (CritSec == NULL)
@ -20,7 +17,7 @@ public:
I_FatalError("Failed to create a critical section mutex.");
}
}
~FCriticalSection()
~FSDLCriticalSection()
{
if (CritSec != NULL)
{
@ -45,4 +42,22 @@ private:
SDL_mutex *CritSec;
};
#endif
FInternalCriticalSection *CreateCriticalSection()
{
return new FInternalCriticalSection();
}
void DeleteCriticalSection(FInternalCriticalSection *c)
{
delete c;
}
void EnterCriticalSection(FInternalCriticalSection *c)
{
c->Enter();
}
void LeaveCriticalSection(FInternalCriticalSection *c)
{
c->Leave();
}

View file

@ -36,6 +36,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#define USE_WINDOWS_DWORD
#else
#include <sys/types.h>
#include <sys/wait.h>
@ -46,8 +47,6 @@
#include <wordexp.h>
#include <stdio.h>
#include "mus2midi.h"
#define FALSE 0
#define TRUE 1
extern void ChildSigHandler (int signum);
#endif
@ -347,7 +346,7 @@ static MIDIStreamer *CreateMIDIStreamer(FileReader &reader, EMidiDevice devtype,
//
//==========================================================================
static EMIDIType IdentifyMIDIType(DWORD *id, int size)
static EMIDIType IdentifyMIDIType(uint32_t *id, int size)
{
// Check for MUS format
// Tolerate sloppy wads by searching up to 32 bytes for the header
@ -400,7 +399,7 @@ MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device)
{
MusInfo *info = NULL;
const char *fmt;
DWORD id[32/4];
uint32_t id[32/4];
if (nomusic)
{
@ -501,7 +500,7 @@ retry_as_sndsys:
// Check for CDDA "format"
if (id[0] == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24)))
{
DWORD subid;
uint32_t subid;
reader->Seek(8, SEEK_CUR);
if (reader->Read (&subid, 4) != 4)
@ -628,7 +627,7 @@ static bool ungzip(uint8_t *data, int complen, TArray<uint8_t> &newdata)
}
// Decompress
isize = LittleLong(*(DWORD *)(data + complen - 4));
isize = LittleLong(*(uint32_t *)(data + complen - 4));
newdata.Resize(isize);
stream.next_in = (Bytef *)compstart;

View file

@ -1,24 +1,4 @@
#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 <windows.h>
#include <mmsystem.h>
#else
#define FALSE 0
#define TRUE 1
#endif
#ifdef __APPLE__
#include <AudioToolbox/AudioToolbox.h>
#endif // __APPLE__
#include "tempfiles.h"
#include "oplsynth/opl_mus_player.h"
#include "c_cvars.h"
@ -105,83 +85,13 @@ public:
virtual FString GetStats();
};
// WinMM implementation of a MIDI output device -----------------------------
#ifdef _WIN32
class WinMIDIDevice : public MIDIDevice
{
public:
WinMIDIDevice(int dev_id);
~WinMIDIDevice();
int Open(MidiCallback, void *userdata);
void Close();
bool IsOpen() const;
int GetTechnology() const;
int SetTempo(int tempo);
int SetTimeDiv(int timediv);
int StreamOut(MidiHeader *data);
int StreamOutSync(MidiHeader *data);
int Resume();
void Stop();
int PrepareHeader(MidiHeader *data);
int UnprepareHeader(MidiHeader *data);
bool FakeVolume();
bool NeedThreadedCallback();
bool Pause(bool paused);
void PrecacheInstruments(const uint16_t *instruments, int count);
protected:
static void CALLBACK CallbackFunc(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD);
HMIDISTRM MidiOut;
UINT DeviceID;
DWORD SavedVolume;
MIDIHDR WinMidiHeaders[2];
int HeaderIndex;
bool VolumeWorks;
MidiCallback Callback;
void *CallbackData;
};
MIDIDevice *CreateWinMIDIDevice(int mididevice);
#elif defined __APPLE__
MIDIDevice *CreateAudioToolboxMIDIDevice(int mididevice);
#endif
// AudioToolbox implementation of a MIDI output device ----------------------
#ifdef __APPLE__
class AudioToolboxMIDIDevice : public MIDIDevice
{
public:
virtual int Open(MidiCallback, void *userData) override;
virtual void Close() override;
virtual bool IsOpen() const override;
virtual int GetTechnology() const override;
virtual int SetTempo(int tempo) override;
virtual int SetTimeDiv(int timediv) override;
virtual int StreamOut(MidiHeader *data) override;
virtual int StreamOutSync(MidiHeader *data) override;
virtual int Resume() override;
virtual void Stop() 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;
private:
MusicPlayer m_player = nullptr;
MusicSequence m_sequence = nullptr;
AudioUnit m_audioUnit = nullptr;
CFRunLoopTimerRef m_timer = nullptr;
MusicTimeStamp m_length = 0;
MidiCallback Callback;
Callback m_callback = nullptr;
void* m_userData = nullptr;
static void TimerCallback(CFRunLoopTimerRef timer, void* info);
};
#endif // __APPLE__
MIDIDevice *CreateTimidityPPMIDIDevice(const char *args);
// Base class for pseudo-MIDI devices ---------------------------------------
@ -218,46 +128,6 @@ public:
bool Preprocess(MIDIStreamer *song, bool looping);
};
// MIDI file played with TiMidity++ and possibly streamed through the Sound System
class TimidityPPMIDIDevice : public PseudoMIDIDevice
{
public:
TimidityPPMIDIDevice(const char *args);
~TimidityPPMIDIDevice();
int Open(MidiCallback, void *userdata);
bool Preprocess(MIDIStreamer *song, bool looping);
bool IsOpen() const;
int Resume();
void Stop();
bool IsOpen();
void TimidityVolumeChanged();
protected:
bool LaunchTimidity();
FTempFileName DiskName;
#ifdef _WIN32
HANDLE ReadWavePipe;
HANDLE WriteWavePipe;
HANDLE ChildProcess;
bool Validated;
bool ValidateTimidity();
#else // _WIN32
int WavePipe[2];
pid_t ChildProcess;
#endif
FString CommandLine;
size_t LoopPos;
static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata);
#ifdef _WIN32
static const char EventName[];
#endif
};
// Base class for software synthesizer MIDI output devices ------------------
class SoftSynthMIDIDevice : public MIDIDevice
@ -286,7 +156,7 @@ protected:
double NextTickIn;
MidiHeader *Events;
bool Started;
DWORD Position;
uint32_t Position;
int SampleRate;
MidiCallback Callback;
@ -491,10 +361,11 @@ public:
protected:
MIDIStreamer(const char *dumpname, EMidiDevice type);
void OutputVolume (DWORD volume);
int FillBuffer(int buffer_num, int max_events, DWORD max_time);
bool CheckExitEvent();
void OutputVolume (uint32_t volume);
int FillBuffer(int buffer_num, int max_events, uint32_t max_time);
int FillStopBuffer(int buffer_num);
DWORD *WriteStopNotes(DWORD *events);
uint32_t *WriteStopNotes(uint32_t *events);
int ServiceEvent();
int VolumeControllerChange(int channel, int volume);
int ClampLoopCount(int loopcount);
@ -512,7 +383,7 @@ protected:
virtual bool CheckDone() = 0;
virtual void Precache();
virtual bool SetMIDISubsong(int subsong);
virtual DWORD *MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time) = 0;
virtual uint32_t *MakeEvents(uint32_t *events, uint32_t *max_event_p, uint32_t max_time) = 0;
enum
{
@ -526,29 +397,20 @@ protected:
SONG_ERROR
};
#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];
uint32_t Events[2][MAX_EVENTS*3];
MidiHeader Buffer[2];
int BufferNum;
int EndQueued;
bool VolumeChanged;
bool Restarting;
bool InitialPlayback;
DWORD NewVolume;
uint32_t NewVolume;
int Division;
int Tempo;
int InitialTempo;
uint8_t ChannelVolumes[16];
DWORD Volume;
uint32_t Volume;
EMidiDevice DeviceType;
bool CallbackIsThreaded;
int LoopLimit;
@ -574,7 +436,7 @@ protected:
void DoRestart();
bool CheckDone();
void Precache();
DWORD *MakeEvents(DWORD *events, DWORD *max_events_p, DWORD max_time);
uint32_t *MakeEvents(uint32_t *events, uint32_t *max_events_p, uint32_t max_time);
MUSHeader *MusHeader;
uint8_t *MusBuffer;
@ -600,13 +462,13 @@ protected:
void DoInitialSetup();
void DoRestart();
bool CheckDone();
DWORD *MakeEvents(DWORD *events, DWORD *max_events_p, DWORD max_time);
void AdvanceTracks(DWORD time);
uint32_t *MakeEvents(uint32_t *events, uint32_t *max_events_p, uint32_t max_time);
void AdvanceTracks(uint32_t time);
struct TrackInfo;
void ProcessInitialMetaEvents ();
DWORD *SendCommand (DWORD *event, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom);
uint32_t *SendCommand (uint32_t *event, TrackInfo *track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom);
TrackInfo *FindNextDue ();
uint8_t *MusHeader;
@ -622,15 +484,15 @@ protected:
struct AutoNoteOff
{
DWORD Delay;
uint32_t Delay;
uint8_t Channel, Key;
};
// Sorry, std::priority_queue, but I want to be able to modify the contents of the heap.
class NoteOffQueue : public TArray<AutoNoteOff>
{
public:
void AddNoteOff(DWORD delay, uint8_t channel, uint8_t key);
void AdvanceTime(DWORD time);
void AddNoteOff(uint32_t delay, uint8_t channel, uint8_t key);
void AdvanceTime(uint32_t time);
bool Pop(AutoNoteOff &item);
protected:
@ -660,17 +522,17 @@ protected:
void DoInitialSetup();
void DoRestart();
bool CheckDone();
DWORD *MakeEvents(DWORD *events, DWORD *max_events_p, DWORD max_time);
void AdvanceTracks(DWORD time);
uint32_t *MakeEvents(uint32_t *events, uint32_t *max_events_p, uint32_t max_time);
void AdvanceTracks(uint32_t time);
struct TrackInfo;
void ProcessInitialMetaEvents ();
DWORD *SendCommand (DWORD *event, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom);
uint32_t *SendCommand (uint32_t *event, TrackInfo *track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom);
TrackInfo *FindNextDue ();
static DWORD ReadVarLenHMI(TrackInfo *);
static DWORD ReadVarLenHMP(TrackInfo *);
static uint32_t ReadVarLenHMI(TrackInfo *);
static uint32_t ReadVarLenHMP(TrackInfo *);
uint8_t *MusHeader;
int SongLen;
@ -678,7 +540,7 @@ protected:
TrackInfo *Tracks;
TrackInfo *TrackDue;
TrackInfo *FakeTrack;
DWORD (*ReadVarLen)(TrackInfo *);
uint32_t (*ReadVarLen)(TrackInfo *);
NoteOffQueue NoteOffs;
};
@ -705,11 +567,11 @@ protected:
void DoInitialSetup();
void DoRestart();
bool CheckDone();
DWORD *MakeEvents(DWORD *events, DWORD *max_events_p, DWORD max_time);
void AdvanceSong(DWORD time);
uint32_t *MakeEvents(uint32_t *events, uint32_t *max_events_p, uint32_t max_time);
void AdvanceSong(uint32_t time);
void ProcessInitialMetaEvents();
DWORD *SendCommand (DWORD *event, EventSource track, DWORD delay, ptrdiff_t room, bool &sysex_noroom);
uint32_t *SendCommand (uint32_t *event, EventSource track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom);
EventSource FindNextDue();
uint8_t *MusHeader;

View file

@ -40,9 +40,6 @@
extern HWND Window;
extern HINSTANCE g_hInst;
#define USE_WINDOWS_DWORD
#else
#define FALSE 0
#define TRUE 1
#endif
#include <stdio.h>

View file

@ -25,9 +25,46 @@
#ifdef __APPLE__
#include <AudioToolbox/AudioToolbox.h>
#include "i_musicinterns.h"
#include "templates.h"
// AudioToolbox implementation of a MIDI output device ----------------------
class AudioToolboxMIDIDevice : public MIDIDevice
{
public:
virtual int Open(MidiCallback, void *userData) override;
virtual void Close() override;
virtual bool IsOpen() const override;
virtual int GetTechnology() const override;
virtual int SetTempo(int tempo) override;
virtual int SetTimeDiv(int timediv) override;
virtual int StreamOut(MidiHeader *data) override;
virtual int StreamOutSync(MidiHeader *data) override;
virtual int Resume() override;
virtual void Stop() 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;
private:
MusicPlayer m_player = nullptr;
MusicSequence m_sequence = nullptr;
AudioUnit m_audioUnit = nullptr;
CFRunLoopTimerRef m_timer = nullptr;
MusicTimeStamp m_length = 0;
MidiCallback Callback;
Callback m_callback = nullptr;
void* m_userData = nullptr;
static void TimerCallback(CFRunLoopTimerRef timer, void* info);
};
#define AT_MIDI_CHECK_ERROR(CALL,...) \
{ \
const OSStatus result = CALL; \
@ -289,4 +326,9 @@ void AudioToolboxMIDIDevice::TimerCallback(CFRunLoopTimerRef timer, void* info)
#undef AT_MIDI_CHECK_ERROR
MIDIDevice *CreateAudioToolboxMIDTDevice(int mididevice)
{
return new AudioToolboxMIDIDevice(mididevice);
}
#endif // __APPLE__

View file

@ -908,7 +908,7 @@ MusInfo *MOD_OpenSong(FileReader &reader)
// safe. We'll restrict MOD loading to 31-instrument modules with known
// signatures and let the sound system worry about 15-instrument ones.
// (Assuming it even supports them)
duh = dumb_read_mod_quick(f, TRUE);
duh = dumb_read_mod_quick(f, true);
}
if (f != NULL)

View file

@ -35,6 +35,7 @@
#ifdef HAVE_FLUIDSYNTH
// HEADER FILES ------------------------------------------------------------
#include "i_midi_win32.h"
#include "i_musicinterns.h"
#include "templates.h"
@ -317,7 +318,7 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice(const char *args)
#ifdef _WIN32
// On Windows, look for the 4 megabyte patch set installed by Creative's drivers as a default.
char sysdir[MAX_PATH+sizeof("\\CT4MGM.SF2")];
UINT filepart;
uint32_t filepart;
if (0 != (filepart = GetSystemDirectoryA(sysdir, MAX_PATH)))
{
strcat(sysdir, "\\CT4MGM.SF2");

View file

@ -92,15 +92,15 @@ struct HMISong::TrackInfo
const uint8_t *TrackBegin;
size_t TrackP;
size_t MaxTrackP;
DWORD Delay;
DWORD PlayedTime;
uint32_t Delay;
uint32_t PlayedTime;
uint16_t Designation[NUM_HMI_DESIGNATIONS];
bool Enabled;
bool Finished;
uint8_t RunningStatus;
DWORD ReadVarLenHMI();
DWORD ReadVarLenHMP();
uint32_t ReadVarLenHMI();
uint32_t ReadVarLenHMP();
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
@ -131,12 +131,10 @@ extern char MIDI_CommonLengths[15];
HMISong::HMISong (FileReader &reader, EMidiDevice type, const char *args)
: MIDIStreamer(type, args), MusHeader(0), Tracks(0)
{
#ifdef _WIN32
if (ExitEvent == NULL)
if (!CheckExitEvent())
{
return;
}
#endif
int len = reader.GetLength();
if (len < 0x100)
{ // Way too small to be HMI.
@ -153,8 +151,8 @@ HMISong::HMISong (FileReader &reader, EMidiDevice type, const char *args)
{
SetupForHMI(len);
}
else if (((DWORD *)MusHeader)[0] == MAKE_ID('H','M','I','M') &&
((DWORD *)MusHeader)[1] == MAKE_ID('I','D','I','P'))
else if (((uint32_t *)MusHeader)[0] == MAKE_ID('H','M','I','M') &&
((uint32_t *)MusHeader)[1] == MAKE_ID('I','D','I','P'))
{
SetupForHMP(len);
}
@ -499,12 +497,12 @@ bool HMISong::CheckDone()
//
//==========================================================================
DWORD *HMISong::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
uint32_t *HMISong::MakeEvents(uint32_t *events, uint32_t *max_event_p, uint32_t max_time)
{
DWORD *start_events;
DWORD tot_time = 0;
DWORD time = 0;
DWORD delay;
uint32_t *start_events;
uint32_t tot_time = 0;
uint32_t time = 0;
uint32_t delay;
start_events = events;
while (TrackDue && events < max_event_p && tot_time <= max_time)
@ -524,7 +522,7 @@ DWORD *HMISong::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
do
{
bool sysex_noroom = false;
DWORD *new_events = SendCommand(events, TrackDue, time, max_event_p - events, sysex_noroom);
uint32_t *new_events = SendCommand(events, TrackDue, time, max_event_p - events, sysex_noroom);
if (sysex_noroom)
{
return events;
@ -552,7 +550,7 @@ DWORD *HMISong::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
//
//==========================================================================
void HMISong::AdvanceTracks(DWORD time)
void HMISong::AdvanceTracks(uint32_t time)
{
for (int i = 0; i <= NumTracks; ++i)
{
@ -573,9 +571,9 @@ void HMISong::AdvanceTracks(DWORD time)
//
//==========================================================================
DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom)
uint32_t *HMISong::SendCommand (uint32_t *events, TrackInfo *track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom)
{
DWORD len;
uint32_t len;
uint8_t event, data1 = 0, data2 = 0;
// If the next event comes from the fake track, pop an entry off the note-off queue.
@ -783,7 +781,7 @@ void HMISong::ProcessInitialMetaEvents ()
TrackInfo *track;
int i;
uint8_t event;
DWORD len;
uint32_t len;
for (i = 0; i < NumTracks; ++i)
{
@ -828,7 +826,7 @@ void HMISong::ProcessInitialMetaEvents ()
//
//==========================================================================
DWORD HMISong::ReadVarLenHMI(TrackInfo *track)
uint32_t HMISong::ReadVarLenHMI(TrackInfo *track)
{
return track->ReadVarLenHMI();
}
@ -839,7 +837,7 @@ DWORD HMISong::ReadVarLenHMI(TrackInfo *track)
//
//==========================================================================
DWORD HMISong::ReadVarLenHMP(TrackInfo *track)
uint32_t HMISong::ReadVarLenHMP(TrackInfo *track)
{
return track->ReadVarLenHMP();
}
@ -852,9 +850,9 @@ DWORD HMISong::ReadVarLenHMP(TrackInfo *track)
//
//==========================================================================
DWORD HMISong::TrackInfo::ReadVarLenHMI()
uint32_t HMISong::TrackInfo::ReadVarLenHMI()
{
DWORD time = 0, t = 0x80;
uint32_t time = 0, t = 0x80;
while ((t & 0x80) && TrackP < MaxTrackP)
{
@ -874,9 +872,9 @@ DWORD HMISong::TrackInfo::ReadVarLenHMI()
//
//==========================================================================
DWORD HMISong::TrackInfo::ReadVarLenHMP()
uint32_t HMISong::TrackInfo::ReadVarLenHMP()
{
DWORD time = 0;
uint32_t time = 0;
uint8_t t = 0;
int off = 0;
@ -895,7 +893,7 @@ DWORD HMISong::TrackInfo::ReadVarLenHMP()
//
//==========================================================================
void NoteOffQueue::AddNoteOff(DWORD delay, uint8_t channel, uint8_t key)
void NoteOffQueue::AddNoteOff(uint32_t delay, uint8_t channel, uint8_t key)
{
unsigned int i = Reserve(1);
while (i > 0 && (*this)[Parent(i)].Delay > delay)
@ -931,7 +929,7 @@ bool NoteOffQueue::Pop(AutoNoteOff &item)
//
//==========================================================================
void NoteOffQueue::AdvanceTime(DWORD time)
void NoteOffQueue::AdvanceTime(uint32_t time)
{
// Because the time is decreasing by the same amount for every entry,
// the heap property is maintained.
@ -985,7 +983,7 @@ void NoteOffQueue::Heapify()
HMISong::TrackInfo *HMISong::FindNextDue ()
{
TrackInfo *track;
DWORD best;
uint32_t best;
int i;
// Give precedence to whichever track last had events taken from it.

View file

@ -1,3 +1,6 @@
#include "i_midi_win32.h"
#include "i_musicinterns.h"
#include "c_dispatch.h"
#include "i_music.h"
@ -65,7 +68,7 @@ static void MIDIDeviceChanged(int newdev)
}
#ifdef _WIN32
UINT mididevice;
unsigned mididevice;
CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{

View file

@ -1,3 +1,6 @@
#include "i_midi_win32.h"
#include "i_musicinterns.h"
#include "c_cvars.h"
#include "cmdlib.h"
@ -20,6 +23,46 @@ void ChildSigHandler (int signum)
}
#endif
class TimidityPPMIDIDevice : public PseudoMIDIDevice
{
public:
TimidityPPMIDIDevice(const char *args);
~TimidityPPMIDIDevice();
int Open(MidiCallback, void *userdata);
bool Preprocess(MIDIStreamer *song, bool looping);
bool IsOpen() const;
int Resume();
void Stop();
bool IsOpen();
void TimidityVolumeChanged();
protected:
bool LaunchTimidity();
FTempFileName DiskName;
#ifdef _WIN32
HANDLE ReadWavePipe;
HANDLE WriteWavePipe;
HANDLE ChildProcess;
bool Validated;
bool ValidateTimidity();
#else // _WIN32
int WavePipe[2];
pid_t ChildProcess;
#endif
FString CommandLine;
size_t LoopPos;
static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata);
#ifdef _WIN32
static const char EventName[];
#endif
};
#ifdef _WIN32
@ -183,7 +226,7 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata)
int pipeSize;
#ifdef _WIN32
static SECURITY_ATTRIBUTES inheritable = { sizeof(inheritable), NULL, TRUE };
static SECURITY_ATTRIBUTES inheritable = { sizeof(inheritable), NULL, true };
if (!Validated && !ValidateTimidity ())
{
@ -392,7 +435,7 @@ bool TimidityPPMIDIDevice::LaunchTimidity ()
startup.lpTitle = TimidityTitle;
startup.wShowWindow = SW_SHOWMINNOACTIVE;
if (CreateProcess(NULL, CommandLine.LockBuffer(), NULL, NULL, TRUE,
if (CreateProcess(NULL, CommandLine.LockBuffer(), NULL, NULL, true,
DETACHED_PROCESS, NULL, NULL, &startup, &procInfo))
{
ChildProcess = procInfo.hProcess;
@ -728,3 +771,9 @@ BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
return bSuccess;
}
#endif
MIDIDevice *CreateTimidityPPMIDIDevice(const char *args)
{
return new TimidityPPMIDIDevice(args);
}

View file

@ -34,6 +34,18 @@
// HEADER FILES ------------------------------------------------------------
#include "i_midi_win32.h"
/*
#ifdef _WIN32
DWORD PlayerLoop();
HANDLE PlayerThread;
HANDLE ExitEvent;
HANDLE BufferDoneEvent;
#endif
*/
#include "i_musicinterns.h"
#include "templates.h"
#include "doomdef.h"
@ -61,7 +73,9 @@ EXTERN_CVAR(Float, snd_musicvolume)
EXTERN_CVAR(Int, snd_mididevice)
#ifdef _WIN32
extern UINT mididevice;
DWORD WINAPI PlayerProc(LPVOID lpParameter);
extern unsigned mididevice;
#endif
extern char MIDI_EventLengths[7];
@ -92,11 +106,12 @@ static const uint8_t StaticMIDIhead[] =
MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args)
:
#ifdef _WIN32
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
//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)
@ -110,6 +125,7 @@ MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args)
return;
}
#endif
*/
}
//==========================================================================
@ -121,15 +137,17 @@ MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args)
MIDIStreamer::MIDIStreamer(const char *dumpname, EMidiDevice type)
:
#ifdef _WIN32
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
//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
*/
}
//==========================================================================
@ -141,6 +159,7 @@ MIDIStreamer::MIDIStreamer(const char *dumpname, EMidiDevice type)
MIDIStreamer::~MIDIStreamer()
{
Stop();
/*
#ifdef _WIN32
if (ExitEvent != NULL)
{
@ -151,6 +170,7 @@ MIDIStreamer::~MIDIStreamer()
CloseHandle(BufferDoneEvent);
}
#endif
*/
if (MIDI != NULL)
{
delete MIDI;
@ -179,7 +199,7 @@ bool MIDIStreamer::IsMIDI() const
bool MIDIStreamer::IsValid() const
{
#ifdef _WIN32
return ExitEvent != NULL && Division != 0;
return /*ExitEvent != NULL &&*/ Division != 0;
#else
return Division != 0;
#endif
@ -264,7 +284,7 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
{
case MDEV_MMAPI:
#ifdef _WIN32
return new WinMIDIDevice(mididevice);
return CreateWinMIDIDevice(mididevice);
#endif
assert(0);
// Intentional fall-through for non-Windows systems.
@ -289,11 +309,11 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
{
// The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found.
Printf("Unable to create OPL MIDI device: %s\nFalling back to Sound System playback", err.GetMessage());
return new SndSysMIDIDevice;
return GSnd->CreateMIDIDevice();
}
case MDEV_TIMIDITY:
return new TimidityPPMIDIDevice(Args);
return CreateTimidityPPMIDIDevice(Args);
case MDEV_WILDMIDI:
return new WildMIDIDevice(Args);
@ -373,6 +393,7 @@ void MIDIStreamer::Play(bool looping, int subsong)
}
else
{
/*
#ifdef _WIN32
if (MIDI->NeedThreadedCallback())
{
@ -389,6 +410,7 @@ void MIDIStreamer::Play(bool looping, int subsong)
}
else
#endif
*/
{
m_Status = STATE_Playing;
}
@ -418,10 +440,12 @@ void MIDIStreamer::StartPlayback()
MusicVolumeChanged(); // set volume to current music's properties
OutputVolume(Volume);
/*
#ifdef _WIN32
ResetEvent(ExitEvent);
ResetEvent(BufferDoneEvent);
#endif
*/
// Fill the initial buffers for the song.
BufferNum = 0;
@ -507,6 +531,8 @@ void MIDIStreamer::Resume()
void MIDIStreamer::Stop()
{
EndQueued = 4;
/*
#ifdef _WIN32
if (PlayerThread != NULL)
{
@ -516,6 +542,7 @@ void MIDIStreamer::Stop()
PlayerThread = NULL;
}
#endif
*/
if (MIDI != NULL && MIDI->IsOpen())
{
MIDI->Stop();
@ -656,7 +683,7 @@ void MIDIStreamer::WildMidiSetOption(int opt, int set)
//
//==========================================================================
void MIDIStreamer::OutputVolume (DWORD volume)
void MIDIStreamer::OutputVolume (uint32_t volume)
{
if (MIDI != NULL && MIDI->FakeVolume())
{
@ -701,6 +728,7 @@ void MIDIStreamer::Callback(void *userdata)
{
return;
}
/*
#ifdef _WIN32
if (self->PlayerThread != NULL)
{
@ -708,6 +736,7 @@ void MIDIStreamer::Callback(void *userdata)
}
else
#endif
*/
{
self->ServiceEvent();
}
@ -724,6 +753,7 @@ void MIDIStreamer::Callback(void *userdata)
void MIDIStreamer::Update()
{
/*
#ifdef _WIN32
// If the PlayerThread is signalled, then it's dead.
if (PlayerThread != NULL &&
@ -785,6 +815,7 @@ void MIDIStreamer::Update()
Stop();
}
#endif
*/
}
//==========================================================================
@ -796,9 +827,10 @@ void MIDIStreamer::Update()
//==========================================================================
#ifdef _WIN32
DWORD WINAPI MIDIStreamer::PlayerProc (LPVOID lpParameter)
DWORD WINAPI PlayerProc(LPVOID lpParameter)
{
return ((MIDIStreamer *)lpParameter)->PlayerLoop();
// return ((MIDIStreamer *)lpParameter)->PlayerLoop();
return 0;
}
#endif
@ -809,6 +841,7 @@ DWORD WINAPI MIDIStreamer::PlayerProc (LPVOID lpParameter)
// Services MIDI playback events.
//
//==========================================================================
/*
#ifdef _WIN32
DWORD MIDIStreamer::PlayerLoop()
@ -837,8 +870,10 @@ DWORD MIDIStreamer::PlayerLoop()
return MMSYSERR_ERROR;
}
}
return 0;
}
#endif
*/
//==========================================================================
//
@ -920,7 +955,7 @@ fill:
//
//==========================================================================
int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time)
int MIDIStreamer::FillBuffer(int buffer_num, int max_events, uint32_t max_time)
{
if (!Restarting && CheckDone())
{
@ -928,9 +963,9 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time)
}
int i;
DWORD *events = Events[buffer_num], *max_event_p;
DWORD tot_time = 0;
DWORD time = 0;
uint32_t *events = Events[buffer_num], *max_event_p;
uint32_t tot_time = 0;
uint32_t time = 0;
// The final event is for a NOP to hold the delay from the last event.
max_event_p = events + (max_events - 1) * 3;
@ -1009,7 +1044,7 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time)
int MIDIStreamer::FillStopBuffer(int buffer_num)
{
DWORD *events = Events[buffer_num];
uint32_t *events = Events[buffer_num];
int i;
events = WriteStopNotes(events);
@ -1040,7 +1075,7 @@ int MIDIStreamer::FillStopBuffer(int buffer_num)
//
//==========================================================================
DWORD *MIDIStreamer::WriteStopNotes(DWORD *events)
uint32_t *MIDIStreamer::WriteStopNotes(uint32_t *events)
{
for (int i = 0; i < 16; ++i)
{
@ -1080,8 +1115,8 @@ void MIDIStreamer::Precache()
// Simulate playback to pick out used instruments.
while (!CheckDone())
{
DWORD *event_end = MakeEvents(Events[0], &Events[0][MAX_EVENTS*3], 1000000*600);
for (DWORD *event = Events[0]; event < event_end; )
uint32_t *event_end = MakeEvents(Events[0], &Events[0][MAX_EVENTS*3], 1000000*600);
for (uint32_t *event = Events[0]; event < event_end; )
{
if (MEVENT_EVENTTYPE(event[2]) == 0)
{
@ -1187,15 +1222,15 @@ void MIDIStreamer::CreateSMF(TArray<uint8_t> &file, int looplimit)
while (!CheckDone())
{
DWORD *event_end = MakeEvents(Events[0], &Events[0][MAX_EVENTS*3], 1000000*600);
for (DWORD *event = Events[0]; event < event_end; )
uint32_t *event_end = MakeEvents(Events[0], &Events[0][MAX_EVENTS*3], 1000000*600);
for (uint32_t *event = Events[0]; event < event_end; )
{
delay += event[0];
if (MEVENT_EVENTTYPE(event[2]) == MEVENT_TEMPO)
{
WriteVarLen(file, delay);
delay = 0;
DWORD tempo = MEVENT_EVENTPARM(event[2]);
uint32_t tempo = MEVENT_EVENTPARM(event[2]);
file.Push(MIDI_META);
file.Push(MIDI_META_TEMPO);
file.Push(3);
@ -1208,7 +1243,7 @@ void MIDIStreamer::CreateSMF(TArray<uint8_t> &file, int looplimit)
{
WriteVarLen(file, delay);
delay = 0;
DWORD len = MEVENT_EVENTPARM(event[2]);
uint32_t len = MEVENT_EVENTPARM(event[2]);
uint8_t *bytes = (uint8_t *)&event[3];
if (bytes[0] == MIDI_SYSEX)
{
@ -1398,6 +1433,27 @@ 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.

View file

@ -96,12 +96,10 @@ static const uint8_t CtrlTranslate[15] =
MUSSong2::MUSSong2 (FileReader &reader, EMidiDevice type, const char *args)
: MIDIStreamer(type, args), MusHeader(0), MusBuffer(0)
{
#ifdef _WIN32
if (ExitEvent == NULL)
if (!CheckExitEvent())
{
return;
}
#endif
uint8_t front[32];
int start;
@ -260,10 +258,10 @@ void MUSSong2::Precache()
//
//==========================================================================
DWORD *MUSSong2::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
uint32_t *MUSSong2::MakeEvents(uint32_t *events, uint32_t *max_event_p, uint32_t max_time)
{
DWORD tot_time = 0;
DWORD time = 0;
uint32_t tot_time = 0;
uint32_t time = 0;
max_time = max_time * Division / Tempo;

View file

@ -60,8 +60,8 @@ struct MIDISong2::TrackInfo
const uint8_t *TrackBegin;
size_t TrackP;
size_t MaxTrackP;
DWORD Delay;
DWORD PlayedTime;
uint32_t Delay;
uint32_t PlayedTime;
bool Finished;
uint8_t RunningStatus;
bool Designated;
@ -70,11 +70,11 @@ struct MIDISong2::TrackInfo
uint16_t Designation;
size_t LoopBegin;
DWORD LoopDelay;
uint32_t LoopDelay;
int LoopCount;
bool LoopFinished;
DWORD ReadVarLen ();
uint32_t ReadVarLen ();
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
@ -108,12 +108,10 @@ MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type, const char *args)
int p;
int i;
#ifdef _WIN32
if (ExitEvent == NULL)
if (!CheckExitEvent())
{
return;
}
#endif
SongLen = reader.GetLength();
MusHeader = new uint8_t[SongLen];
if (reader.Read(MusHeader, SongLen) != SongLen)
@ -149,13 +147,13 @@ MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type, const char *args)
// Gather information about each track
for (i = 0, p = 14; i < NumTracks && p < SongLen + 8; ++i)
{
DWORD chunkLen =
uint32_t chunkLen =
(MusHeader[p+4]<<24) |
(MusHeader[p+5]<<16) |
(MusHeader[p+6]<<8) |
(MusHeader[p+7]);
if (chunkLen + p + 8 > (DWORD)SongLen)
if (chunkLen + p + 8 > (uint32_t)SongLen)
{ // Track too long, so truncate it
chunkLen = SongLen - p - 8;
}
@ -298,12 +296,12 @@ bool MIDISong2::CheckDone()
//
//==========================================================================
DWORD *MIDISong2::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
uint32_t *MIDISong2::MakeEvents(uint32_t *events, uint32_t *max_event_p, uint32_t max_time)
{
DWORD *start_events;
DWORD tot_time = 0;
DWORD time = 0;
DWORD delay;
uint32_t *start_events;
uint32_t tot_time = 0;
uint32_t time = 0;
uint32_t delay;
start_events = events;
while (TrackDue && events < max_event_p && tot_time <= max_time)
@ -323,7 +321,7 @@ DWORD *MIDISong2::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
do
{
bool sysex_noroom = false;
DWORD *new_events = SendCommand(events, TrackDue, time, max_event_p - events, sysex_noroom);
uint32_t *new_events = SendCommand(events, TrackDue, time, max_event_p - events, sysex_noroom);
if (sysex_noroom)
{
return events;
@ -351,7 +349,7 @@ DWORD *MIDISong2::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
//
//==========================================================================
void MIDISong2::AdvanceTracks(DWORD time)
void MIDISong2::AdvanceTracks(uint32_t time)
{
for (int i = 0; i < NumTracks; ++i)
{
@ -371,9 +369,9 @@ void MIDISong2::AdvanceTracks(DWORD time)
//
//==========================================================================
DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom)
uint32_t *MIDISong2::SendCommand (uint32_t *events, TrackInfo *track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom)
{
DWORD len;
uint32_t len;
uint8_t event, data1 = 0, data2 = 0;
int i;
@ -456,7 +454,7 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
case 110: // EMIDI Track Designation - InitBeat only
// Instruments 4, 5, 6, and 7 are all FM synth.
// The rest are all wavetable.
if (track->PlayedTime < (DWORD)Division)
if (track->PlayedTime < (uint32_t)Division)
{
if (data2 == 127)
{
@ -473,7 +471,7 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
break;
case 111: // EMIDI Track Exclusion - InitBeat only
if (track->PlayedTime < (DWORD)Division)
if (track->PlayedTime < (uint32_t)Division)
{
if (track->Designated && data2 <= 9)
{
@ -485,7 +483,7 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
case 112: // EMIDI Program Change
// Ignored unless it also appears in the InitBeat
if (track->PlayedTime < (DWORD)Division || track->EProgramChange)
if (track->PlayedTime < (uint32_t)Division || track->EProgramChange)
{
track->EProgramChange = true;
event = 0xC0 | (event & 0x0F);
@ -496,7 +494,7 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
case 113: // EMIDI Volume
// Ignored unless it also appears in the InitBeat
if (track->PlayedTime < (DWORD)Division || track->EVolume)
if (track->PlayedTime < (uint32_t)Division || track->EVolume)
{
track->EVolume = true;
data1 = 7;
@ -700,7 +698,7 @@ void MIDISong2::ProcessInitialMetaEvents ()
TrackInfo *track;
int i;
uint8_t event;
DWORD len;
uint32_t len;
for (i = 0; i < NumTracks; ++i)
{
@ -747,9 +745,9 @@ void MIDISong2::ProcessInitialMetaEvents ()
//
//==========================================================================
DWORD MIDISong2::TrackInfo::ReadVarLen ()
uint32_t MIDISong2::TrackInfo::ReadVarLen ()
{
DWORD time = 0, t = 0x80;
uint32_t time = 0, t = 0x80;
while ((t & 0x80) && TrackP < MaxTrackP)
{
@ -771,7 +769,7 @@ DWORD MIDISong2::TrackInfo::ReadVarLen ()
MIDISong2::TrackInfo *MIDISong2::FindNextDue ()
{
TrackInfo *track;
DWORD best;
uint32_t best;
int i;
// Give precedence to whichever track last had events taken from it.

View file

@ -34,6 +34,8 @@
// HEADER FILES ------------------------------------------------------------
#include "i_midi_win32.h"
#include "i_musicinterns.h"
#include "templates.h"
#include "doomdef.h"
@ -46,21 +48,22 @@
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// MIDI file played with TiMidity++ and possibly streamed through the Sound System
struct FmtChunk
{
DWORD ChunkID;
DWORD ChunkLen;
uint32_t ChunkID;
uint32_t ChunkLen;
uint16_t FormatTag;
uint16_t Channels;
DWORD SamplesPerSec;
DWORD AvgBytesPerSec;
uint32_t SamplesPerSec;
uint32_t AvgBytesPerSec;
uint16_t BlockAlign;
uint16_t BitsPerSample;
uint16_t ExtensionSize;
uint16_t ValidBitsPerSample;
DWORD ChannelMask;
DWORD SubFormatA;
uint32_t ChannelMask;
uint32_t SubFormatA;
uint16_t SubFormatB;
uint16_t SubFormatC;
uint8_t SubFormatD[8];
@ -250,7 +253,7 @@ TimidityWaveWriterMIDIDevice::TimidityWaveWriterMIDIDevice(const char *filename,
File = fopen(filename, "wb");
if (File != NULL)
{ // Write wave header
DWORD work[3];
uint32_t work[3];
FmtChunk fmt;
work[0] = MAKE_ID('R','I','F','F');
@ -259,7 +262,7 @@ TimidityWaveWriterMIDIDevice::TimidityWaveWriterMIDIDevice(const char *filename,
if (3 != fwrite(work, 4, 3, File)) goto fail;
fmt.ChunkID = MAKE_ID('f','m','t',' ');
fmt.ChunkLen = LittleLong(DWORD(sizeof(fmt) - 8));
fmt.ChunkLen = LittleLong(uint32_t(sizeof(fmt) - 8));
fmt.FormatTag = LittleShort(0xFFFE); // WAVE_FORMAT_EXTENSIBLE
fmt.Channels = LittleShort(2);
fmt.SamplesPerSec = LittleLong((int)Renderer->rate);
@ -305,15 +308,15 @@ TimidityWaveWriterMIDIDevice::~TimidityWaveWriterMIDIDevice()
if (File != NULL)
{
long pos = ftell(File);
DWORD size;
uint32_t size;
// data chunk size
size = LittleLong(DWORD(pos - 8));
size = LittleLong(uint32_t(pos - 8));
if (0 == fseek(File, 4, SEEK_SET))
{
if (1 == fwrite(&size, 4, 1, File))
{
size = LittleLong(DWORD(pos - 12 - sizeof(FmtChunk) - 8));
size = LittleLong(uint32_t(pos - 12 - sizeof(FmtChunk) - 8));
if (0 == fseek(File, 4 + sizeof(FmtChunk) + 4, SEEK_CUR))
{
if (1 == fwrite(&size, 4, 1, File))

View file

@ -34,6 +34,20 @@
#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 <windows.h>
#include <mmsystem.h>
// HEADER FILES ------------------------------------------------------------
#include "i_musicinterns.h"
@ -58,6 +72,43 @@ static bool IgnoreMIDIVolume(UINT id);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// WinMM implementation of a MIDI output device -----------------------------
class WinMIDIDevice : public MIDIDevice
{
public:
WinMIDIDevice(int dev_id);
~WinMIDIDevice();
int Open(MidiCallback, void *userdata);
void Close();
bool IsOpen() const;
int GetTechnology() const;
int SetTempo(int tempo);
int SetTimeDiv(int timediv);
int StreamOut(MidiHeader *data);
int StreamOutSync(MidiHeader *data);
int Resume();
void Stop();
int PrepareHeader(MidiHeader *data);
int UnprepareHeader(MidiHeader *data);
bool FakeVolume();
bool NeedThreadedCallback();
bool Pause(bool paused);
void PrecacheInstruments(const uint16_t *instruments, int count);
protected:
static void CALLBACK CallbackFunc(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD);
HMIDISTRM MidiOut;
UINT DeviceID;
DWORD SavedVolume;
MIDIHDR WinMidiHeaders[2];
int HeaderIndex;
bool VolumeWorks;
MidiCallback Callback;
void *CallbackData;
};
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -487,4 +538,10 @@ static bool IgnoreMIDIVolume(UINT id)
return false;
}
MIDIDevice *CreateWinMIDIDevice(int mididevice)
{
return new WinMIDIDevice(mididevice);
}
#endif

View file

@ -72,15 +72,15 @@ struct XMISong::TrackInfo
const uint8_t *TimbreChunk;
size_t TimbreLen;
DWORD Delay;
DWORD PlayedTime;
uint32_t Delay;
uint32_t PlayedTime;
bool Finished;
LoopInfo ForLoops[MAX_FOR_DEPTH];
int ForDepth;
DWORD ReadVarLen();
DWORD ReadDelay();
uint32_t ReadVarLen();
uint32_t ReadDelay();
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
@ -111,12 +111,10 @@ extern char MIDI_CommonLengths[15];
XMISong::XMISong (FileReader &reader, EMidiDevice type, const char *args)
: MIDIStreamer(type, args), MusHeader(0), Songs(0)
{
#ifdef _WIN32
if (ExitEvent == NULL)
if (!CheckExitEvent())
{
return;
}
#endif
SongLen = reader.GetLength();
MusHeader = new uint8_t[SongLen];
if (reader.Read(MusHeader, SongLen) != SongLen)
@ -313,12 +311,12 @@ bool XMISong::CheckDone()
//
//==========================================================================
DWORD *XMISong::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
uint32_t *XMISong::MakeEvents(uint32_t *events, uint32_t *max_event_p, uint32_t max_time)
{
DWORD *start_events;
DWORD tot_time = 0;
DWORD time = 0;
DWORD delay;
uint32_t *start_events;
uint32_t tot_time = 0;
uint32_t time = 0;
uint32_t delay;
start_events = events;
while (EventDue != EVENT_None && events < max_event_p && tot_time <= max_time)
@ -338,7 +336,7 @@ DWORD *XMISong::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
do
{
bool sysex_noroom = false;
DWORD *new_events = SendCommand(events, EventDue, time, max_event_p - events, sysex_noroom);
uint32_t *new_events = SendCommand(events, EventDue, time, max_event_p - events, sysex_noroom);
if (sysex_noroom)
{
return events;
@ -366,7 +364,7 @@ DWORD *XMISong::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
//
//==========================================================================
void XMISong::AdvanceSong(DWORD time)
void XMISong::AdvanceSong(uint32_t time)
{
if (time != 0)
{
@ -387,9 +385,9 @@ void XMISong::AdvanceSong(DWORD time)
//
//==========================================================================
DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay, ptrdiff_t room, bool &sysex_noroom)
uint32_t *XMISong::SendCommand (uint32_t *events, EventSource due, uint32_t delay, ptrdiff_t room, bool &sysex_noroom)
{
DWORD len;
uint32_t len;
uint8_t event, data1 = 0, data2 = 0;
if (due == EVENT_Fake)
@ -617,7 +615,7 @@ void XMISong::ProcessInitialMetaEvents ()
{
TrackInfo *track = CurrSong;
uint8_t event;
DWORD len;
uint32_t len;
while (!track->Finished &&
track->EventP < track->EventLen - 3 &&
@ -646,9 +644,9 @@ void XMISong::ProcessInitialMetaEvents ()
//
//==========================================================================
DWORD XMISong::TrackInfo::ReadVarLen()
uint32_t XMISong::TrackInfo::ReadVarLen()
{
DWORD time = 0, t = 0x80;
uint32_t time = 0, t = 0x80;
while ((t & 0x80) && EventP < EventLen)
{
@ -667,9 +665,9 @@ DWORD XMISong::TrackInfo::ReadVarLen()
//
//==========================================================================
DWORD XMISong::TrackInfo::ReadDelay()
uint32_t XMISong::TrackInfo::ReadDelay()
{
DWORD time = 0, t;
uint32_t time = 0, t;
while (EventP < EventLen && !((t = EventChunk[EventP]) & 0x80))
{
@ -697,8 +695,8 @@ XMISong::EventSource XMISong::FindNextDue()
}
// Which is due sooner? The current song or the note-offs?
DWORD real_delay = CurrSong->Finished ? 0xFFFFFFFF : CurrSong->Delay;
DWORD fake_delay = NoteOffs.Size() == 0 ? 0xFFFFFFFF : NoteOffs[0].Delay;
uint32_t real_delay = CurrSong->Finished ? 0xFFFFFFFF : CurrSong->Delay;
uint32_t fake_delay = NoteOffs.Size() == 0 ? 0xFFFFFFFF : NoteOffs[0].Delay;
return (fake_delay <= real_delay) ? EVENT_Fake : EVENT_Real;
}

View file

@ -2055,10 +2055,10 @@ void OpenALSoundRenderer::PrintDriversList()
MIDIDevice* OpenALSoundRenderer::CreateMIDIDevice() const
{
#ifdef _WIN32
extern UINT mididevice;
return new WinMIDIDevice(mididevice);
extern unsigned mididevice;
return CreateWinMIDIDevice(mididevice);
#elif defined __APPLE__
return new AudioToolboxMIDIDevice;
return CreateAudioToolboxMIDIDevice;
#else
return new OPLMIDIDevice(nullptr);
#endif

View file

@ -1,22 +1,19 @@
// Wraps a Windows critical section object.
#ifndef CRITSEC_H
#define CRITSEC_H
#ifndef _WINNT_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define USE_WINDOWS_DWORD
#endif
class FCriticalSection
class FInternalCriticalSection
{
public:
FCriticalSection()
FInternalCriticalSection()
{
InitializeCriticalSection(&CritSec);
}
~FCriticalSection()
~FInternalCriticalSection()
{
DeleteCriticalSection(&CritSec);
}
@ -39,4 +36,23 @@ private:
CRITICAL_SECTION CritSec;
};
#endif
FInternalCriticalSection *CreateCriticalSection()
{
return new FInternalCriticalSection();
}
void DeleteCriticalSection(FInternalCriticalSection *c)
{
delete c;
}
void EnterCriticalSection(FInternalCriticalSection *c)
{
c->Enter();
}
void LeaveCriticalSection(FInternalCriticalSection *c)
{
c->Leave();
}

View file

@ -175,10 +175,10 @@ FString I_GetLongPathName(FString shortpath);
struct findstate_t
{
DWORD Attribs;
DWORD Times[3*2];
DWORD Size[2];
DWORD Reserved[2];
uint32_t Attribs;
uint32_t Times[3*2];
uint32_t Size[2];
uint32_t Reserved[2];
char Name[MAX_PATH];
char AltName[14];
};