- Fixed snd_mididevice so that changing it immediately restarts the song for all devices, not

just Windows system devices.
- Remove SMF generation from i_music.cpp, since the psuedo-MIDI devices do this now.

SVN r2875 (trunk)
This commit is contained in:
Randy Heit 2010-10-02 04:12:21 +00:00
parent 90dd40c58f
commit b2b84ad11f
9 changed files with 167 additions and 217 deletions

View file

@ -247,6 +247,11 @@ bool MusInfo::SetPosition (unsigned int ms)
return false;
}
bool MusInfo::IsMIDI() const
{
return false;
}
bool MusInfo::SetSubsong (int subsong)
{
return false;
@ -297,7 +302,7 @@ MusInfo *MusInfo::GetWaveDumper(const char *filename, int rate)
//
//==========================================================================
static MIDIStreamer *CreateMIDIStreamer(FILE *file, BYTE *musiccache, int len, EMIDIDevice devtype, EMIDIType miditype)
static MIDIStreamer *CreateMIDIStreamer(FILE *file, BYTE *musiccache, int len, EMidiDevice devtype, EMIDIType miditype)
{
switch (miditype)
{
@ -318,29 +323,6 @@ static MIDIStreamer *CreateMIDIStreamer(FILE *file, BYTE *musiccache, int len, E
}
}
//==========================================================================
//
// create a MIDI player
//
//==========================================================================
static MusInfo *CreateMIDISong(FILE *file, const char *filename, BYTE *musiccache, int offset, int len, EMIDIDevice devtype, EMIDIType miditype)
{
if (devtype >= MIDI_Null)
{
assert(miditype == MIDI_MIDI);
if (musiccache != NULL)
{
return new StreamSong((char *)musiccache, -1, len);
}
else
{
return new StreamSong(filename, offset, len);
}
}
else return CreateMIDIStreamer(file, musiccache, len, devtype, miditype);
}
//==========================================================================
//
// identify MIDI file type
@ -390,66 +372,6 @@ static EMIDIType IdentifyMIDIType(DWORD *id, int size)
}
}
//==========================================================================
//
// select the MIDI device to play on
//
//==========================================================================
static EMIDIDevice SelectMIDIDevice(int device)
{
/* MIDI are played as:
- OPL:
- if explicitly selected by $mididevice
- when snd_mididevice is -3 and no midi device is set for the song
- Timidity:
- if explicitly selected by $mididevice
- when snd_mididevice is -2 and no midi device is set for the song
- FMod:
- if explicitly selected by $mididevice
- when snd_mididevice is -1 and no midi device is set for the song
- as fallback when both OPL and Timidity failed unless snd_mididevice is >= 0
- MMAPI (Win32 only):
- if explicitly selected by $mididevice (non-Win32 redirects this to FMOD)
- when snd_mididevice is >= 0 and no midi device is set for the song
- as fallback when both OPL and Timidity failed and snd_mididevice is >= 0
*/
EMIDIDevice devtype = MIDI_Null;
// Choose the type of MIDI device we want.
if (device == MDEV_FMOD || (snd_mididevice == -1 && device == MDEV_DEFAULT))
{
return MIDI_FMOD;
}
else if (device == MDEV_TIMIDITY || (snd_mididevice == -2 && device == MDEV_DEFAULT))
{
return MIDI_Timidity;
}
else if (device == MDEV_OPL || (snd_mididevice == -3 && device == MDEV_DEFAULT))
{
return MIDI_OPL;
}
else if (device == MDEV_GUS || (snd_mididevice == -4 && device == MDEV_DEFAULT))
{
return MIDI_GUS;
}
#ifdef HAVE_FLUIDSYNTH
else if (device == MDEV_FLUIDSYNTH || (snd_mididevice == -5 && device == MDEV_DEFAULT))
{
return MIDI_Fluid;
}
#endif
#ifdef _WIN32
return MIDI_Win;
#else
return MIDI_Null;
#endif
}
//==========================================================================
//
// identify a music lump's type and set up a player for it
@ -557,45 +479,24 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
{
TArray<BYTE> midi;
EMIDIDevice devtype = SelectMIDIDevice(device);
EMidiDevice devtype = (EMidiDevice)device;
retry_as_fmod:
if (devtype >= MIDI_Null)
{
// Convert to standard MIDI for external sequencers.
MIDIStreamer *streamer = CreateMIDIStreamer(file, musiccache, len, MIDI_Null, miditype);
if (streamer != NULL)
{
if (streamer->IsValid())
{
streamer->CreateSMF(midi);
miditype = MIDI_MIDI;
musiccache = &midi[0];
len = midi.Size();
if (file != NULL)
{
fclose(file);
file = NULL;
}
}
delete streamer;
}
}
info = CreateMIDISong(file, filename, musiccache, offset, len, devtype, miditype);
info = CreateMIDIStreamer(file, musiccache, len, devtype, miditype);
if (info != NULL && !info->IsValid())
{
delete info;
info = NULL;
}
if (info == NULL && devtype != MIDI_FMOD && snd_mididevice < 0)
if (info == NULL && devtype != MDEV_FMOD && snd_mididevice < 0)
{
devtype = MIDI_FMOD;
devtype = MDEV_FMOD;
goto retry_as_fmod;
}
#ifdef _WIN32
if (info == NULL && devtype != MIDI_Win && snd_mididevice >= 0)
if (info == NULL && devtype != MDEV_MMAPI && snd_mididevice >= 0)
{
info = CreateMIDISong(file, filename, musiccache, offset, len, MIDI_Win, miditype);
info = CreateMIDIStreamer(file, musiccache, len, MDEV_MMAPI, miditype);
}
#endif
}

View file

@ -70,7 +70,7 @@ public:
virtual void Resume () = 0;
virtual void Stop () = 0;
virtual bool IsPlaying () = 0;
virtual bool IsMIDI () const = 0;
virtual bool IsMIDI () const;
virtual bool IsValid () const = 0;
virtual bool SetPosition (unsigned int ms);
virtual bool SetSubsong (int subsong);

View file

@ -23,6 +23,7 @@
#include "mus2midi.h"
#include "i_sound.h"
#include "i_music.h"
#include "s_sound.h"
void I_InitMusicWin32 ();
void I_ShutdownMusicWin32 ();
@ -404,24 +405,10 @@ protected:
// Base class for streaming MUS and MIDI files ------------------------------
// MIDI device selection.
enum EMIDIDevice
{
MIDI_Win,
MIDI_OPL,
MIDI_GUS,
MIDI_Fluid,
MIDI_FMOD,
MIDI_Timidity,
// only used by I_RegisterSong
MIDI_Null,
};
class MIDIStreamer : public MusInfo
{
public:
MIDIStreamer(EMIDIDevice type);
MIDIStreamer(EMidiDevice type);
~MIDIStreamer();
void MusicVolumeChanged();
@ -442,7 +429,7 @@ public:
void CreateSMF(TArray<BYTE> &file);
protected:
MIDIStreamer(const char *dumpname, EMIDIDevice type);
MIDIStreamer(const char *dumpname, EMidiDevice type);
void OutputVolume (DWORD volume);
int FillBuffer(int buffer_num, int max_events, DWORD max_time);
@ -450,6 +437,8 @@ protected:
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;
static void Callback(unsigned int uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2);
@ -498,7 +487,7 @@ protected:
int InitialTempo;
BYTE ChannelVolumes[16];
DWORD Volume;
EMIDIDevice DeviceType;
EMidiDevice DeviceType;
bool CallbackIsThreaded;
int LoopLimit;
FString DumpFilename;
@ -509,14 +498,14 @@ protected:
class MUSSong2 : public MIDIStreamer
{
public:
MUSSong2(FILE *file, BYTE *musiccache, int length, EMIDIDevice type);
MUSSong2(FILE *file, BYTE *musiccache, int length, EMidiDevice type);
~MUSSong2();
MusInfo *GetOPLDumper(const char *filename);
MusInfo *GetWaveDumper(const char *filename, int rate);
protected:
MUSSong2(const MUSSong2 *original, const char *filename, EMIDIDevice type); // file dump constructor
MUSSong2(const MUSSong2 *original, const char *filename, EMidiDevice type); // file dump constructor
void DoInitialSetup();
void DoRestart();
@ -535,14 +524,14 @@ protected:
class MIDISong2 : public MIDIStreamer
{
public:
MIDISong2(FILE *file, BYTE *musiccache, int length, EMIDIDevice type);
MIDISong2(FILE *file, BYTE *musiccache, int length, EMidiDevice type);
~MIDISong2();
MusInfo *GetOPLDumper(const char *filename);
MusInfo *GetWaveDumper(const char *filename, int rate);
protected:
MIDISong2(const MIDISong2 *original, const char *filename, EMIDIDevice type); // file dump constructor
MIDISong2(const MIDISong2 *original, const char *filename, EMidiDevice type); // file dump constructor
void CheckCaps(int tech);
void DoInitialSetup();
@ -592,14 +581,14 @@ protected:
class HMISong : public MIDIStreamer
{
public:
HMISong(FILE *file, BYTE *musiccache, int length, EMIDIDevice type);
HMISong(FILE *file, BYTE *musiccache, int length, EMidiDevice type);
~HMISong();
MusInfo *GetOPLDumper(const char *filename);
MusInfo *GetWaveDumper(const char *filename, int rate);
protected:
HMISong(const HMISong *original, const char *filename, EMIDIDevice type); // file dump constructor
HMISong(const HMISong *original, const char *filename, EMidiDevice type); // file dump constructor
void SetupForHMI(int len);
void SetupForHMP(int len);
@ -634,7 +623,7 @@ protected:
class XMISong : public MIDIStreamer
{
public:
XMISong(FILE *file, BYTE *musiccache, int length, EMIDIDevice type);
XMISong(FILE *file, BYTE *musiccache, int length, EMidiDevice type);
~XMISong();
MusInfo *GetOPLDumper(const char *filename);
@ -644,7 +633,7 @@ protected:
struct TrackInfo;
enum EventSource { EVENT_None, EVENT_Real, EVENT_Fake };
XMISong(const XMISong *original, const char *filename, EMIDIDevice type); // file dump constructor
XMISong(const XMISong *original, const char *filename, EMidiDevice type); // file dump constructor
int FindXMIDforms(const BYTE *chunk, int len, TrackInfo *songs) const;
void FoundXMID(const BYTE *chunk, int len, TrackInfo *song) const;
@ -680,7 +669,6 @@ public:
void Resume ();
void Stop ();
bool IsPlaying ();
bool IsMIDI () const { return false; }
bool IsValid () const { return m_Stream != NULL; }
bool SetPosition (unsigned int pos);
bool SetSubsong (int subsong);
@ -732,7 +720,6 @@ public:
void Resume ();
void Stop ();
bool IsPlaying ();
bool IsMIDI () const { return false; }
bool IsValid () const { return m_Inited; }
protected:

View file

@ -127,7 +127,7 @@ extern char MIDI_CommonLengths[15];
//
//==========================================================================
HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), Tracks(0)
{
#ifdef _WIN32
@ -983,7 +983,7 @@ HMISong::TrackInfo *HMISong::FindNextDue ()
MusInfo *HMISong::GetOPLDumper(const char *filename)
{
return new HMISong(this, filename, MIDI_OPL);
return new HMISong(this, filename, MDEV_OPL);
}
//==========================================================================
@ -994,7 +994,7 @@ MusInfo *HMISong::GetOPLDumper(const char *filename)
MusInfo *HMISong::GetWaveDumper(const char *filename, int rate)
{
return new HMISong(this, filename, MIDI_GUS);
return new HMISong(this, filename, MDEV_GUS);
}
//==========================================================================
@ -1003,7 +1003,7 @@ MusInfo *HMISong::GetWaveDumper(const char *filename, int rate)
//
//==========================================================================
HMISong::HMISong(const HMISong *original, const char *filename, EMIDIDevice type)
HMISong::HMISong(const HMISong *original, const char *filename, EMidiDevice type)
: MIDIStreamer(filename, type)
{
SongLen = original->SongLen;

View file

@ -38,13 +38,28 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
}
static void MIDIDeviceChanged(int newdev)
{
static int oldmididev = INT_MIN;
// If a song is playing, move it to the new device.
if (oldmididev != newdev && currSong != NULL && currSong->IsMIDI())
{
MusInfo *song = currSong;
if (song->m_Status == MusInfo::STATE_Playing)
{
song->Stop();
song->Start(song->m_Looping);
}
}
oldmididev = newdev;
}
#ifdef _WIN32
UINT mididevice;
CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
UINT oldmididev = mididevice;
if (!nummididevicesset)
return;
@ -54,26 +69,8 @@ CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
self = 0;
return;
}
else if (self < 0)
{
mididevice = 0;
}
else
{
mididevice = self;
}
// If a song is playing, move it to the new device.
if (oldmididev != mididevice && currSong != NULL && currSong->IsMIDI())
{
// Does this even work, except for Windows system devices?
MusInfo *song = currSong;
if (song->m_Status == MusInfo::STATE_Playing)
{
song->Stop();
song->Start(song->m_Looping);
}
}
mididevice = MAX<UINT>(0, self);
MIDIDeviceChanged(self);
}
void I_InitMusicWin32 ()
@ -196,6 +193,8 @@ CUSTOM_CVAR(Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
self = -5;
else if (self > -1)
self = -1;
else
MIDIDeviceChanged(self);
}
void I_BuildMIDIMenuList (FOptionValues *opt)

View file

@ -57,6 +57,7 @@ static void WriteVarLen (TArray<BYTE> &file, DWORD value);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
EXTERN_CVAR(Float, snd_musicvolume)
EXTERN_CVAR(Int, snd_mididevice)
#ifdef _WIN32
extern UINT mididevice;
@ -87,7 +88,7 @@ static const BYTE StaticMIDIhead[] =
//
//==========================================================================
MIDIStreamer::MIDIStreamer(EMIDIDevice type)
MIDIStreamer::MIDIStreamer(EMidiDevice type)
:
#ifdef _WIN32
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
@ -115,7 +116,7 @@ MIDIStreamer::MIDIStreamer(EMIDIDevice type)
//
//==========================================================================
MIDIStreamer::MIDIStreamer(const char *dumpname, EMIDIDevice type)
MIDIStreamer::MIDIStreamer(const char *dumpname, EMidiDevice type)
:
#ifdef _WIN32
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
@ -194,6 +195,98 @@ void MIDIStreamer::CheckCaps(int tech)
{
}
//==========================================================================
//
// MIDIStreamer :: SelectMIDIDevice static
//
// Select the MIDI device to play on
//
//==========================================================================
EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
{
/* MIDI are played as:
- OPL:
- if explicitly selected by $mididevice
- when snd_mididevice is -3 and no midi device is set for the song
- Timidity:
- if explicitly selected by $mididevice
- when snd_mididevice is -2 and no midi device is set for the song
- FMod:
- if explicitly selected by $mididevice
- when snd_mididevice is -1 and no midi device is set for the song
- as fallback when both OPL and Timidity failed unless snd_mididevice is >= 0
- MMAPI (Win32 only):
- if explicitly selected by $mididevice (non-Win32 redirects this to FMOD)
- when snd_mididevice is >= 0 and no midi device is set for the song
- as fallback when both OPL and Timidity failed and snd_mididevice is >= 0
*/
// Choose the type of MIDI device we want.
if (device != MDEV_DEFAULT)
{
return device;
}
switch (snd_mididevice)
{
case -1: return MDEV_FMOD;
case -2: return MDEV_TIMIDITY;
case -3: return MDEV_OPL;
case -4: return MDEV_GUS;
#ifdef HAVE_FLUIDSYNTH
case -5: return MDEV_FLUIDSYNTH;
#endif
default:
#ifdef _WIN32
return MDEV_MMAPI;
#else
return MDEV_FMOD;
#endif
}
}
//==========================================================================
//
// MIDIStreamer :: CreateMIDIDevice
//
//==========================================================================
MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
{
switch (devtype)
{
case MDEV_MMAPI:
#ifdef _WIN32
return new WinMIDIDevice(mididevice);
#endif
assert(0);
// Intentional fall-through for non-Windows systems.
#ifdef HAVE_FLUIDSYNTH
case MDEV_FLUIDSYNTH:
return new FluidSynthMIDIDevice;
#endif
case MDEV_FMOD:
return new FMODMIDIDevice;
case MDEV_GUS:
return new TimidityMIDIDevice;
case MDEV_OPL:
return new OPLMIDIDevice;
case MDEV_TIMIDITY:
return new TimidityPPMIDIDevice;
default:
return NULL;
}
}
//==========================================================================
//
// MIDIStreamer :: Play
@ -203,6 +296,7 @@ void MIDIStreamer::CheckCaps(int tech)
void MIDIStreamer::Play(bool looping, int subsong)
{
DWORD tid;
EMidiDevice devtype;
m_Status = STATE_Stopped;
m_Looping = looping;
@ -212,52 +306,21 @@ void MIDIStreamer::Play(bool looping, int subsong)
InitialPlayback = true;
assert(MIDI == NULL);
devtype = SelectMIDIDevice(DeviceType);
if (DumpFilename.IsNotEmpty())
{
if (DeviceType == MIDI_OPL)
if (devtype == MDEV_OPL)
{
MIDI = new OPLDumperMIDIDevice(DumpFilename);
}
else if (DeviceType == MIDI_GUS)
else if (devtype == MDEV_GUS)
{
MIDI = new TimidityWaveWriterMIDIDevice(DumpFilename, 0);
}
}
else switch(DeviceType)
else
{
case MIDI_Win:
#ifdef _WIN32
MIDI = new WinMIDIDevice(mididevice);
break;
#endif
assert(0);
// Intentional fall-through for non-Windows systems.
#ifdef HAVE_FLUIDSYNTH
case MIDI_Fluid:
MIDI = new FluidSynthMIDIDevice;
break;
#endif
case MIDI_FMOD:
MIDI = new FMODMIDIDevice;
break;
case MIDI_GUS:
MIDI = new TimidityMIDIDevice;
break;
case MIDI_OPL:
MIDI = new OPLMIDIDevice;
break;
case MIDI_Timidity:
MIDI = new TimidityPPMIDIDevice;
break;
default:
MIDI = NULL;
break;
MIDI = CreateMIDIDevice(devtype);
}
#ifndef _WIN32

View file

@ -91,7 +91,7 @@ static const BYTE CtrlTranslate[15] =
//
//==========================================================================
MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), MusBuffer(0)
{
#ifdef _WIN32
@ -371,7 +371,7 @@ end:
MusInfo *MUSSong2::GetOPLDumper(const char *filename)
{
return new MUSSong2(this, filename, MIDI_OPL);
return new MUSSong2(this, filename, MDEV_OPL);
}
//==========================================================================
@ -382,7 +382,7 @@ MusInfo *MUSSong2::GetOPLDumper(const char *filename)
MusInfo *MUSSong2::GetWaveDumper(const char *filename, int rate)
{
return new MUSSong2(this, filename, MIDI_GUS);
return new MUSSong2(this, filename, MDEV_GUS);
}
//==========================================================================
@ -391,7 +391,7 @@ MusInfo *MUSSong2::GetWaveDumper(const char *filename, int rate)
//
//==========================================================================
MUSSong2::MUSSong2(const MUSSong2 *original, const char *filename, EMIDIDevice type)
MUSSong2::MUSSong2(const MUSSong2 *original, const char *filename, EMidiDevice type)
: MIDIStreamer(filename, type)
{
int songstart = LittleShort(original->MusHeader->SongStart);

View file

@ -101,7 +101,7 @@ char MIDI_CommonLengths[15] = { 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
//
//==========================================================================
MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), Tracks(0)
{
int p;
@ -782,7 +782,7 @@ MIDISong2::TrackInfo *MIDISong2::FindNextDue ()
MusInfo *MIDISong2::GetOPLDumper(const char *filename)
{
return new MIDISong2(this, filename, MIDI_OPL);
return new MIDISong2(this, filename, MDEV_OPL);
}
//==========================================================================
@ -793,7 +793,7 @@ MusInfo *MIDISong2::GetOPLDumper(const char *filename)
MusInfo *MIDISong2::GetWaveDumper(const char *filename, int rate)
{
return new MIDISong2(this, filename, MIDI_GUS);
return new MIDISong2(this, filename, MDEV_GUS);
}
//==========================================================================
@ -802,7 +802,7 @@ MusInfo *MIDISong2::GetWaveDumper(const char *filename, int rate)
//
//==========================================================================
MIDISong2::MIDISong2(const MIDISong2 *original, const char *filename, EMIDIDevice type)
MIDISong2::MIDISong2(const MIDISong2 *original, const char *filename, EMidiDevice type)
: MIDIStreamer(filename, type)
{
SongLen = original->SongLen;

View file

@ -107,7 +107,7 @@ extern char MIDI_CommonLengths[15];
//
//==========================================================================
XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), Songs(0)
{
#ifdef _WIN32
@ -683,7 +683,7 @@ XMISong::EventSource XMISong::FindNextDue()
MusInfo *XMISong::GetOPLDumper(const char *filename)
{
return new XMISong(this, filename, MIDI_OPL);
return new XMISong(this, filename, MDEV_OPL);
}
//==========================================================================
@ -694,7 +694,7 @@ MusInfo *XMISong::GetOPLDumper(const char *filename)
MusInfo *XMISong::GetWaveDumper(const char *filename, int rate)
{
return new XMISong(this, filename, MIDI_GUS);
return new XMISong(this, filename, MDEV_GUS);
}
//==========================================================================
@ -703,7 +703,7 @@ MusInfo *XMISong::GetWaveDumper(const char *filename, int rate)
//
//==========================================================================
XMISong::XMISong(const XMISong *original, const char *filename, EMIDIDevice type)
XMISong::XMISong(const XMISong *original, const char *filename, EMidiDevice type)
: MIDIStreamer(filename, type)
{
SongLen = original->SongLen;