AUDIO: Add pure virtual MidiDriver::isOpen() method

This in turn enables modifying MidiDriver_MPU401::close() to allow
it to be called on a midi driver that has not yet been opened.

The specific issue that triggered me to make these changes was a
crash-upon-quit in HUGO, caused by it instantiating a midi driver,
then encountering an error (missing hugo.dat) *before* having
opened the new midi driver; the general cleanup code then tries
to close the (not yet opened) midi driver -> kaboom

Also fixed some engines which were leaking MidiDriver instances.
This commit is contained in:
Max Horn 2011-03-21 15:42:17 +01:00
parent 92716d71ed
commit 8982fff1b7
43 changed files with 175 additions and 65 deletions

View file

@ -182,6 +182,11 @@ public:
*/ */
virtual int open() = 0; virtual int open() = 0;
/**
* Check whether the midi driver has already been opened.
*/
virtual bool isOpen() const = 0;
/** Close the midi driver. */ /** Close the midi driver. */
virtual void close() = 0; virtual void close() = 0;

View file

@ -105,12 +105,15 @@ MidiDriver_MPU401::~MidiDriver_MPU401() {
} }
void MidiDriver_MPU401::close() { void MidiDriver_MPU401::close() {
if (_timer_proc) if (_timer_proc) {
g_system->getTimerManager()->removeTimerProc(_timer_proc); g_system->getTimerManager()->removeTimerProc(_timer_proc);
_timer_proc = 0; _timer_proc = 0;
}
if (isOpen()) {
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
send(0x7B << 8 | 0xB0 | i); send(0x7B << 8 | 0xB0 | i);
} }
}
uint32 MidiDriver_MPU401::property(int prop, uint32 param) { uint32 MidiDriver_MPU401::property(int prop, uint32 param) {
switch (prop) { switch (prop) {

View file

@ -33,6 +33,7 @@
class MidiDriver_NULL : public MidiDriver_MPU401 { class MidiDriver_NULL : public MidiDriver_MPU401 {
public: public:
int open() { return 0; } int open() { return 0; }
bool isOpen() const { return true; }
void send(uint32 b) { } void send(uint32 b) { }
}; };

View file

@ -76,6 +76,8 @@ public:
return 0; return 0;
} }
bool isOpen() const { return _isOpen; }
virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
_timerProc = timer_proc; _timerProc = timer_proc;
_timerParam = timer_param; _timerParam = timer_param;

View file

@ -71,6 +71,7 @@ class MidiDriver_ALSA : public MidiDriver_MPU401 {
public: public:
MidiDriver_ALSA(int client, int port); MidiDriver_ALSA(int client, int port);
int open(); int open();
bool isOpen() const { return _isOpen; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);

View file

@ -46,6 +46,7 @@ class MidiDriver_CAMD : public MidiDriver_MPU401 {
public: public:
MidiDriver_CAMD(); MidiDriver_CAMD();
int open(); int open();
bool isOpen() const { return _isOpen; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);

View file

@ -72,7 +72,9 @@ do { \
class MidiDriver_CORE : public MidiDriver_MPU401 { class MidiDriver_CORE : public MidiDriver_MPU401 {
public: public:
MidiDriver_CORE(); MidiDriver_CORE();
~MidiDriver_CORE();
int open(); int open();
bool isOpen() const { return _auGraph != 0; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);
@ -86,10 +88,18 @@ MidiDriver_CORE::MidiDriver_CORE()
: _auGraph(0) { : _auGraph(0) {
} }
MidiDriver_CORE::~MidiDriver_CORE() {
if (_auGraph) {
AUGraphStop(_auGraph);
DisposeAUGraph(_auGraph);
_auGraph = 0;
}
}
int MidiDriver_CORE::open() { int MidiDriver_CORE::open() {
OSStatus err = 0; OSStatus err = 0;
if (_auGraph) if (isOpen())
return MERR_ALREADY_OPEN; return MERR_ALREADY_OPEN;
// Open the Music Device. // Open the Music Device.
@ -176,7 +186,6 @@ bail:
void MidiDriver_CORE::close() { void MidiDriver_CORE::close() {
MidiDriver_MPU401::close(); MidiDriver_MPU401::close();
if (_auGraph) { if (_auGraph) {
AUGraphStop(_auGraph); AUGraphStop(_auGraph);
DisposeAUGraph(_auGraph); DisposeAUGraph(_auGraph);
@ -185,7 +194,7 @@ void MidiDriver_CORE::close() {
} }
void MidiDriver_CORE::send(uint32 b) { void MidiDriver_CORE::send(uint32 b) {
assert(_auGraph != NULL); assert(isOpen());
byte status_byte = (b & 0x000000FF); byte status_byte = (b & 0x000000FF);
byte first_byte = (b & 0x0000FF00) >> 8; byte first_byte = (b & 0x0000FF00) >> 8;
@ -198,7 +207,7 @@ void MidiDriver_CORE::sysEx(const byte *msg, uint16 length) {
unsigned char buf[266]; unsigned char buf[266];
assert(length + 2 <= ARRAYSIZE(buf)); assert(length + 2 <= ARRAYSIZE(buf));
assert(_auGraph != NULL); assert(isOpen());
// Add SysEx frame // Add SysEx frame
buf[0] = 0xF0; buf[0] = 0xF0;

View file

@ -56,6 +56,7 @@ public:
MidiDriver_CoreMIDI(); MidiDriver_CoreMIDI();
~MidiDriver_CoreMIDI(); ~MidiDriver_CoreMIDI();
int open(); int open();
bool isOpen() const { return mOutPort != 0 && mDest != 0; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);
@ -80,7 +81,7 @@ MidiDriver_CoreMIDI::~MidiDriver_CoreMIDI() {
} }
int MidiDriver_CoreMIDI::open() { int MidiDriver_CoreMIDI::open() {
if (mDest) if (isOpen())
return MERR_ALREADY_OPEN; return MERR_ALREADY_OPEN;
OSStatus err = noErr; OSStatus err = noErr;
@ -106,7 +107,7 @@ int MidiDriver_CoreMIDI::open() {
void MidiDriver_CoreMIDI::close() { void MidiDriver_CoreMIDI::close() {
MidiDriver_MPU401::close(); MidiDriver_MPU401::close();
if (mOutPort && mDest) { if (isOpen()) {
MIDIPortDispose(mOutPort); MIDIPortDispose(mOutPort);
mOutPort = 0; mOutPort = 0;
mDest = 0; mDest = 0;
@ -114,8 +115,7 @@ void MidiDriver_CoreMIDI::close() {
} }
void MidiDriver_CoreMIDI::send(uint32 b) { void MidiDriver_CoreMIDI::send(uint32 b) {
assert(mOutPort != 0); assert(isOpen());
assert(mDest != 0);
// Extract the MIDI data // Extract the MIDI data
byte status_byte = (b & 0x000000FF); byte status_byte = (b & 0x000000FF);
@ -158,8 +158,7 @@ void MidiDriver_CoreMIDI::send(uint32 b) {
} }
void MidiDriver_CoreMIDI::sysEx(const byte *msg, uint16 length) { void MidiDriver_CoreMIDI::sysEx(const byte *msg, uint16 length) {
assert(mOutPort != 0); assert(isOpen());
assert(mDest != 0);
byte buf[384]; byte buf[384];
MIDIPacketList *packetList = (MIDIPacketList *)buf; MIDIPacketList *packetList = (MIDIPacketList *)buf;

View file

@ -57,6 +57,7 @@ class MidiDriver_DMEDIA : public MidiDriver_MPU401 {
public: public:
MidiDriver_DMEDIA(); MidiDriver_DMEDIA();
int open(); int open();
bool isOpen() const { return _isOpen; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);

View file

@ -55,6 +55,7 @@ class MidiDriver_SEQ : public MidiDriver_MPU401 {
public: public:
MidiDriver_SEQ(); MidiDriver_SEQ();
int open(); int open();
bool isOpen() const { return _isOpen; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);

View file

@ -50,6 +50,7 @@ class MidiDriver_STMIDI : public MidiDriver_MPU401 {
public: public:
MidiDriver_STMIDI() : _isOpen (false) { } MidiDriver_STMIDI() : _isOpen (false) { }
int open(); int open();
bool isOpen() const { return _isOpen; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);
@ -59,7 +60,7 @@ private:
}; };
int MidiDriver_STMIDI::open() { int MidiDriver_STMIDI::open() {
if ((_isOpen) && (!Bcostat(4))) if (_isOpen && (!Bcostat(4)))
return MERR_ALREADY_OPEN; return MERR_ALREADY_OPEN;
warning("ST Midi Port Open"); warning("ST Midi Port Open");
_isOpen = true; _isOpen = true;

View file

@ -93,6 +93,7 @@ public:
MidiDriver_TIMIDITY(); MidiDriver_TIMIDITY();
int open(); int open();
bool isOpen() const { return _isOpen; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);

View file

@ -61,6 +61,7 @@ private:
public: public:
MidiDriver_WIN(int deviceIndex) : _isOpen(false), _device(deviceIndex) { } MidiDriver_WIN(int deviceIndex) : _isOpen(false), _device(deviceIndex) { }
int open(); int open();
bool isOpen() const { return _isOpen; }
void close(); void close();
void send(uint32 b); void send(uint32 b);
void sysEx(const byte *msg, uint16 length); void sysEx(const byte *msg, uint16 length);
@ -93,6 +94,8 @@ void MidiDriver_WIN::close() {
} }
void MidiDriver_WIN::send(uint32 b) { void MidiDriver_WIN::send(uint32 b) {
assert(_isOpen);
union { union {
DWORD dwData; DWORD dwData;
BYTE bData[4]; BYTE bData[4];

View file

@ -138,6 +138,10 @@ int SoundGenMIDI::open() {
return 0; return 0;
} }
bool SoundGenMIDI::isOpen() const {
return _driver && _driver->isOpen();
}
void SoundGenMIDI::close() { void SoundGenMIDI::close() {
stop(); stop();
if (_driver) if (_driver)

View file

@ -72,6 +72,7 @@ public:
// MidiDriver interface implementation // MidiDriver interface implementation
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);

View file

@ -85,11 +85,17 @@ int MidiPlayer::open() {
return 0; return 0;
} }
bool MidiPlayer::isOpen() const {
return _driver && _driver->isOpen();
}
void MidiPlayer::close() { void MidiPlayer::close() {
stop(); stop();
// _system->lockMutex(_mutex); // _system->lockMutex(_mutex);
if (_driver) if (_driver) {
delete _driver;
_driver->close(); _driver->close();
}
_driver = NULL; _driver = NULL;
clearConstructs(); clearConstructs();
// _system->unlockMutex(_mutex); // _system->unlockMutex(_mutex);

View file

@ -115,6 +115,7 @@ public:
public: public:
// MidiDriver interface implementation // MidiDriver interface implementation
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);

View file

@ -97,10 +97,16 @@ int MusicPlayer::open() {
return 0; return 0;
} }
bool MusicPlayer::isOpen() const {
return _driver && _driver->isOpen();
}
void MusicPlayer::close() { void MusicPlayer::close() {
stop(); stop();
if (_driver) if (_driver) {
_driver->close(); _driver->close();
delete _driver;
}
_driver = 0; _driver = 0;
} }

View file

@ -61,6 +61,7 @@ public:
// MidiDriver interface implementation // MidiDriver interface implementation
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);

View file

@ -264,6 +264,10 @@ int MusicPlayerMidi::open() {
return 0; return 0;
} }
bool MusicPlayerMidi::isOpen() const {
return _driver && _driver->isOpen();
}
void MusicPlayerMidi::close() {} void MusicPlayerMidi::close() {}
void MusicPlayerMidi::send(uint32 b) { void MusicPlayerMidi::send(uint32 b) {

View file

@ -95,6 +95,7 @@ public:
// MidiDriver interface // MidiDriver interface
virtual int open(); virtual int open();
virtual bool isOpen() const;
virtual void close(); virtual void close();
virtual void send(uint32 b); virtual void send(uint32 b);
virtual void metaEvent(byte type, byte *data, uint16 length); virtual void metaEvent(byte type, byte *data, uint16 length);

View file

@ -192,6 +192,10 @@ int MidiPlayer::open() {
return 0; return 0;
} }
bool MidiPlayer::isOpen() const {
return _driver && _driver->isOpen();
}
void MidiPlayer::close() { void MidiPlayer::close() {
stop(); stop();
_mutex.lock(); _mutex.lock();

View file

@ -60,6 +60,7 @@ public:
// MidiDriver interface // MidiDriver interface
int open(); int open();
bool isOpen() const;
MidiChannel *allocateChannel(); MidiChannel *allocateChannel();
MidiChannel *getPercussionChannel(); MidiChannel *getPercussionChannel();

View file

@ -55,6 +55,7 @@ public:
// DUMMY // DUMMY
int open() { return 0; } int open() { return 0; }
bool isOpen() const { return true; }
void close() {} void close() {}
MidiChannel *allocateChannel() { return 0; } MidiChannel *allocateChannel() { return 0; }

View file

@ -694,6 +694,10 @@ int MidiMusic::open() {
return 0; return 0;
} }
bool MidiMusic::isOpen() const {
return _driver != 0;
}
void MidiMusic::close() { void MidiMusic::close() {
} }

View file

@ -86,6 +86,7 @@ public:
//MidiDriver interface implementation //MidiDriver interface implementation
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);
void onTimer(); void onTimer();

View file

@ -83,10 +83,16 @@ int MidiPlayer::open() {
return 0; return 0;
} }
bool MidiPlayer::isOpen() const {
return _driver && _driver->isOpen();
}
void MidiPlayer::close() { void MidiPlayer::close() {
stopMusic(); stopMusic();
if (_driver) if (_driver) {
_driver->close(); _driver->close();
delete _driver;
}
_driver = 0; _driver = 0;
} }

View file

@ -54,6 +54,7 @@ public:
//MidiDriver interface implementation //MidiDriver interface implementation
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);

View file

@ -89,10 +89,16 @@ int MusicPlayer::open() {
return 0; return 0;
} }
bool MusicPlayer::isOpen() const {
return _driver && _driver->isOpen();
}
void MusicPlayer::close() { void MusicPlayer::close() {
stop(); stop();
if (_driver) if (_driver) {
_driver->close(); _driver->close();
delete _driver;
}
_driver = 0; _driver = 0;
} }

View file

@ -66,6 +66,7 @@ public:
//MidiDriver interface implementation //MidiDriver interface implementation
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);

View file

@ -222,6 +222,7 @@ public:
// MidiDriver interface // MidiDriver interface
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);
void metaEvent(byte type, byte *data, uint16 length); void metaEvent(byte type, byte *data, uint16 length);
@ -342,6 +343,10 @@ int MidiPlayer_MSC::open() {
return ret; return ret;
} }
bool MidiPlayer_MSC::isOpen() const {
return _driver && _driver->isOpen();
}
void MidiPlayer_MSC::close() { void MidiPlayer_MSC::close() {
stop(); stop();
_mutex.lock(); _mutex.lock();

View file

@ -59,6 +59,7 @@ public:
// MidiDriver interface // MidiDriver interface
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);
void metaEvent(byte type, byte *data, uint16 length); void metaEvent(byte type, byte *data, uint16 length);
@ -178,6 +179,10 @@ int MidiPlayer::open() {
return ret; return ret;
} }
bool MidiPlayer::isOpen() const {
return _driver && _driver->isOpen();
}
void MidiPlayer::close() { void MidiPlayer::close() {
stop(); stop();
_mutex.lock(); _mutex.lock();

View file

@ -78,8 +78,10 @@ MidiMusic::MidiMusic(QueenEngine *vm)
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
} }
} }
assert(_driver);
_driver->open(); int ret = _driver->open();
assert(ret == 0);
_driver->setTimerCallback(this, &timerCallback); _driver->setTimerCallback(this, &timerCallback);
if (_nativeMT32) if (_nativeMT32)

View file

@ -58,6 +58,7 @@ public:
//MidiDriver interface implementation //MidiDriver interface implementation
int open() { return 0; } int open() { return 0; }
bool isOpen() const { return true; }
void close() {} void close() {}
void send(uint32 b); void send(uint32 b);

View file

@ -50,6 +50,7 @@ MusicDriver::MusicDriver() : _isGM(false) {
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
_driver = MidiDriver::createMidi(dev); _driver = MidiDriver::createMidi(dev);
assert(_driver);
_driverType = MidiDriver::getMusicType(dev); _driverType = MidiDriver::getMusicType(dev);
if (isMT32()) if (isMT32())
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
@ -75,6 +76,10 @@ int MusicDriver::open() {
return 0; return 0;
} }
bool MusicDriver::isOpen() const {
return _driver->isOpen();
}
void MusicDriver::setVolume(int volume) { void MusicDriver::setVolume(int volume) {
volume = CLIP(volume, 0, 255); volume = CLIP(volume, 0, 255);

View file

@ -58,6 +58,7 @@ public:
//MidiDriver interface implementation //MidiDriver interface implementation
int open(); int open();
bool isOpen() const;
void close() { _driver->close(); } void close() { _driver->close(); }
void send(uint32 b); void send(uint32 b);

View file

@ -89,6 +89,7 @@ public:
return open(resMan); return open(resMan);
} }
virtual int open(ResourceManager *resMan) { return _driver->open(); } virtual int open(ResourceManager *resMan) { return _driver->open(); }
bool isOpen() const { return _driver->isOpen(); }
virtual void close() { _driver->close(); } virtual void close() { _driver->close(); }
virtual void send(uint32 b) { _driver->send(b); } virtual void send(uint32 b) { _driver->send(b); }
uint32 getBaseTempo() { return _driver->getBaseTempo(); } uint32 getBaseTempo() { return _driver->getBaseTempo(); }

View file

@ -284,6 +284,7 @@ public:
public: public:
// MidiDriver interface // MidiDriver interface
int open() { return 0; } int open() { return 0; }
bool isOpen() const { return true; }
void close() { } void close() { }
void send(uint32 b); void send(uint32 b);
const char *getErrorName(int error_code) { return "Unknown"; } const char *getErrorName(int error_code) { return "Unknown"; }

View file

@ -432,10 +432,16 @@ int MidiMusicPlayer::open() {
return 0; return 0;
} }
bool MidiMusicPlayer::isOpen() const {
return _driver && _driver->isOpen();
}
void MidiMusicPlayer::close() { void MidiMusicPlayer::close() {
stop(); stop();
if (_driver) if (_driver) {
_driver->close(); _driver->close();
delete _driver;
}
_driver = 0; _driver = 0;
} }

View file

@ -80,6 +80,7 @@ public:
//MidiDriver interface implementation //MidiDriver interface implementation
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);

View file

@ -110,6 +110,10 @@ int MidiPlayer::open() {
return ret; return ret;
} }
bool MidiPlayer::isOpen() const {
return _driver && _driver->isOpen();
}
void MidiPlayer::close() { void MidiPlayer::close() {
stop(); stop();
_mutex.lock(); _mutex.lock();

View file

@ -59,6 +59,7 @@ public:
// MidiDriver interface // MidiDriver interface
int open(); int open();
bool isOpen() const;
void close(); void close();
void send(uint32 b); void send(uint32 b);
void metaEvent(byte type, byte *data, uint16 length); void metaEvent(byte type, byte *data, uint16 length);