[Scummvm-cvs-logs] scummvm master -> e70fd59b3505619cccb6f3280a4cf0fb57aefa97

fingolfin max at quendi.de
Wed Mar 23 16:51:16 CET 2011


This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
4172414e35 COMMON: Remove TODO from struct Event
756f592b61 SCUMM: Remove unused iMuse MIDI 'passthrough' code
99dbecf3b4 TINSEL: Make MidiMusicPlayer::_parser and _mutex protected
7b02dac3c5 ENGINES: Use Common::StackLock in more places
2bc842dcee AGOS: Sanitize the mutex locking in MidiPlayer::startTrack
a539be098d AUDIO: Update some comments, remove some obsolete ones
c70c8864f1 AUDIO: Introduce a new MidiDriver_BASE base class.
29847ea42d AUDIO: Change several fake MidiDrivers to MidiDriver_BASE subclasses
e70fd59b35 ENGINES: Further simplify pseudo MidiDrivers; fix some regressions


Commit: 4172414e358099bb937044629d6d9c794637629c
    https://github.com/scummvm/scummvm/commit/4172414e358099bb937044629d6d9c794637629c
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T07:25:46-07:00

Commit Message:
COMMON: Remove TODO from struct Event

I moved this TODO to the Wiki TODO page and extended it there. Yet
while I originally wrote it, I now think that we are probably best off
keeping things as they are.

Changed paths:
    common/events.h



diff --git a/common/events.h b/common/events.h
index f9ebce7..120d7d9 100644
--- a/common/events.h
+++ b/common/events.h
@@ -81,30 +81,6 @@ enum EventType {
 /**
  * Data structure for an event. A pointer to an instance of Event
  * can be passed to pollEvent.
- * @todo Rework/document this structure. It should be made 100% clear which
- *       field is valid for which event type.
- *       Implementation wise, we might want to use the classic
- *       union-of-structs trick. It goes roughly like this:
- *       struct BasicEvent {
- *          EventType type;
- *       };
- *       struct MouseMovedEvent : BasicEvent {
- *          Common::Point pos;
- *       };
- *       struct MouseButtonEvent : MouseMovedEvent {
- *          int button;
- *       };
- *       struct KeyEvent : BasicEvent {
- *          ...
- *       };
- *       ...
- *       union Event {
- *          EventType type;
- *          MouseMovedEvent mouse;
- *          MouseButtonEvent button;
- *          KeyEvent key;
- *          ...
- *       };
  */
 struct Event {
 	/** The type of the event. */


Commit: 756f592b61c0c1ca98b78c30a9be46b5560f0c69
    https://github.com/scummvm/scummvm/commit/756f592b61c0c1ca98b78c30a9be46b5560f0c69
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T07:25:46-07:00

Commit Message:
SCUMM: Remove unused iMuse MIDI 'passthrough' code

Changed paths:
    engines/scumm/imuse/imuse.cpp
    engines/scumm/imuse/imuse.h
    engines/scumm/imuse/imuse_internal.h
    engines/scumm/imuse/imuse_player.cpp
    engines/scumm/scumm.cpp



diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index 4db40e6..6c626cd 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -57,7 +57,6 @@ _initialized(false),
 _tempoFactor(0),
 _player_limit(ARRAYSIZE(_players)),
 _recycle_players(false),
-_direct_passthrough(false),
 _queue_end(0),
 _queue_pos(0),
 _queue_sound(0),
@@ -472,10 +471,6 @@ uint32 IMuseInternal::property(int prop, uint32 value) {
 		_recycle_players = (value != 0);
 		break;
 
-	case IMuse::PROP_DIRECT_PASSTHROUGH:
-		_direct_passthrough = (value != 0);
-		break;
-
 	case IMuse::PROP_GAME_ID:
 		_game_id = value;
 		break;
@@ -636,7 +631,7 @@ bool IMuseInternal::startSound_internal(int sound, int offset) {
 
 	player->clear();
 	player->setOffsetNote(offset);
-	return player->startSound(sound, driver, _direct_passthrough);
+	return player->startSound(sound, driver);
 }
 
 int IMuseInternal::stopSound_internal(int sound) {
diff --git a/engines/scumm/imuse/imuse.h b/engines/scumm/imuse/imuse.h
index d7ce2b7..1e3b0fd 100644
--- a/engines/scumm/imuse/imuse.h
+++ b/engines/scumm/imuse/imuse.h
@@ -58,7 +58,6 @@ public:
 		PROP_GS,
 		PROP_LIMIT_PLAYERS,
 		PROP_RECYCLE_PLAYERS,
-		PROP_DIRECT_PASSTHROUGH,
 		PROP_GAME_ID
 	};
 
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index 3a6470f..d1153a0 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -174,7 +174,6 @@ protected:
 protected:
 	MidiDriver *_midi;
 	MidiParser *_parser;
-	bool _passThrough; // Only respond to EOT, all else direct to MidiDriver
 
 	Part *_parts;
 	bool _active;
@@ -278,7 +277,7 @@ public:
 	void setSpeed(byte speed);
 	int setTranspose(byte relative, int b);
 	int setVolume(byte vol);
-	bool startSound(int sound, MidiDriver *midi, bool passThrough);
+	bool startSound(int sound, MidiDriver *midi);
 	int getMusicTimer() const;
 
 public:
@@ -425,7 +424,6 @@ protected:
 
 	int  _player_limit;       // Limits how many simultaneous music tracks are played
 	bool _recycle_players;    // Can we stop a player in order to start another one?
-	bool _direct_passthrough; // Pass data direct to MidiDriver (no interactivity)
 
 	uint _queue_end, _queue_pos, _queue_sound;
 	byte _queue_adding;
diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp
index ac2b2d4..9958a93 100644
--- a/engines/scumm/imuse/imuse_player.cpp
+++ b/engines/scumm/imuse/imuse_player.cpp
@@ -61,7 +61,6 @@ uint16 Player::_active_notes[128];
 Player::Player() :
 	_midi(NULL),
 	_parser(NULL),
-	_passThrough(0),
 	_parts(NULL),
 	_active(false),
 	_scanning(false),
@@ -93,7 +92,7 @@ Player::~Player() {
 	}
 }
 
-bool Player::startSound(int sound, MidiDriver *midi, bool passThrough) {
+bool Player::startSound(int sound, MidiDriver *midi) {
 	void *ptr;
 	int i;
 
@@ -119,7 +118,6 @@ bool Player::startSound(int sound, MidiDriver *midi, bool passThrough) {
 	_pan = 0;
 	_transpose = 0;
 	_detune = 0;
-	_passThrough = passThrough;
 
 	for (i = 0; i < ARRAYSIZE(_parameterFaders); ++i)
 		_parameterFaders[i].init();
@@ -227,11 +225,6 @@ void Player::setSpeed(byte speed) {
 }
 
 void Player::send(uint32 b) {
-	if (_passThrough) {
-		_midi->send(b);
-		return;
-	}
-
 	byte cmd = (byte)(b & 0xF0);
 	byte chan = (byte)(b & 0x0F);
 	byte param1 = (byte)((b >> 8) & 0xFF);
@@ -348,11 +341,6 @@ void Player::sysEx(const byte *p, uint16 len) {
 	byte buf[128];
 	Part *part;
 
-	if (_passThrough) {
-		_midi->sysEx(p, len);
-		return;
-	}
-
 	// Check SysEx manufacturer.
 	a = *p++;
 	--len;
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 564f3a7..d22b6ee 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1858,17 +1858,15 @@ void ScummEngine::setupMusic(int midi) {
 			if (ConfMan.hasKey("tempo"))
 				_imuse->property(IMuse::PROP_TEMPO_BASE, ConfMan.getInt("tempo"));
 			// YM2162 driver can't handle midi->getPercussionChannel(), NULL shouldn't init MT-32/GM/GS
-			if (/*(midi != MDT_TOWNS) && (*/midi != MDT_NONE/*)*/) {
+			if (midi != MDT_NONE) {
 				_imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32);
 				if (MidiDriver::getMusicType(dev) != MT_MT32) // MT-32 Emulation shouldn't be GM/GS initialized
 					_imuse->property(IMuse::PROP_GS, _enable_gs);
 			}
-			if (_game.heversion >= 60 /*|| midi == MDT_TOWNS*/) {
+			if (_game.heversion >= 60) {
 				_imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1);
 				_imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1);
 			}
-			/*if (midi == MDT_TOWNS)
-				_imuse->property(IMuse::PROP_DIRECT_PASSTHROUGH, 1);*/
 		}
 	}
 }


Commit: 99dbecf3b4a14382fa867610a43201fc150bfda9
    https://github.com/scummvm/scummvm/commit/99dbecf3b4a14382fa867610a43201fc150bfda9
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T07:25:46-07:00

Commit Message:
TINSEL: Make MidiMusicPlayer::_parser and _mutex protected

Changed paths:
    engines/tinsel/music.h



diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h
index 5545200..8f5acc5 100644
--- a/engines/tinsel/music.h
+++ b/engines/tinsel/music.h
@@ -97,13 +97,13 @@ public:
 	MidiChannel *allocateChannel()		{ return 0; }
 	MidiChannel *getPercussionChannel()	{ return 0; }
 
-	MidiParser *_parser;
-	Common::Mutex _mutex;
-
 protected:
 
 	static void onTimer(void *data);
 
+	MidiParser *_parser;
+	Common::Mutex _mutex;
+
 	MidiChannel *_channel[16];
 	MidiDriver *_driver;
 	MidiParser *_xmidiParser;


Commit: 7b02dac3c5678bb47216495fc97130b98ff2bfe4
    https://github.com/scummvm/scummvm/commit/7b02dac3c5678bb47216495fc97130b98ff2bfe4
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T07:25:46-07:00

Commit Message:
ENGINES: Use Common::StackLock in more places

Changed paths:
    engines/hugo/sound.cpp
    engines/parallaction/sound_br.cpp
    engines/parallaction/sound_ns.cpp
    engines/queen/music.cpp
    engines/sci/sound/music.cpp
    engines/scumm/player_pce.cpp
    engines/scumm/player_sid.cpp
    engines/sky/music/musicbase.cpp
    engines/touche/midi.cpp



diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index c4feb5f..33627fb 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -98,26 +98,26 @@ void MidiPlayer::play(uint8 *stream, uint16 size) {
 	_midiData = (uint8 *)malloc(size);
 	if (_midiData) {
 		memcpy(_midiData, stream, size);
-		_mutex.lock();
+
+		Common::StackLock lock(_mutex);
 		syncVolume();
 		_parser->loadMusic(_midiData, size);
 		_parser->setTrack(0);
 		_isLooping = false;
 		_isPlaying = true;
-		_mutex.unlock();
 	}
 }
 
 void MidiPlayer::stop() {
 	debugC(3, kDebugMusic, "MidiPlayer::stop");
-	_mutex.lock();
+
+	Common::StackLock lock(_mutex);
 	if (_isPlaying) {
 		_isPlaying = false;
 		_parser->unloadMusic();
 		free(_midiData);
 		_midiData = 0;
 	}
-	_mutex.unlock();
 }
 
 void MidiPlayer::pause(bool p) {
@@ -135,11 +135,10 @@ void MidiPlayer::updateTimer() {
 		return;
 	}
 
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	if (_isPlaying) {
 		_parser->onTimer();
 	}
-	_mutex.unlock();
 }
 
 void MidiPlayer::adjustVolume(int diff) {
@@ -159,13 +158,13 @@ void MidiPlayer::syncVolume() {
 void MidiPlayer::setVolume(int volume) {
 	debugC(3, kDebugMusic, "MidiPlayer::setVolume");
 	_masterVolume = CLIP(volume, 0, 255);
-	_mutex.lock();
+
+	Common::StackLock lock(_mutex);
 	for (int i = 0; i < kNumbChannels; ++i) {
 		if (_channelsTable[i]) {
 			_channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
 		}
 	}
-	_mutex.unlock();
 }
 
 void MidiPlayer::setChannelVolume(int channel) {
@@ -198,7 +197,8 @@ bool MidiPlayer::isOpen() const {
 
 void MidiPlayer::close() {
 	stop();
-	_mutex.lock();
+
+	Common::StackLock lock(_mutex);
 	_driver->setTimerCallback(0, 0);
 	_driver->close();
 	delete _driver;
@@ -206,7 +206,6 @@ void MidiPlayer::close() {
 	if (_parser)
 		_parser->setMidiDriver(0);
 	delete _parser;
-	_mutex.unlock();
 }
 
 void MidiPlayer::send(uint32 b) {
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index 5be9539..80bd957 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -278,24 +278,23 @@ void MidiPlayer_MSC::play(Common::SeekableReadStream *stream) {
 	if (_midiData) {
 		stream->read(_midiData, size);
 		delete stream;
-		_mutex.lock();
+
+		Common::StackLock lock(_mutex);
 		_parser->loadMusic(_midiData, size);
 		_parser->setTrack(0);
 		_isLooping = true;
 		_isPlaying = true;
-		_mutex.unlock();
 	}
 }
 
 void MidiPlayer_MSC::stop() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	if (_isPlaying) {
 		_isPlaying = false;
 		_parser->unloadMusic();
 		free(_midiData);
 		_midiData = 0;
 	}
-	_mutex.unlock();
 }
 
 void MidiPlayer_MSC::pause(bool p) {
@@ -349,14 +348,14 @@ bool MidiPlayer_MSC::isOpen() const {
 
 void MidiPlayer_MSC::close() {
 	stop();
-	_mutex.lock();
+
+	Common::StackLock lock(_mutex);
 	_driver->setTimerCallback(NULL, NULL);
 	_driver->close();
 	delete _driver;
 	_driver = 0;
 	_parser->setMidiDriver(NULL);
 	delete _parser;
-	_mutex.unlock();
 }
 
 void MidiPlayer_MSC::send(uint32 b) {
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index de8a861..aeb934f 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -111,24 +111,23 @@ void MidiPlayer::play(Common::SeekableReadStream *stream) {
 	if (_midiData) {
 		stream->read(_midiData, size);
 		delete stream;
-		_mutex.lock();
+
+		Common::StackLock lock(_mutex);
 		_parser->loadMusic(_midiData, size);
 		_parser->setTrack(0);
 		_isLooping = true;
 		_isPlaying = true;
-		_mutex.unlock();
 	}
 }
 
 void MidiPlayer::stop() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	if (_isPlaying) {
 		_isPlaying = false;
 		_parser->unloadMusic();
 		free(_midiData);
 		_midiData = 0;
 	}
-	_mutex.unlock();
 }
 
 void MidiPlayer::pause(bool p) {
@@ -146,11 +145,10 @@ void MidiPlayer::updateTimer() {
 		return;
 	}
 
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	if (_isPlaying) {
 		_parser->onTimer();
 	}
-	_mutex.unlock();
 }
 
 void MidiPlayer::adjustVolume(int diff) {
@@ -159,13 +157,13 @@ void MidiPlayer::adjustVolume(int diff) {
 
 void MidiPlayer::setVolume(int volume) {
 	_masterVolume = CLIP(volume, 0, 255);
-	_mutex.lock();
+
+	Common::StackLock lock(_mutex);
 	for (int i = 0; i < NUM_CHANNELS; ++i) {
 		if (_channelsTable[i]) {
 			_channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
 		}
 	}
-	_mutex.unlock();
 }
 
 int MidiPlayer::open() {
@@ -185,14 +183,14 @@ bool MidiPlayer::isOpen() const {
 
 void MidiPlayer::close() {
 	stop();
-	_mutex.lock();
+
+	Common::StackLock lock(_mutex);
 	_driver->setTimerCallback(NULL, NULL);
 	_driver->close();
 	delete _driver;
 	_driver = 0;
 	_parser->setMidiDriver(NULL);
 	delete _parser;
-	_mutex.unlock();
 }
 
 void MidiPlayer::send(uint32 b) {
diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp
index 0447178..e04527d 100644
--- a/engines/queen/music.cpp
+++ b/engines/queen/music.cpp
@@ -218,10 +218,9 @@ void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
 }
 
 void MidiMusic::onTimer() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	if (_isPlaying)
 		_parser->onTimer();
-	_mutex.unlock();
 }
 
 void MidiMusic::queueTuneList(int16 tuneList) {
@@ -319,11 +318,10 @@ void MidiMusic::playMusic() {
 
 	stopMusic();
 
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	_parser->loadMusic(musicPtr, size);
 	_parser->setTrack(0);
 	_isPlaying = true;
-	_mutex.unlock();
 
 	debug(8, "Playing song %d [queue position: %d]", songNum, _queuePos);
 	queueUpdatePos();
@@ -349,14 +347,13 @@ uint8 MidiMusic::randomQueuePos() {
 	if (!queueSize)
 		return 0;
 
-	return (uint8) _rnd.getRandomNumber(queueSize - 1) & 0xFF;
+	return (uint8)_rnd.getRandomNumber(queueSize - 1) & 0xFF;
 }
 
 void MidiMusic::stopMusic() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	_isPlaying = false;
 	_parser->unloadMusic();
-	_mutex.unlock();
 }
 
 uint32 MidiMusic::songOffset(uint16 songNum) const {
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index a028617..0ed99c1 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -303,7 +303,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
 			pSnd->hCurrentAud = Audio::SoundHandle();
 		} else {
 			// play MIDI track
-			_mutex.lock();
+			Common::StackLock lock(_mutex);
 			pSnd->soundType = Audio::Mixer::kMusicSoundType;
 			if (pSnd->pMidiParser == NULL) {
 				pSnd->pMidiParser = new MidiParser_SCI(_soundVersion, this);
@@ -334,7 +334,6 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
 			pSnd->loop = prevLoop;
 			pSnd->hold = prevHold;
 			pSnd->pMidiParser->mainThreadEnd();
-			_mutex.unlock();
 		}
 	}
 }
@@ -441,7 +440,7 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
 		}
 	} else {
 		if (pSnd->pMidiParser) {
-			_mutex.lock();
+			Common::StackLock lock(_mutex);
 			pSnd->pMidiParser->mainThreadBegin();
 			pSnd->pMidiParser->tryToOwnChannels();
 			if (pSnd->status != kSoundPaused)
@@ -468,7 +467,6 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
 			pSnd->loop = prevLoop;
 			pSnd->hold = prevHold;
 			pSnd->pMidiParser->mainThreadEnd();
-			_mutex.unlock();
 		}
 	}
 
@@ -484,7 +482,7 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
 		_pMixer->stopHandle(pSnd->hCurrentAud);
 
 	if (pSnd->pMidiParser) {
-		_mutex.lock();
+		Common::StackLock lock(_mutex);
 		pSnd->pMidiParser->mainThreadBegin();
 		// We shouldn't call stop in case it's paused, otherwise we would send
 		// allNotesOff() again
@@ -492,7 +490,6 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
 			pSnd->pMidiParser->stop();
 		freeChannels(pSnd);
 		pSnd->pMidiParser->mainThreadEnd();
-		_mutex.unlock();
 	}
 
 	pSnd->fadeStep = 0; // end fading, if fading was in progress
@@ -504,11 +501,10 @@ void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
 		// we simply ignore volume changes for samples, because sierra sci also
 		//  doesn't support volume for samples via kDoSound
 	} else if (pSnd->pMidiParser) {
-		_mutex.lock();
+		Common::StackLock lock(_mutex);
 		pSnd->pMidiParser->mainThreadBegin();
 		pSnd->pMidiParser->setVolume(volume);
 		pSnd->pMidiParser->mainThreadEnd();
-		_mutex.unlock();
 	}
 }
 
@@ -530,13 +526,12 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
 	pSnd->status = kSoundStopped;
 
 	if (pSnd->pMidiParser) {
-		_mutex.lock();
+		Common::StackLock lock(_mutex);
 		pSnd->pMidiParser->mainThreadBegin();
 		pSnd->pMidiParser->unloadMusic();
 		pSnd->pMidiParser->mainThreadEnd();
 		delete pSnd->pMidiParser;
 		pSnd->pMidiParser = NULL;
-		_mutex.unlock();
 	}
 
 	if (pSnd->pStreamAud) {
@@ -547,7 +542,7 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
 		pSnd->pLoopStream = 0;
 	}
 
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	uint sz = _playList.size(), i;
 	// Remove sound from playlist
 	for (i = 0; i < sz; i++) {
@@ -558,7 +553,6 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
 			break;
 		}
 	}
-	_mutex.unlock();
 }
 
 void SciMusic::soundPause(MusicEntry *pSnd) {
@@ -581,12 +575,11 @@ void SciMusic::soundPause(MusicEntry *pSnd) {
 		_pMixer->pauseHandle(pSnd->hCurrentAud, true);
 	} else {
 		if (pSnd->pMidiParser) {
-			_mutex.lock();
+			Common::StackLock lock(_mutex);
 			pSnd->pMidiParser->mainThreadBegin();
 			pSnd->pMidiParser->pause();
 			freeChannels(pSnd);
 			pSnd->pMidiParser->mainThreadEnd();
-			_mutex.unlock();
 		}
 	}
 }
diff --git a/engines/scumm/player_pce.cpp b/engines/scumm/player_pce.cpp
index 4236fb2..46d9767 100644
--- a/engines/scumm/player_pce.cpp
+++ b/engines/scumm/player_pce.cpp
@@ -515,7 +515,7 @@ int Player_PCE::readBuffer(int16 *buffer, const int numSamples) {
 	int sampleCopyCnt;
 	int samplesLeft = numSamples;
 
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 
 	while (true) {
 		// copy samples to output buffer
@@ -543,8 +543,6 @@ int Player_PCE::readBuffer(int16 *buffer, const int numSamples) {
 			_sampleBufferCnt * sizeof(int16));
 	}
 
-	_mutex.unlock();
-
 	return numSamples;
 }
 
diff --git a/engines/scumm/player_sid.cpp b/engines/scumm/player_sid.cpp
index 34654a6..0d5832a 100644
--- a/engines/scumm/player_sid.cpp
+++ b/engines/scumm/player_sid.cpp
@@ -1287,7 +1287,7 @@ uint8 *Player_SID::getResource(int resID) {
 int Player_SID::readBuffer(int16 *buffer, const int numSamples) {
 	int samplesLeft = numSamples;
 
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 
 	while (samplesLeft > 0) {
 		// update SID status after each frame
@@ -1301,8 +1301,6 @@ int Player_SID::readBuffer(int16 *buffer, const int numSamples) {
 		buffer += sampleCount;
 	}
 
-	_mutex.unlock();
-
 	return numSamples;
 }
 
@@ -1337,7 +1335,7 @@ void Player_SID::startSound(int nr) {
 	// prio 7 is never used in any sound file use this byte for auto-detection.
 	bool isMusic = (data[4] == 0x07);
 
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 
 	if (isMusic) {
 		initMusic(nr);
@@ -1345,29 +1343,25 @@ void Player_SID::startSound(int nr) {
 		stopSound_intern(nr);
 		initSound(nr);
 	}
-
-	_mutex.unlock();
 }
 
 void Player_SID::stopSound(int nr) {
 	if (nr == -1)
 		return;
 
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	stopSound_intern(nr);
-	_mutex.unlock();
 }
 
 void Player_SID::stopAllSounds() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	stopAllSounds_intern();
-	_mutex.unlock();
 }
 
 int Player_SID::getSoundStatus(int nr) const {
 	int result = 0;
 
-	//_mutex.lock();
+	//Common::StackLock lock(_mutex);
 
 	if (resID_song == nr && isMusicPlaying) {
 		result = 1;
@@ -1379,8 +1373,6 @@ int Player_SID::getSoundStatus(int nr) const {
 		}
 	}
 
-	//_mutex.unlock();
-
 	return result;
 }
 
diff --git a/engines/sky/music/musicbase.cpp b/engines/sky/music/musicbase.cpp
index 0d3cb65..e1044a9 100644
--- a/engines/sky/music/musicbase.cpp
+++ b/engines/sky/music/musicbase.cpp
@@ -44,7 +44,7 @@ MusicBase::~MusicBase() {
 }
 
 void MusicBase::loadSection(uint8 pSection) {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	if (_currentMusic)
 		stopMusicInternal();
 	free(_musicData);
@@ -58,7 +58,6 @@ void MusicBase::loadSection(uint8 pSection) {
 	_numberOfChannels = _currentMusic = 0;
 	setupPointers();
 	startDriver();
-	_mutex.unlock();
 }
 
 bool MusicBase::musicIsPlaying() {
@@ -69,9 +68,8 @@ bool MusicBase::musicIsPlaying() {
 }
 
 void MusicBase::stopMusic() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	stopMusicInternal();
-	_mutex.unlock();
 }
 
 void MusicBase::stopMusicInternal() {
@@ -113,7 +111,7 @@ void MusicBase::loadNewMusic() {
 }
 
 void MusicBase::pollMusic() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	uint8 newTempo;
 	if (_onNextPoll.musicToProcess != _currentMusic)
 		loadNewMusic();
@@ -127,7 +125,6 @@ void MusicBase::pollMusic() {
 			updateTempo();
 		}
 	}
-	_mutex.unlock();
 	_aktTime &= 0xFFFF;
 }
 
diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp
index c420fb3..c1270dd 100644
--- a/engines/touche/midi.cpp
+++ b/engines/touche/midi.cpp
@@ -48,32 +48,30 @@ void MidiPlayer::play(Common::ReadStream &stream, int size, bool loop) {
 	_midiData = (uint8 *)malloc(size);
 	if (_midiData) {
 		stream.read(_midiData, size);
-		_mutex.lock();
+
+		Common::StackLock lock(_mutex);
 		_parser->loadMusic(_midiData, size);
 		_parser->setTrack(0);
 		_isLooping = loop;
 		_isPlaying = true;
-		_mutex.unlock();
 	}
 }
 
 void MidiPlayer::stop() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	if (_isPlaying) {
 		_isPlaying = false;
 		_parser->unloadMusic();
 		free(_midiData);
 		_midiData = 0;
 	}
-	_mutex.unlock();
 }
 
 void MidiPlayer::updateTimer() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	if (_isPlaying) {
 		_parser->onTimer();
 	}
-	_mutex.unlock();
 }
 
 void MidiPlayer::adjustVolume(int diff) {
@@ -82,13 +80,12 @@ void MidiPlayer::adjustVolume(int diff) {
 
 void MidiPlayer::setVolume(int volume) {
 	_masterVolume = CLIP(volume, 0, 255);
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	for (int i = 0; i < NUM_CHANNELS; ++i) {
 		if (_channelsTable[i]) {
 			_channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
 		}
 	}
-	_mutex.unlock();
 }
 
 int MidiPlayer::open() {
@@ -116,14 +113,14 @@ bool MidiPlayer::isOpen() const {
 
 void MidiPlayer::close() {
 	stop();
-	_mutex.lock();
+
+	Common::StackLock lock(_mutex);
 	_driver->setTimerCallback(NULL, NULL);
 	_driver->close();
 	delete _driver;
 	_driver = 0;
 	_parser->setMidiDriver(NULL);
 	delete _parser;
-	_mutex.unlock();
 }
 
 void MidiPlayer::send(uint32 b) {


Commit: 2bc842dcee9552b302ac1acc927e6305ab6fad19
    https://github.com/scummvm/scummvm/commit/2bc842dcee9552b302ac1acc927e6305ab6fad19
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T07:25:46-07:00

Commit Message:
AGOS: Sanitize the mutex locking in MidiPlayer::startTrack

Changed paths:
    engines/agos/midi.cpp



diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index e80b89d..bbc0181 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -62,9 +62,8 @@ MidiPlayer::MidiPlayer() {
 }
 
 MidiPlayer::~MidiPlayer() {
-	_mutex.lock();
+	Common::StackLock lock(_mutex);
 	close();
-	_mutex.unlock();
 }
 
 int MidiPlayer::open() {
@@ -211,6 +210,8 @@ void MidiPlayer::onTimer(void *data) {
 }
 
 void MidiPlayer::startTrack(int track) {
+	Common::StackLock lock(_mutex);
+
 	if (track == _currentTrack)
 		return;
 
@@ -218,8 +219,6 @@ void MidiPlayer::startTrack(int track) {
 		if (track >= _music.num_songs)
 			return;
 
-		_mutex.lock();
-
 		if (_music.parser) {
 			_current = &_music;
 			delete _music.parser;
@@ -240,9 +239,7 @@ void MidiPlayer::startTrack(int track) {
 		_currentTrack = (byte)track;
 		_music.parser = parser; // That plugs the power cord into the wall
 	} else if (_music.parser) {
-		_mutex.lock();
 		if (!_music.parser->setTrack(track)) {
-			_mutex.unlock();
 			return;
 		}
 		_currentTrack = (byte)track;
@@ -250,8 +247,6 @@ void MidiPlayer::startTrack(int track) {
 		_music.parser->jumpToTick(0);
 		_current = 0;
 	}
-
-	_mutex.unlock();
 }
 
 void MidiPlayer::stop() {


Commit: a539be098d3b5598422e52a65457c68b43042e4a
    https://github.com/scummvm/scummvm/commit/a539be098d3b5598422e52a65457c68b43042e4a
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T07:25:47-07:00

Commit Message:
AUDIO: Update some comments, remove some obsolete ones

Changed paths:
    audio/mididrv.h



diff --git a/audio/mididrv.h b/audio/mididrv.h
index f635472..8323553 100644
--- a/audio/mididrv.h
+++ b/audio/mididrv.h
@@ -38,15 +38,6 @@ namespace Audio {
 namespace Common { class String; }
 
 /**
- * Music Driver Types, used to uniquely identify each music driver.
- *
- * The pseudo drivers are listed first, then all native drivers,
- * then all other MIDI drivers, and finally the non-MIDI drivers.
- *
- * @todo Rename MidiDriverType to MusicDriverType
- */
-
-/**
  * Music types that music drivers can implement and engines can rely on.
  */
 enum MusicType {
@@ -84,8 +75,8 @@ enum MusicType {
  */
 enum MidiDriverFlags {
 	MDT_NONE        = 0,
-	MDT_PCSPK       = 1 << 0,		// PC Speaker: Maps to MD_PCSPK and MD_PCJR
-	MDT_CMS         = 1 << 1,		// Creative Music System / Gameblaster: Maps to MD_CMS
+	MDT_PCSPK       = 1 << 0,		// PC Speaker: Maps to MT_PCSPK and MT_PCJR
+	MDT_CMS         = 1 << 1,		// Creative Music System / Gameblaster: Maps to MT_CMS
 	MDT_PCJR        = 1 << 2,		// Tandy/PC Junior driver
 	MDT_ADLIB       = 1 << 3,		// AdLib: Maps to MT_ADLIB
 	MDT_C64         = 1 << 4,
@@ -99,14 +90,6 @@ enum MidiDriverFlags {
 };
 
 /**
- * Abstract description of a MIDI driver. Used by the config file and command
- * line parsing code, and also to be able to give the user a list of available
- * drivers.
- *
- * @todo Rename MidiDriverType to MusicDriverType
- */
-
-/**
  * Abstract MIDI Driver Class
  *
  * @todo Rename MidiDriver to MusicDriver


Commit: c70c8864f131bfe42437b05d03f77ab198f59247
    https://github.com/scummvm/scummvm/commit/c70c8864f131bfe42437b05d03f77ab198f59247
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T07:25:47-07:00

Commit Message:
AUDIO: Introduce a new MidiDriver_BASE base class.

The actual MidiDriver derives from it. MidiDriver_BASE only
provides the minimal API necessary for transmitting MIDI data.
The idea is that this is all MidiParser needs, thus allowing
us to simplify the various MidiPlayer classes in our engines.

Changed paths:
    audio/mididrv.h
    audio/midiparser.h



diff --git a/audio/mididrv.h b/audio/mididrv.h
index 8323553..8d6f942 100644
--- a/audio/mididrv.h
+++ b/audio/mididrv.h
@@ -90,11 +90,53 @@ enum MidiDriverFlags {
 };
 
 /**
+ * TODO: Document this, give it a better name.
+ */
+class MidiDriver_BASE {
+public:
+	virtual ~MidiDriver_BASE() { }
+
+	/**
+	 * Output a packed midi command to the midi stream.
+	 * The 'lowest' byte (i.e. b & 0xFF) is the status
+	 * code, then come (if used) the first and second
+	 * opcode.
+	 */
+	virtual void send(uint32 b) = 0;
+
+	/**
+	 * Output a midi command to the midi stream. Convenience wrapper
+	 * around the usual 'packed' send method.
+	 *
+	 * Do NOT use this for sysEx transmission; instead, use the sysEx()
+	 * method below.
+	 */
+	void send(byte status, byte firstOp, byte secondOp) {
+		send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+	}
+
+	/**
+	 * Transmit a sysEx to the midi device.
+	 *
+	 * The given msg MUST NOT contain the usual SysEx frame, i.e.
+	 * do NOT include the leading 0xF0 and the trailing 0xF7.
+	 *
+	 * Furthermore, the maximal supported length of a SysEx
+	 * is 264 bytes. Passing longer buffers can lead to
+	 * undefined behavior (most likely, a crash).
+	 */
+	virtual void sysEx(const byte *msg, uint16 length) { }
+
+	// TODO: Document this.
+	virtual void metaEvent(byte type, byte *data, uint16 length) { }
+};
+
+/**
  * Abstract MIDI Driver Class
  *
  * @todo Rename MidiDriver to MusicDriver
  */
-class MidiDriver {
+class MidiDriver : public MidiDriver_BASE {
 public:
 	/**
 	 * The device handle.
@@ -173,25 +215,6 @@ public:
 	/** Close the midi driver. */
 	virtual void close() = 0;
 
-	/**
-	 * Output a packed midi command to the midi stream.
-	 * The 'lowest' byte (i.e. b & 0xFF) is the status
-	 * code, then come (if used) the first and second
-	 * opcode.
-	 */
-	virtual void send(uint32 b) = 0;
-
-	/**
-	 * Output a midi command to the midi stream. Convenience wrapper
-	 * around the usual 'packed' send method.
-	 *
-	 * Do NOT use this for sysEx transmission; instead, use the sysEx()
-	 * method below.
-	 */
-	void send(byte status, byte firstOp, byte secondOp) {
-		send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
-	}
-
 	/** Get or set a property. */
 	virtual uint32 property(int prop, uint32 param) { return 0; }
 
@@ -218,22 +241,8 @@ public:
 	 */
 	void sendGMReset();
 
-	/**
-	 * Transmit a sysEx to the midi device.
-	 *
-	 * The given msg MUST NOT contain the usual SysEx frame, i.e.
-	 * do NOT include the leading 0xF0 and the trailing 0xF7.
-	 *
-	 * Furthermore, the maximal supported length of a SysEx
-	 * is 264 bytes. Passing longer buffers can lead to
-	 * undefined behavior (most likely, a crash).
-	 */
-	virtual void sysEx(const byte *msg, uint16 length) { }
-
 	virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { }
 
-	virtual void metaEvent(byte type, byte *data, uint16 length) { }
-
 	// Timing functions - MidiDriver now operates timers
 	virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) = 0;
 
diff --git a/audio/midiparser.h b/audio/midiparser.h
index 0b18a19..eeeee98 100644
--- a/audio/midiparser.h
+++ b/audio/midiparser.h
@@ -32,7 +32,7 @@
 #include "common/endian.h"
 
 class MidiParser;
-class MidiDriver;
+class MidiDriver_BASE;
 
 
 
@@ -273,7 +273,7 @@ protected:
 	                                ///< Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.
 	byte      _hanging_notes_count; ///< Count of hanging notes, used to optimize expiration.
 
-	MidiDriver *_driver;    ///< The device to which all events will be transmitted.
+	MidiDriver_BASE *_driver;    ///< The device to which all events will be transmitted.
 	uint32 _timer_rate;     ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
 	uint32 _ppqn;           ///< Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
 	uint32 _tempo;          ///< Microseconds per quarter note.
@@ -380,7 +380,7 @@ public:
 	virtual void unloadMusic();
 	virtual void property(int prop, int value);
 
-	void setMidiDriver(MidiDriver *driver) { _driver = driver; }
+	void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
 	void setTimerRate(uint32 rate) { _timer_rate = rate; }
 	void setTempo(uint32 tempo);
 	void onTimer();


Commit: 29847ea42da3e597d3496972c80ce49bea76da20
    https://github.com/scummvm/scummvm/commit/29847ea42da3e597d3496972c80ce49bea76da20
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T07:25:47-07:00

Commit Message:
AUDIO: Change several fake MidiDrivers to MidiDriver_BASE subclasses

Many engines follow the advice in audio/midiparser.h and create a
"pseudo-MidiDriver" subclass. But MidiParser really only needs a tiny
subset of the MidiDriver capabilities, namely those found in
MidiDriver_BASE. So we try to subclass from that whenever possible; this
allows us to remove many stub methods, and enables further future
simplifications.

Changed paths:
    engines/agi/sound_midi.cpp
    engines/agi/sound_midi.h
    engines/agos/agos.cpp
    engines/agos/midi.cpp
    engines/agos/midi.h
    engines/draci/music.cpp
    engines/draci/music.h
    engines/groovie/music.cpp
    engines/groovie/music.h
    engines/hugo/sound.cpp
    engines/hugo/sound.h
    engines/kyra/sound_intern.h
    engines/kyra/sound_midi.cpp
    engines/lure/sound.cpp
    engines/lure/sound.h
    engines/m4/midi.cpp
    engines/m4/midi.h
    engines/made/music.cpp
    engines/made/music.h
    engines/parallaction/sound_br.cpp
    engines/parallaction/sound_ns.cpp
    engines/queen/music.h
    engines/saga/music.cpp
    engines/saga/music.h
    engines/sci/sound/drivers/cms.cpp
    engines/sci/sound/drivers/fb01.cpp
    engines/sci/sound/drivers/midi.cpp
    engines/sci/sound/drivers/mididriver.h
    engines/scumm/imuse/imuse_internal.h
    engines/scumm/imuse/imuse_player.cpp
    engines/testbed/midi.cpp
    engines/tinsel/music.cpp
    engines/tinsel/music.h
    engines/touche/midi.cpp
    engines/touche/midi.h



diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp
index 050c0d6..877f632 100644
--- a/engines/agi/sound_midi.cpp
+++ b/engines/agi/sound_midi.cpp
@@ -72,7 +72,7 @@ MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A
 }
 
 SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _parser(0), _isPlaying(false), _passThrough(false), _isGM(false) {
-	DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
+	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
 	_driver = MidiDriver::createMidi(dev);
 
 	if (ConfMan.getBool("native_mt32") || MidiDriver::getMusicType(dev) == MT_MT32) {
@@ -138,10 +138,6 @@ int SoundGenMIDI::open() {
 	return 0;
 }
 
-bool SoundGenMIDI::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void SoundGenMIDI::close() {
 	stop();
 	if (_driver)
@@ -221,7 +217,7 @@ void SoundGenMIDI::play(int resnum) {
 		MidiParser *parser = _smfParser;
 		parser->setTrack(0);
 		parser->setMidiDriver(this);
-		parser->setTimerRate(getBaseTempo());
+		parser->setTimerRate(_driver->getBaseTempo());
 		parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
 
 		_parser = parser;
diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h
index b7355a0..2e1bfe2 100644
--- a/engines/agi/sound_midi.h
+++ b/engines/agi/sound_midi.h
@@ -46,7 +46,7 @@ protected:
 	uint16 _type; ///< Sound resource type
 };
 
-class SoundGenMIDI : public SoundGen, public MidiDriver {
+class SoundGenMIDI : public SoundGen, public MidiDriver_BASE {
 public:
 	SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer);
 	~SoundGenMIDI();
@@ -72,27 +72,19 @@ public:
 
 	// MidiDriver interface implementation
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 
 	void metaEvent(byte type, byte *data, uint16 length);
 
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
-	// Channel allocation functions
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
-
-	MidiParser *_parser;
-	Common::Mutex _mutex;
-
 private:
 
 	static void onTimer(void *data);
 	void setChannelVolume(int channel);
 
+	MidiParser *_parser;
+	Common::Mutex _mutex;
+
 	MidiChannel *_channel[16];
 	MidiDriver *_driver;
 	MidiParser *_smfParser;
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index 574031d..7b6d4cf 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -571,7 +571,7 @@ Common::Error AGOSEngine::init() {
 
 		int ret = _midi.open();
 		if (ret)
-			warning("MIDI Player init failed: \"%s\"", _midi.getErrorName (ret));
+			warning("MIDI Player init failed: \"%s\"", MidiDriver::getErrorName (ret));
 
 		_midi.setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
 
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index bbc0181..d76aa42 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -84,10 +84,6 @@ int MidiPlayer::open() {
 	return 0;
 }
 
-bool MidiPlayer::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MidiPlayer::close() {
 	stop();
 //	_system->lockMutex(_mutex);
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index c27c5a7..01456d7 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -55,7 +55,7 @@ struct MusicInfo {
 	}
 };
 
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
 protected:
 	Common::Mutex _mutex;
 	MidiDriver *_driver;
@@ -115,20 +115,11 @@ public:
 public:
 	// MidiDriver interface implementation
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 
 	void metaEvent(byte type, byte *data, uint16 length);
 	void setPassThrough(bool b)		{ _passThrough = b; }
-
-	// Timing functions - MidiDriver now operates timers
-	void setTimerCallback(void *timer_param, void (*timer_proc) (void *)) { }
-	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
-	// Channel allocation functions
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
 };
 
 } // End of namespace AGOS
diff --git a/engines/draci/music.cpp b/engines/draci/music.cpp
index cc1cd6d..b56e105 100644
--- a/engines/draci/music.cpp
+++ b/engines/draci/music.cpp
@@ -97,10 +97,6 @@ int MusicPlayer::open() {
 	return 0;
 }
 
-bool MusicPlayer::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MusicPlayer::close() {
 	stop();
 	if (_driver) {
@@ -198,7 +194,7 @@ void MusicPlayer::playSMF(int track, bool loop) {
 		MidiParser *parser = _smfParser;
 		parser->setTrack(0);
 		parser->setMidiDriver(this);
-		parser->setTimerRate(getBaseTempo());
+		parser->setTimerRate(_driver->getBaseTempo());
 		parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
 
 		_parser = parser;
diff --git a/engines/draci/music.h b/engines/draci/music.h
index 0d15fda..80d2501 100644
--- a/engines/draci/music.h
+++ b/engines/draci/music.h
@@ -36,7 +36,7 @@ namespace Draci {
 
 // Taken from MADE, which took it from SAGA.
 
-class MusicPlayer : public MidiDriver {
+class MusicPlayer : public MidiDriver_BASE {
 public:
 	MusicPlayer(MidiDriver *driver, const char *pathMask);
 	~MusicPlayer();
@@ -61,19 +61,11 @@ public:
 
 	// MidiDriver interface implementation
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 
 	void metaEvent(byte type, byte *data, uint16 length);
 
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
-	//Channel allocation functions
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
-
 	MidiParser *_parser;
 	Common::Mutex _mutex;
 
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 7651576..1921d65 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -264,12 +264,6 @@ int MusicPlayerMidi::open() {
 	return 0;
 }
 
-bool MusicPlayerMidi::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
-void MusicPlayerMidi::close() {}
-
 void MusicPlayerMidi::send(uint32 b) {
 	if ((b & 0xFFF0) == 0x07B0) { // Volume change
 		// Save the specific channel volume
@@ -298,32 +292,6 @@ void MusicPlayerMidi::metaEvent(byte type, byte *data, uint16 length) {
 	}
 }
 
-void MusicPlayerMidi::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
-	if (_driver)
-		_driver->setTimerCallback(timer_param, timer_proc);
-}
-
-uint32 MusicPlayerMidi::getBaseTempo() {
-	if (_driver)
-		return _driver->getBaseTempo();
-	else
-		return 0;
-}
-
-MidiChannel *MusicPlayerMidi::allocateChannel() {
-	if (_driver)
-		return _driver->allocateChannel();
-	else
-		return 0;
-}
-
-MidiChannel *MusicPlayerMidi::getPercussionChannel() {
-	if (_driver)
-		return _driver->getPercussionChannel();
-	else
-		return 0;
-}
-
 void MusicPlayerMidi::updateChanVolume(byte channel) {
 	// Generate a MIDI Control change message for the volume
 	uint32 b = 0x7B0;
@@ -406,7 +374,7 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
 
 	// Create the driver
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
-	_driver = createMidi(dev);
+	_driver = MidiDriver::createMidi(dev);
 	this->open();
 
 	// Set the parser's driver
@@ -706,7 +674,7 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) {
 
 	// Create the driver
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
-	_driver = createMidi(dev);
+	_driver = MidiDriver::createMidi(dev);
 	this->open();
 
 	// Set the parser's driver
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index e45e130..870fd10 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -88,21 +88,15 @@ protected:
 	virtual void unload();
 };
 
-class MusicPlayerMidi : public MusicPlayer, public MidiDriver {
+class MusicPlayerMidi : public MusicPlayer, public MidiDriver_BASE {
 public:
 	MusicPlayerMidi(GroovieEngine *vm);
 	~MusicPlayerMidi();
 
 	// MidiDriver interface
 	virtual int open();
-	virtual bool isOpen() const;
-	virtual void close();
 	virtual void send(uint32 b);
 	virtual void metaEvent(byte type, byte *data, uint16 length);
-	virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
-	virtual uint32 getBaseTempo();
-	virtual MidiChannel *allocateChannel();
-	virtual MidiChannel *getPercussionChannel();
 
 private:
 	// Channel volumes
diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index 33627fb..daa467f 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -75,18 +75,6 @@ void MidiPlayer::setLooping(bool loop) {
 	_isLooping = loop;
 }
 
-MidiChannel *MidiPlayer::allocateChannel() {
-	return 0;
-}
-
-MidiChannel *MidiPlayer::getPercussionChannel() {
-	return 0;
-}
-
-uint32 MidiPlayer::getBaseTempo() {
-	return _driver ? _driver->getBaseTempo() : 0;
-}
-
 void MidiPlayer::play(uint8 *stream, uint16 size) {
 	debugC(3, kDebugMusic, "MidiPlayer::play");
 	if (!stream) {
@@ -191,10 +179,6 @@ int MidiPlayer::open() {
 	return 0;
 }
 
-bool MidiPlayer::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MidiPlayer::close() {
 	stop();
 
diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h
index e5e9d94..c8f4ae5 100644
--- a/engines/hugo/sound.h
+++ b/engines/hugo/sound.h
@@ -40,7 +40,7 @@
 
 namespace Hugo {
 
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
 public:
 	MidiPlayer(MidiDriver *driver);
 	~MidiPlayer();
@@ -60,15 +60,9 @@ public:
 
 	// MidiDriver interface
 	int open();
-	bool isOpen() const;
-
-	MidiChannel *allocateChannel();
-	MidiChannel *getPercussionChannel();
-
 	void close();
 	void metaEvent(byte type, byte *data, uint16 length);
 	void send(uint32 b);
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
 
 	uint32 getBaseTempo();
 
diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h
index 7b33fc2..354f573 100644
--- a/engines/kyra/sound_intern.h
+++ b/engines/kyra/sound_intern.h
@@ -219,12 +219,12 @@ public:
 	~MidiDriver_PCSpeaker();
 
 	// MidiDriver interface
-	void close() {}
+	virtual void close() {}
 
-	void send(uint32 data);
+	virtual void send(uint32 data);
 
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
+	virtual MidiChannel *allocateChannel() { return 0; }
+	virtual MidiChannel *getPercussionChannel() { return 0; }
 
 	// MidiDriver_Emulated interface
 	void generateSamples(int16 *buffer, int numSamples);
diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp
index 903375c..02ba735 100644
--- a/engines/kyra/sound_midi.cpp
+++ b/engines/kyra/sound_midi.cpp
@@ -33,7 +33,7 @@
 
 namespace Kyra {
 
-class MidiOutput : public MidiDriver {
+class MidiOutput : public MidiDriver_BASE {
 public:
 	MidiOutput(OSystem *system, MidiDriver *output, bool isMT32, bool defaultMT32);
 	~MidiOutput();
@@ -46,20 +46,16 @@ public:
 
 	void setSoundSource(int source) { _curSource = source; }
 
-	void send(uint32 b);
-	void sysEx(const byte *msg, uint16 length);
-	void metaEvent(byte type, byte *data, uint16 length);
+	// MidiDriver_BASE interface
+	virtual void send(uint32 b);
+	virtual void sysEx(const byte *msg, uint16 length);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
+	// TODO: Get rid of the following two methods
 	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _output->setTimerCallback(timerParam, timerProc); }
 	uint32 getBaseTempo() { return _output->getBaseTempo(); }
 
-	// DUMMY
-	int open() { return 0; }
-	bool isOpen() const { return true; }
-	void close() {}
 
-	MidiChannel *allocateChannel()		{ return 0; }
-	MidiChannel *getPercussionChannel()	{ return 0; }
 private:
 	void sendIntern(const byte event, const byte channel, byte param1, const byte param2);
 	void sendSysEx(const byte p1, const byte p2, const byte p3, const byte *buffer, const int size);
@@ -266,7 +262,7 @@ void MidiOutput::sendIntern(const byte event, const byte channel, byte param1, c
 	if (event == 0xC0) {
 		// MT32 -> GM conversion
 		if (!_isMT32 && _defaultMT32)
-			param1 = _mt32ToGm[param1];
+			param1 = MidiDriver::_mt32ToGm[param1];
 	}
 
 	_output->send(event | channel, param1, param2);
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 482527d..5f954eb 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -694,10 +694,6 @@ int MidiMusic::open() {
 	return 0;
 }
 
-bool MidiMusic::isOpen() const {
-	return _driver != 0;
-}
-
 void MidiMusic::close() {
 }
 
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index 454bff2..f4ddb8d 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -46,7 +46,7 @@ struct ChannelEntry {
 	uint8 volume;
 };
 
-class MidiMusic: public MidiDriver {
+class MidiMusic: public MidiDriver_BASE {
 private:
 	uint8 _soundNumber;
 	uint8 _channelNumber;
@@ -86,20 +86,12 @@ public:
 
 	//MidiDriver interface implementation
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 	void onTimer();
 
 	void metaEvent(byte type, byte *data, uint16 length);
 
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
-	//Channel allocation functions
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
-
 	uint8 channelNumber() { return _channelNumber; }
 	uint8 soundNumber() { return _soundNumber; }
 	bool isPlaying() { return _isPlaying; }
diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp
index 3a6475d..36f7f29 100644
--- a/engines/m4/midi.cpp
+++ b/engines/m4/midi.cpp
@@ -33,11 +33,12 @@
 namespace M4 {
 
 MidiPlayer::MidiPlayer(MadsM4Engine *vm, MidiDriver *driver) : _vm(vm), _midiData(NULL), _driver(driver), _isPlaying(false), _passThrough(false), _isGM(false) {
+	assert(_driver);
 	memset(_channel, 0, sizeof(_channel));
 	_masterVolume = 0;
 	_parser = MidiParser::createParser_SMF();
 	_parser->setMidiDriver(this);
-	_parser->setTimerRate(getBaseTempo());
+	_parser->setTimerRate(_driver->getBaseTempo());
 	open();
 }
 
@@ -83,10 +84,6 @@ int MidiPlayer::open() {
 	return 0;
 }
 
-bool MidiPlayer::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MidiPlayer::close() {
 	stopMusic();
 	if (_driver) {
diff --git a/engines/m4/midi.h b/engines/m4/midi.h
index a631cec..46dc5ef 100644
--- a/engines/m4/midi.h
+++ b/engines/m4/midi.h
@@ -34,7 +34,7 @@
 
 namespace M4 {
 
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
 public:
 	MidiPlayer(MadsM4Engine *vm, MidiDriver *driver);
 	~MidiPlayer();
@@ -54,19 +54,11 @@ public:
 
 	//MidiDriver interface implementation
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 
 	void metaEvent(byte type, byte *data, uint16 length);
 
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo()	{ return _driver ? _driver->getBaseTempo() : 0; }
-
-	//Channel allocation functions
-	MidiChannel *allocateChannel()		{ return 0; }
-	MidiChannel *getPercussionChannel()	{ return 0; }
-
 protected:
 	static void onTimer(void *data);
 
diff --git a/engines/made/music.cpp b/engines/made/music.cpp
index 5ace997..acb37bc 100644
--- a/engines/made/music.cpp
+++ b/engines/made/music.cpp
@@ -89,10 +89,6 @@ int MusicPlayer::open() {
 	return 0;
 }
 
-bool MusicPlayer::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MusicPlayer::close() {
 	stop();
 	if (_driver) {
@@ -169,7 +165,7 @@ void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) {
 		MidiParser *parser = _xmidiParser;
 		parser->setTrack(0);
 		parser->setMidiDriver(this);
-		parser->setTimerRate(getBaseTempo());
+		parser->setTimerRate(_driver->getBaseTempo());
 		parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
 		parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
 
@@ -196,7 +192,7 @@ void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) {
 		MidiParser *parser = _smfParser;
 		parser->setTrack(0);
 		parser->setMidiDriver(this);
-		parser->setTimerRate(getBaseTempo());
+		parser->setTimerRate(_driver->getBaseTempo());
 		parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
 
 		_parser = parser;
diff --git a/engines/made/music.h b/engines/made/music.h
index 024588e..6bd4da4 100644
--- a/engines/made/music.h
+++ b/engines/made/music.h
@@ -41,7 +41,7 @@ enum MusicFlags {
 	MUSIC_LOOP = 1
 };
 
-class MusicPlayer : public MidiDriver {
+class MusicPlayer : public MidiDriver_BASE {
 public:
 	MusicPlayer(MidiDriver *driver);
 	~MusicPlayer();
@@ -66,19 +66,11 @@ public:
 
 	//MidiDriver interface implementation
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 
 	void metaEvent(byte type, byte *data, uint16 length);
 
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo()	{ return _driver ? _driver->getBaseTempo() : 0; }
-
-	//Channel allocation functions
-	MidiChannel *allocateChannel()		{ return 0; }
-	MidiChannel *getPercussionChannel()	{ return 0; }
-
 	MidiParser *_parser;
 	Common::Mutex _mutex;
 
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index 80bd957..b74a584 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -201,7 +201,7 @@ MidiParser *createParser_MSC() {
 }
 
 
-class MidiPlayer_MSC : public MidiDriver {
+class MidiPlayer_MSC : public MidiDriver_BASE {
 public:
 
 	enum {
@@ -222,14 +222,9 @@ public:
 
 	// MidiDriver interface
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 	void metaEvent(byte type, byte *data, uint16 length);
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
 
 private:
 
@@ -342,10 +337,6 @@ int MidiPlayer_MSC::open() {
 	return ret;
 }
 
-bool MidiPlayer_MSC::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MidiPlayer_MSC::close() {
 	stop();
 
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index aeb934f..6d80b5d 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -38,7 +38,7 @@
 
 namespace Parallaction {
 
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
 public:
 
 	enum {
@@ -59,14 +59,9 @@ public:
 
 	// MidiDriver interface
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 	void metaEvent(byte type, byte *data, uint16 length);
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
 
 private:
 
@@ -177,10 +172,6 @@ int MidiPlayer::open() {
 	return ret;
 }
 
-bool MidiPlayer::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MidiPlayer::close() {
 	stop();
 
diff --git a/engines/queen/music.h b/engines/queen/music.h
index 50f7b3d..898abb4 100644
--- a/engines/queen/music.h
+++ b/engines/queen/music.h
@@ -39,7 +39,7 @@ struct TuneData;
 
 class QueenEngine;
 
-class MidiMusic : public MidiDriver {
+class MidiMusic : public MidiDriver_BASE {
 public:
 	MidiMusic(QueenEngine *vm);
 	~MidiMusic();
@@ -57,20 +57,9 @@ public:
 	void toggleVChange();
 
 	//MidiDriver interface implementation
-	int open() { return 0; }
-	bool isOpen() const { return true; }
-	void close() {}
 	void send(uint32 b);
-
 	void metaEvent(byte type, byte *data, uint16 length);
 
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo()	{ return _driver ? _driver->getBaseTempo() : 0; }
-
-	//Channel allocation functions
-	MidiChannel *allocateChannel()		{ return 0; }
-	MidiChannel *getPercussionChannel()	{ return 0; }
-
 protected:
 
 	enum {
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 3e1f3e3..b683505 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -76,10 +76,6 @@ int MusicDriver::open() {
 	return 0;
 }
 
-bool MusicDriver::isOpen() const {
-	return _driver->isOpen();
-}
-
 void MusicDriver::setVolume(int volume) {
 	volume = CLIP(volume, 0, 255);
 
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 22d957e..0b7d21d 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -44,7 +44,7 @@ enum MusicFlags {
 	MUSIC_DEFAULT = 0xffff
 };
 
-class MusicDriver : public MidiDriver {
+class MusicDriver : public MidiDriver_BASE {
 public:
 	MusicDriver();
 	~MusicDriver();
@@ -67,16 +67,10 @@ public:
 	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _driver->setTimerCallback(timerParam, timerProc); }
 	uint32 getBaseTempo()	{ return _driver->getBaseTempo(); }
 
-	//Channel allocation functions
-	MidiChannel *allocateChannel()		{ return 0; }
-	MidiChannel *getPercussionChannel()	{ return 0; }
-
 	Common::Mutex _mutex;
 
 protected:
 
-	static void onTimer(void *data);
-
 	MidiChannel *_channel[16];
 	MidiDriver *_driver;
 	MusicType _driverType;
diff --git a/engines/sci/sound/drivers/cms.cpp b/engines/sci/sound/drivers/cms.cpp
index ff38e1c..051fa7f 100644
--- a/engines/sci/sound/drivers/cms.cpp
+++ b/engines/sci/sound/drivers/cms.cpp
@@ -785,7 +785,7 @@ public:
 
 	int open(ResourceManager *resMan) {
 		if (_driver)
-			return MERR_ALREADY_OPEN;
+			return MidiDriver::MERR_ALREADY_OPEN;
 
 		_driver = new MidiDriver_CMS(g_system->getMixer(), resMan);
 		int driverRetVal = _driver->open();
diff --git a/engines/sci/sound/drivers/fb01.cpp b/engines/sci/sound/drivers/fb01.cpp
index ce48b7f..971c2ff 100644
--- a/engines/sci/sound/drivers/fb01.cpp
+++ b/engines/sci/sound/drivers/fb01.cpp
@@ -129,7 +129,7 @@ private:
 
 MidiPlayer_Fb01::MidiPlayer_Fb01(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _timerParam(NULL), _timerProc(NULL) {
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI);
-	_driver = createMidi(dev);
+	_driver = MidiDriver::createMidi(dev);
 
 	_sysExBuf[0] = 0x43;
 	_sysExBuf[1] = 0x75;
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index d166559..381f2aa 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -132,7 +132,7 @@ private:
 
 MidiPlayer_Midi::MidiPlayer_Midi(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _isMt32(false), _hasReverb(false), _useMT32Track(true) {
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI);
-	_driver = createMidi(dev);
+	_driver = MidiDriver::createMidi(dev);
 
 	if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32"))
 		_isMt32 = true;
diff --git a/engines/sci/sound/drivers/mididriver.h b/engines/sci/sound/drivers/mididriver.h
index 5cecebd..2038725 100644
--- a/engines/sci/sound/drivers/mididriver.h
+++ b/engines/sci/sound/drivers/mididriver.h
@@ -76,7 +76,7 @@ enum {
 
 #define SCI_MIDI_CONTROLLER(status) ((status & 0xF0) == 0xB0)
 
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
 protected:
 	MidiDriver *_driver;
 	int8 _reverb;
@@ -89,13 +89,10 @@ public:
 		return open(resMan);
 	}
 	virtual int open(ResourceManager *resMan) { return _driver->open(); }
-	bool isOpen() const { return _driver->isOpen(); }
 	virtual void close() { _driver->close(); }
 	virtual void send(uint32 b) { _driver->send(b); }
-	uint32 getBaseTempo() { return _driver->getBaseTempo(); }
+	virtual uint32 getBaseTempo() { return _driver->getBaseTempo(); }
 	virtual bool hasRhythmChannel() const = 0;
-	MidiChannel *allocateChannel() { return _driver->allocateChannel(); }
-	MidiChannel *getPercussionChannel() { return _driver->getPercussionChannel(); }
 	virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { _driver->setTimerCallback(timer_param, timer_proc); }
 
 	virtual byte getPlayId() const = 0;
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index d1153a0..7d46650 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -155,7 +155,7 @@ struct CommandQueue {
 //
 //////////////////////////////////////////////////
 
-class Player : public MidiDriver {
+class Player : public MidiDriver_BASE {
 /*
  * External SysEx handler functions shall each be defined in
  * a separate file. This header file shall be included at the
@@ -282,17 +282,9 @@ public:
 
 public:
 	// MidiDriver interface
-	int open() { return 0; }
-	bool isOpen() const { return true; }
-	void close() { }
 	void send(uint32 b);
-	const char *getErrorName(int error_code) { return "Unknown"; }
 	void sysEx(const byte *msg, uint16 length);
 	void metaEvent(byte type, byte *data, uint16 length);
-	void setTimerCallback(void *timer_param, void(*timer_proc)(void *)) { }
-	uint32 getBaseTempo();
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
 };
 
 
diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp
index 9958a93..4d185d9 100644
--- a/engines/scumm/imuse/imuse_player.cpp
+++ b/engines/scumm/imuse/imuse_player.cpp
@@ -986,10 +986,6 @@ void Player::fixAfterLoad() {
 	}
 }
 
-uint32 Player::getBaseTempo() {
-	return (_midi ? _midi->getBaseTempo() : 0);
-}
-
 void Player::metaEvent(byte type, byte *msg, uint16 len) {
 	if (type == 0x2F)
 		clear();
diff --git a/engines/testbed/midi.cpp b/engines/testbed/midi.cpp
index 673f5d8..7ec24aa 100644
--- a/engines/testbed/midi.cpp
+++ b/engines/testbed/midi.cpp
@@ -96,7 +96,7 @@ TestExitStatus MidiTests::playMidiMusic() {
 	int errCode = driver->open();
 
 	if (errCode) {
-		Common::String errMsg = driver->getErrorName(errCode);
+		Common::String errMsg = MidiDriver::getErrorName(errCode);
 		Testsuite::writeOnScreen(errMsg, Common::Point(0, 100));
 		Testsuite::logPrintf("Error! %s", errMsg.c_str());
 		return kTestFailed;
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index fb0f6b9..3e0d87b 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -432,10 +432,6 @@ int MidiMusicPlayer::open() {
 	return 0;
 }
 
-bool MidiMusicPlayer::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MidiMusicPlayer::close() {
 	stop();
 	if (_driver) {
diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h
index 8f5acc5..a75f2b8 100644
--- a/engines/tinsel/music.h
+++ b/engines/tinsel/music.h
@@ -60,7 +60,7 @@ SCNHANDLE GetTrackOffset(int trackNumber);
 
 void dumpMusic();
 
-class MidiMusicPlayer : public MidiDriver {
+class MidiMusicPlayer : public MidiDriver_BASE {
 public:
 	MidiMusicPlayer(MidiDriver *driver);
 	~MidiMusicPlayer();
@@ -80,23 +80,16 @@ public:
 
 	//MidiDriver interface implementation
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 
 	void metaEvent(byte type, byte *data, uint16 length);
 
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-
 	// The original sets the "sequence timing" to 109 Hz, whatever that
 	// means. The default is 120.
 
 	uint32 getBaseTempo()	{ return _driver ? (109 * _driver->getBaseTempo()) / 120 : 0; }
 
-	//Channel allocation functions
-	MidiChannel *allocateChannel()		{ return 0; }
-	MidiChannel *getPercussionChannel()	{ return 0; }
-
 protected:
 
 	static void onTimer(void *data);
diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp
index c1270dd..c6c7a60 100644
--- a/engines/touche/midi.cpp
+++ b/engines/touche/midi.cpp
@@ -107,10 +107,6 @@ int MidiPlayer::open() {
 	return ret;
 }
 
-bool MidiPlayer::isOpen() const {
-	return _driver && _driver->isOpen();
-}
-
 void MidiPlayer::close() {
 	stop();
 
diff --git a/engines/touche/midi.h b/engines/touche/midi.h
index 75f3326..a750f12 100644
--- a/engines/touche/midi.h
+++ b/engines/touche/midi.h
@@ -39,7 +39,7 @@ namespace Common {
 
 namespace Touche {
 
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
 public:
 
 	enum {
@@ -59,14 +59,9 @@ public:
 
 	// MidiDriver interface
 	int open();
-	bool isOpen() const;
 	void close();
 	void send(uint32 b);
 	void metaEvent(byte type, byte *data, uint16 length);
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
 
 private:
 


Commit: e70fd59b3505619cccb6f3280a4cf0fb57aefa97
    https://github.com/scummvm/scummvm/commit/e70fd59b3505619cccb6f3280a4cf0fb57aefa97
Author: Max Horn (max at quendi.de)
Date: 2011-03-23T08:49:41-07:00

Commit Message:
ENGINES: Further simplify pseudo MidiDrivers; fix some regressions

The regression affected AGOS and maybe some others; specifically,
the real MidiDriver would have been deleted twice -- I previously
missed that the Engine instances takes care of freeing the real
MidiDriver, not the MidiPlayer wrapping it.

This commit should clarify the ownership of the real MidiDriver for
most pseudo MidiDrivers.

Changed paths:
    engines/agi/sound_midi.cpp
    engines/agi/sound_midi.h
    engines/agos/agos.cpp
    engines/agos/agos.h
    engines/agos/midi.cpp
    engines/agos/midi.h
    engines/draci/draci.cpp
    engines/draci/draci.h
    engines/draci/music.cpp
    engines/draci/music.h
    engines/groovie/music.cpp
    engines/groovie/music.h
    engines/hugo/sound.cpp
    engines/hugo/sound.h
    engines/lure/sound.cpp
    engines/lure/sound.h
    engines/m4/midi.cpp
    engines/m4/midi.h
    engines/made/made.cpp
    engines/made/music.cpp
    engines/made/music.h
    engines/parallaction/sound_br.cpp
    engines/parallaction/sound_ns.cpp
    engines/queen/music.h
    engines/saga/music.cpp
    engines/saga/music.h
    engines/tinsel/music.cpp
    engines/tinsel/music.h
    engines/tinsel/tinsel.cpp
    engines/touche/midi.cpp
    engines/touche/midi.h



diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp
index 877f632..fe3d97b 100644
--- a/engines/agi/sound_midi.cpp
+++ b/engines/agi/sound_midi.cpp
@@ -74,6 +74,7 @@ MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A
 SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _parser(0), _isPlaying(false), _passThrough(false), _isGM(false) {
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
 	_driver = MidiDriver::createMidi(dev);
+	assert(_driver);
 
 	if (ConfMan.getBool("native_mt32") || MidiDriver::getMusicType(dev) == MT_MT32) {
 		_nativeMT32 = true;
@@ -85,7 +86,17 @@ SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, p
 	memset(_channel, 0, sizeof(_channel));
 	memset(_channelVolume, 127, sizeof(_channelVolume));
 	_masterVolume = 0;
-	this->open();
+
+	int ret = _driver->open();
+	if (ret == 0) {
+		if (_nativeMT32)
+			_driver->sendMT32Reset();
+		else
+			_driver->sendGMReset();
+
+		_driver->setTimerCallback(this, &onTimer);
+	}
+
 	_smfParser = MidiParser::createParser_SMF();
 	_midiMusicData = NULL;
 }
@@ -93,7 +104,11 @@ SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, p
 SoundGenMIDI::~SoundGenMIDI() {
 	_driver->setTimerCallback(NULL, NULL);
 	stop();
-	this->close();
+	if (_driver) {
+		_driver->close();
+		delete _driver;
+		_driver = 0;
+	}
 	_smfParser->setMidiDriver(NULL);
 	delete _smfParser;
 	delete[] _midiMusicData;
@@ -119,32 +134,6 @@ void SoundGenMIDI::setVolume(int volume) {
 	}
 }
 
-int SoundGenMIDI::open() {
-	// Don't ever call open without first setting the output driver!
-	if (!_driver)
-		return 255;
-
-	int ret = _driver->open();
-	if (ret)
-		return ret;
-
-	_driver->setTimerCallback(this, &onTimer);
-
-	if (_nativeMT32)
-		_driver->sendMT32Reset();
-	else
-		_driver->sendGMReset();
-
-	return 0;
-}
-
-void SoundGenMIDI::close() {
-	stop();
-	if (_driver)
-		_driver->close();
-	_driver = 0;
-}
-
 void SoundGenMIDI::send(uint32 b) {
 	if (_passThrough) {
 		_driver->send(b);
diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h
index 2e1bfe2..dc6609c 100644
--- a/engines/agi/sound_midi.h
+++ b/engines/agi/sound_midi.h
@@ -70,12 +70,9 @@ public:
 
 	void setGM(bool isGM) { _isGM = isGM; }
 
-	// MidiDriver interface implementation
-	int open();
-	void close();
-	void send(uint32 b);
-
-	void metaEvent(byte type, byte *data, uint16 length);
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 private:
 
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index 7b6d4cf..498c7e4 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -470,7 +470,6 @@ AGOSEngine::AGOSEngine(OSystem *syst)
 	_planarBuf = 0;
 
 	_midiEnabled = false;
-	_nativeMT32 = false;
 
 	_vgaTickCounter = 0;
 
@@ -555,30 +554,13 @@ Common::Error AGOSEngine::init() {
 		((getFeatures() & GF_TALKIE) && getPlatform() == Common::kPlatformAcorn) ||
 		(getPlatform() == Common::kPlatformPC)) {
 
-		// Setup midi driver
-		MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (getGameType() == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM));
-		_nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-
-		_driver = MidiDriver::createMidi(dev);
-
-		if (_nativeMT32)
-			_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
-		_midi.setNativeMT32(_nativeMT32);
-		_midi.mapMT32toGM(getGameType() != GType_SIMON2 && !_nativeMT32);
-
-		_midi.setDriver(_driver);
-
-		int ret = _midi.open();
+		int ret = _midi.open(getGameType());
 		if (ret)
-			warning("MIDI Player init failed: \"%s\"", MidiDriver::getErrorName (ret));
+			warning("MIDI Player init failed: \"%s\"", MidiDriver::getErrorName(ret));
 
 		_midi.setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
 
-
 		_midiEnabled = true;
-	} else {
-		_driver = NULL;
 	}
 
 	// Setup mixer
@@ -734,7 +716,7 @@ void AGOSEngine_Simon2::setupGame() {
 	_itemMemSize = 20000;
 	_tableMemSize = 100000;
 	// Check whether to use MT-32 MIDI tracks in Simon the Sorcerer 2
-	if (getGameType() == GType_SIMON2 && _nativeMT32)
+	if (getGameType() == GType_SIMON2 && _midi.hasNativeMT32())
 		_musicIndexBase = (1128 + 612) / 4;
 	else
 		_musicIndexBase = 1128 / 4;
@@ -895,9 +877,6 @@ void AGOSEngine::setupGame() {
 }
 
 AGOSEngine::~AGOSEngine() {
-	_midi.close();
-	delete _driver;
-
 	_system->getAudioCDManager()->stop();
 
 	for (uint i = 0; i < _itemHeap.size(); i++) {
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index 9c2a292..bf51b31 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -550,9 +550,7 @@ protected:
 	byte _lettersToPrintBuf[80];
 
 	MidiPlayer _midi;
-	MidiDriver *_driver;
 	bool _midiEnabled;
-	bool _nativeMT32;
 
 	int _vgaTickCounter;
 
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index d76aa42..234aa8d 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -25,6 +25,7 @@
 
 
 
+#include "common/config-manager.h"
 #include "common/file.h"
 #include "common/system.h"
 
@@ -62,15 +63,34 @@ MidiPlayer::MidiPlayer() {
 }
 
 MidiPlayer::~MidiPlayer() {
+	stop();
+
 	Common::StackLock lock(_mutex);
-	close();
+	if (_driver) {
+		_driver->close();
+		delete _driver;
+	}
+	_driver = NULL;
+	clearConstructs();
 }
 
-int MidiPlayer::open() {
-	// Don't ever call open without first setting the output driver!
+int MidiPlayer::open(int gameType) {
+	// Don't call open() twice!
+	assert(!_driver);
+
+	// Setup midi driver
+	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (gameType == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM));
+	_nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+
+	_driver = MidiDriver::createMidi(dev);
 	if (!_driver)
 		return 255;
 
+	if (_nativeMT32)
+		_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+
+	_map_mt32_to_gm = (gameType != GType_SIMON2 && !_nativeMT32);
+
 	int ret = _driver->open();
 	if (ret)
 		return ret;
@@ -84,18 +104,6 @@ int MidiPlayer::open() {
 	return 0;
 }
 
-void MidiPlayer::close() {
-	stop();
-//	_system->lockMutex(_mutex);
-	if (_driver) {
-		delete _driver;
-		_driver->close();
-	}
-	_driver = NULL;
-	clearConstructs();
-//	_system->unlockMutex(_mutex);
-}
-
 void MidiPlayer::send(uint32 b) {
 	if (!_current)
 		return;
@@ -305,12 +313,6 @@ void MidiPlayer::setDriver(MidiDriver *md) {
 	_driver = md;
 }
 
-void MidiPlayer::mapMT32toGM(bool map) {
-	Common::StackLock lock(_mutex);
-
-	_map_mt32_to_gm = map;
-}
-
 void MidiPlayer::setLoop(bool loop) {
 	Common::StackLock lock(_mutex);
 
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index 01456d7..64ab14d 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -97,8 +97,7 @@ public:
 	void loadXMIDI(Common::File *in, bool sfx = false);
 	void loadS1D(Common::File *in, bool sfx = false);
 
-	void mapMT32toGM(bool map);
-	void setNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; }
+	bool hasNativeMT32() const { return _nativeMT32; }
 	void setLoop(bool loop);
 	void startTrack(int track);
 	void queueTrack(int track, bool loop);
@@ -113,13 +112,13 @@ public:
 	void setDriver(MidiDriver *md);
 
 public:
-	// MidiDriver interface implementation
-	int open();
-	void close();
-	void send(uint32 b);
-
-	void metaEvent(byte type, byte *data, uint16 length);
+	int open(int gameType);
 	void setPassThrough(bool b)		{ _passThrough = b; }
+
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
+
 };
 
 } // End of namespace AGOS
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp
index 0bf2d5d..45d17ea 100644
--- a/engines/draci/draci.cpp
+++ b/engines/draci/draci.cpp
@@ -162,18 +162,7 @@ int DraciEngine::init() {
 	_dubbingArchive = openAnyPossibleDubbing();
 	_sound = new Sound(_mixer);
 
-	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
-	bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-	//bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
-
-	_midiDriver = MidiDriver::createMidi(dev);
-	if (native_mt32)
-		_midiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
-	_music = new MusicPlayer(_midiDriver, musicPathMask);
-	_music->setNativeMT32(native_mt32);
-	_music->open();
-	//_music->setAdLib(adlib);
+	_music = new MusicPlayer(musicPathMask);
 
 	// Setup mixer
 	syncSoundSettings();
@@ -404,7 +393,6 @@ DraciEngine::~DraciEngine() {
 
 	delete _sound;
 	delete _music;
-	delete _midiDriver;
 	delete _soundsArchive;
 	delete _dubbingArchive;
 
diff --git a/engines/draci/draci.h b/engines/draci/draci.h
index aa6080c..6a597e1 100644
--- a/engines/draci/draci.h
+++ b/engines/draci/draci.h
@@ -85,7 +85,6 @@ public:
 	AnimationManager *_anims;
 	Sound *_sound;
 	MusicPlayer *_music;
-	MidiDriver *_midiDriver;
 
 	Font *_smallFont;
 	Font *_bigFont;
diff --git a/engines/draci/music.cpp b/engines/draci/music.cpp
index b56e105..210e925 100644
--- a/engines/draci/music.cpp
+++ b/engines/draci/music.cpp
@@ -36,18 +36,46 @@
 
 namespace Draci {
 
-MusicPlayer::MusicPlayer(MidiDriver *driver, const char *pathMask) : _parser(0), _driver(driver), _pathMask(pathMask), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false), _track(-1) {
+MusicPlayer::MusicPlayer(const char *pathMask) : _parser(0), _driver(0), _pathMask(pathMask), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false), _track(-1) {
+
+	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+	_nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+	//bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
+
+	_driver = MidiDriver::createMidi(dev);
+	assert(_driver);
+	if (_nativeMT32)
+		_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+
 	memset(_channel, 0, sizeof(_channel));
 	memset(_channelVolume, 127, sizeof(_channelVolume));
 	_masterVolume = 0;
 	_smfParser = MidiParser::createParser_SMF();
 	_midiMusicData = NULL;
+
+	int ret = _driver->open();
+	if (ret == 0) {
+		if (_nativeMT32)
+			_driver->sendMT32Reset();
+		else
+			_driver->sendGMReset();
+
+		// TODO: Load cmf.ins with the instrument table.  It seems that an
+		// interface for such an operation is supported for AdLib.  Maybe for
+		// this card, setting instruments is necessary.
+
+		_driver->setTimerCallback(this, &onTimer);
+	}
 }
 
 MusicPlayer::~MusicPlayer() {
 	_driver->setTimerCallback(NULL, NULL);
 	stop();
-	this->close();
+	if (_driver) {
+		_driver->close();
+		delete _driver;
+		_driver = 0;
+	}
 	_smfParser->setMidiDriver(NULL);
 	delete _smfParser;
 	delete[] _midiMusicData;
@@ -75,37 +103,6 @@ void MusicPlayer::setVolume(int volume) {
 	}
 }
 
-int MusicPlayer::open() {
-	// Don't ever call open without first setting the output driver!
-	if (!_driver)
-		return 255;
-
-	int ret = _driver->open();
-	if (ret)
-		return ret;
-
-	if (_nativeMT32)
-		_driver->sendMT32Reset();
-	else
-		_driver->sendGMReset();
-
-	// TODO: Load cmf.ins with the instrument table.  It seems that an
-	// interface for such an operation is supported for AdLib.  Maybe for
-	// this card, setting instruments is necessary.
-
-	_driver->setTimerCallback(this, &onTimer);
-	return 0;
-}
-
-void MusicPlayer::close() {
-	stop();
-	if (_driver) {
-		_driver->close();
-		delete _driver;
-	}
-	_driver = 0;
-}
-
 void MusicPlayer::send(uint32 b) {
 	if (_passThrough) {
 		_driver->send(b);
diff --git a/engines/draci/music.h b/engines/draci/music.h
index 80d2501..e469014 100644
--- a/engines/draci/music.h
+++ b/engines/draci/music.h
@@ -38,7 +38,7 @@ namespace Draci {
 
 class MusicPlayer : public MidiDriver_BASE {
 public:
-	MusicPlayer(MidiDriver *driver, const char *pathMask);
+	MusicPlayer(const char *pathMask);
 	~MusicPlayer();
 
 	bool isPlaying() { return _isPlaying; }
@@ -48,7 +48,6 @@ public:
 	int getVolume() { return _masterVolume; }
 	void syncVolume();
 
-	void setNativeMT32(bool b) { _nativeMT32 = b; }
 	bool hasNativeMT32() { return _nativeMT32; }
 	void playSMF(int track, bool loop);
 	void stop();
@@ -59,21 +58,18 @@ public:
 
 	void setGM(bool isGM) { _isGM = isGM; }
 
-	// MidiDriver interface implementation
-	int open();
-	void close();
-	void send(uint32 b);
-
-	void metaEvent(byte type, byte *data, uint16 length);
-
-	MidiParser *_parser;
-	Common::Mutex _mutex;
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 protected:
 
 	static void onTimer(void *data);
 	void setChannelVolume(int channel);
 
+	MidiParser *_parser;
+	Common::Mutex _mutex;
+
 	MidiChannel *_channel[16];
 	MidiDriver *_driver;
 	MidiParser *_smfParser;
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 1921d65..7529f95 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -247,21 +247,10 @@ MusicPlayerMidi::~MusicPlayerMidi() {
 	delete _midiParser;
 
 	// Unload the MIDI Driver
-	if (_driver)
+	if (_driver) {
 		_driver->close();
-	delete _driver;
-}
-
-int MusicPlayerMidi::open() {
-	// Don't ever call open without first setting the output driver!
-	if (!_driver)
-		return 255;
-
-	int ret = _driver->open();
-	if (ret)
-		return ret;
-
-	return 0;
+		delete _driver;
+	}
 }
 
 void MusicPlayerMidi::send(uint32 b) {
@@ -375,7 +364,9 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
 	// Create the driver
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
 	_driver = MidiDriver::createMidi(dev);
-	this->open();
+	assert(_driver);
+
+	_driver->open();	// TODO: Handle return value != 0 (indicating an error)
 
 	// Set the parser's driver
 	_midiParser->setMidiDriver(this);
@@ -675,7 +666,9 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) {
 	// Create the driver
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
 	_driver = MidiDriver::createMidi(dev);
-	this->open();
+	assert(_driver);
+
+	_driver->open();	// TODO: Handle return value != 0 (indicating an error)
 
 	// Set the parser's driver
 	_midiParser->setMidiDriver(this);
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index 870fd10..bde0a7a 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -93,8 +93,7 @@ public:
 	MusicPlayerMidi(GroovieEngine *vm);
 	~MusicPlayerMidi();
 
-	// MidiDriver interface
-	virtual int open();
+	// MidiDriver_BASE interface
 	virtual void send(uint32 b);
 	virtual void metaEvent(byte type, byte *data, uint16 length);
 
diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index daa467f..f80faea 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -60,7 +60,16 @@ MidiPlayer::MidiPlayer(MidiDriver *driver)
 }
 
 MidiPlayer::~MidiPlayer() {
-	close();
+	stop();
+
+	Common::StackLock lock(_mutex);
+	_driver->setTimerCallback(0, 0);
+	_driver->close();
+	delete _driver;
+	_driver = 0;
+	if (_parser)
+		_parser->setMidiDriver(0);
+	delete _parser;
 }
 
 bool MidiPlayer::isPlaying() const {
@@ -179,19 +188,6 @@ int MidiPlayer::open() {
 	return 0;
 }
 
-void MidiPlayer::close() {
-	stop();
-
-	Common::StackLock lock(_mutex);
-	_driver->setTimerCallback(0, 0);
-	_driver->close();
-	delete _driver;
-	_driver = 0;
-	if (_parser)
-		_parser->setMidiDriver(0);
-	delete _parser;
-}
-
 void MidiPlayer::send(uint32 b) {
 	byte volume, ch = (byte)(b & 0xF);
 	debugC(9, kDebugMusic, "MidiPlayer::send, channel %d (volume is %d)", ch, _channelsVolume[ch]);
diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h
index c8f4ae5..cdde8cc 100644
--- a/engines/hugo/sound.h
+++ b/engines/hugo/sound.h
@@ -58,12 +58,11 @@ public:
 	void syncVolume();
 	void updateTimer();
 
-	// MidiDriver interface
-	int open();
-	void close();
-	void metaEvent(byte type, byte *data, uint16 length);
-	void send(uint32 b);
+	// MidiDriver_BASE interface
+	virtual void metaEvent(byte type, byte *data, uint16 length);
+	virtual void send(uint32 b);
 
+	int open();
 	uint32 getBaseTempo();
 
 private:
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 5f954eb..8ab0f54 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -97,8 +97,8 @@ SoundManager::~SoundManager() {
 	if (_driver) {
 		_driver->close();
 		delete _driver;
+		_driver = NULL;
 	}
-	_driver = NULL;
 
 	g_system->deleteMutex(_soundMutex);
 }
@@ -597,6 +597,7 @@ void SoundManager::doTimer() {
 MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
 					 uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size) {
 	_driver = driver;
+	assert(_driver);
 	_channels = channels;
 	_soundNumber = soundNum;
 	_channelNumber = channelNum;
@@ -620,9 +621,7 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
 	_parser->setMidiDriver(this);
 	_parser->setTimerRate(_driver->getBaseTempo());
 
-	this->open();
-
-	_soundData = (uint8 *) soundData;
+	_soundData = (uint8 *)soundData;
 	_soundSize = size;
 
 	// Check whether the music data is compressed - if so, decompress it for the duration
@@ -654,7 +653,6 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
 MidiMusic::~MidiMusic() {
 	_parser->unloadMusic();
 	delete _parser;
-	this->close();
 	delete _decompressedSound;
 }
 
@@ -686,17 +684,6 @@ void MidiMusic::playMusic() {
 	_isPlaying = true;
 }
 
-int MidiMusic::open() {
-	// Don't ever call open without first setting the output driver!
-	if (!_driver)
-		return 255;
-
-	return 0;
-}
-
-void MidiMusic::close() {
-}
-
 void MidiMusic::send(uint32 b) {
 	if (_passThrough) {
 		_driver->send(b);
@@ -749,7 +736,6 @@ void MidiMusic::stopMusic() {
 	debugC(ERROR_DETAILED, kLureDebugSounds, "MidiMusic::stopMusic sound %d", _soundNumber);
 	_isPlaying = false;
 	_parser->unloadMusic();
-	close();
 }
 
 } // End of namespace Lure
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index f4ddb8d..fe7ec50 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -84,13 +84,11 @@ public:
 	void setPassThrough(bool b) { _passThrough = b; }
 	void toggleVChange();
 
-	//MidiDriver interface implementation
-	int open();
-	void close();
-	void send(uint32 b);
-	void onTimer();
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
-	void metaEvent(byte type, byte *data, uint16 length);
+	void onTimer();
 
 	uint8 channelNumber() { return _channelNumber; }
 	uint8 soundNumber() { return _soundNumber; }
diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp
index 36f7f29..b5ae3b9 100644
--- a/engines/m4/midi.cpp
+++ b/engines/m4/midi.cpp
@@ -39,14 +39,21 @@ MidiPlayer::MidiPlayer(MadsM4Engine *vm, MidiDriver *driver) : _vm(vm), _midiDat
 	_parser = MidiParser::createParser_SMF();
 	_parser->setMidiDriver(this);
 	_parser->setTimerRate(_driver->getBaseTempo());
-	open();
+
+	int ret = _driver->open();
+	if (ret == 0)
+		_driver->setTimerCallback(this, &onTimer);
 }
 
 MidiPlayer::~MidiPlayer() {
 	_driver->setTimerCallback(NULL, NULL);
 	_parser->setMidiDriver(NULL);
 	stopMusic();
-	close();
+	if (_driver) {
+		_driver->close();
+		delete _driver;
+	}
+	_driver = 0;
 	delete _parser;
 	free(_midiData);
 }
@@ -71,28 +78,6 @@ void MidiPlayer::setVolume(int volume) {
 	}
 }
 
-int MidiPlayer::open() {
-	// Don't ever call open without first setting the output driver!
-	if (!_driver)
-		return 255;
-
-	int ret = _driver->open();
-	if (ret)
-		return ret;
-
-	_driver->setTimerCallback(this, &onTimer);
-	return 0;
-}
-
-void MidiPlayer::close() {
-	stopMusic();
-	if (_driver) {
-		_driver->close();
-		delete _driver;
-	}
-	_driver = 0;
-}
-
 void MidiPlayer::send(uint32 b) {
 	if (_passThrough) {
 		_driver->send(b);
diff --git a/engines/m4/midi.h b/engines/m4/midi.h
index 46dc5ef..42948e5 100644
--- a/engines/m4/midi.h
+++ b/engines/m4/midi.h
@@ -52,12 +52,9 @@ public:
 
 	void setGM(bool isGM) { _isGM = isGM; }
 
-	//MidiDriver interface implementation
-	int open();
-	void close();
-	void send(uint32 b);
-
-	void metaEvent(byte type, byte *data, uint16 length);
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 protected:
 	static void onTimer(void *data);
diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 1c8d54a..c81fa3d 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -100,18 +100,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
 
 	_script = new ScriptInterpreter(this);
 
-	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
-	bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-	//bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
-
-	MidiDriver *driver = MidiDriver::createMidi(dev);
-	if (native_mt32)
-		driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
-	_music = new MusicPlayer(driver);
-	_music->setNativeMT32(native_mt32);
-	_music->open();
-	//_music->setAdLib(adlib);
+	_music = new MusicPlayer();
 
 	// Set default sound frequency
 	switch (getGameID()) {
diff --git a/engines/made/music.cpp b/engines/made/music.cpp
index acb37bc..779b7d6 100644
--- a/engines/made/music.cpp
+++ b/engines/made/music.cpp
@@ -37,17 +37,40 @@
 
 namespace Made {
 
-MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
+MusicPlayer::MusicPlayer() : _parser(0), _driver(0), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
+	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+	_nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+	//bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
+
+	_driver = MidiDriver::createMidi(dev);
+	assert(_driver);
+	if (_nativeMT32)
+		_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+
 	memset(_channel, 0, sizeof(_channel));
 	_masterVolume = 0;
 	_xmidiParser = MidiParser::createParser_XMIDI();
 	_smfParser = MidiParser::createParser_SMF();
+
+	int ret = _driver->open();
+	if (ret == 0) {
+		if (_nativeMT32)
+			_driver->sendMT32Reset();
+		else
+			_driver->sendGMReset();
+
+		_driver->setTimerCallback(this, &onTimer);
+	}
 }
 
 MusicPlayer::~MusicPlayer() {
 	_driver->setTimerCallback(NULL, NULL);
 	stop();
-	this->close();
+	if (_driver) {
+		_driver->close();
+		delete _driver;
+		_driver = 0;
+	}
 	_xmidiParser->setMidiDriver(NULL);
 	_smfParser->setMidiDriver(NULL);
 	delete _xmidiParser;
@@ -71,33 +94,6 @@ void MusicPlayer::setVolume(int volume) {
 	}
 }
 
-int MusicPlayer::open() {
-	// Don't ever call open without first setting the output driver!
-	if (!_driver)
-		return 255;
-
-	int ret = _driver->open();
-	if (ret)
-		return ret;
-
-	if (_nativeMT32)
-		_driver->sendMT32Reset();
-	else
-		_driver->sendGMReset();
-
-	_driver->setTimerCallback(this, &onTimer);
-	return 0;
-}
-
-void MusicPlayer::close() {
-	stop();
-	if (_driver) {
-		_driver->close();
-		delete _driver;
-	}
-	_driver = 0;
-}
-
 void MusicPlayer::send(uint32 b) {
 	if (_passThrough) {
 		_driver->send(b);
diff --git a/engines/made/music.h b/engines/made/music.h
index 6bd4da4..b52a811 100644
--- a/engines/made/music.h
+++ b/engines/made/music.h
@@ -43,7 +43,7 @@ enum MusicFlags {
 
 class MusicPlayer : public MidiDriver_BASE {
 public:
-	MusicPlayer(MidiDriver *driver);
+	MusicPlayer();
 	~MusicPlayer();
 
 	bool isPlaying() { return _isPlaying; }
@@ -52,8 +52,7 @@ public:
 	void setVolume(int volume);
 	int getVolume() { return _masterVolume; }
 
-	void setNativeMT32(bool b) { _nativeMT32 = b; }
-	bool hasNativeMT32() { return _nativeMT32; }
+	bool hasNativeMT32() const { return _nativeMT32; }
 	void playXMIDI(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL);
 	void playSMF(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL);
 	void stop();
@@ -64,20 +63,17 @@ public:
 
 	void setGM(bool isGM) { _isGM = isGM; }
 
-	//MidiDriver interface implementation
-	int open();
-	void close();
-	void send(uint32 b);
-
-	void metaEvent(byte type, byte *data, uint16 length);
-
-	MidiParser *_parser;
-	Common::Mutex _mutex;
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 protected:
 
 	static void onTimer(void *data);
 
+	MidiParser *_parser;
+	Common::Mutex _mutex;
+
 	MidiChannel *_channel[16];
 	MidiDriver *_driver;
 	MidiParser *_xmidiParser, *_smfParser;
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index b74a584..c80f96b 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -220,11 +220,9 @@ public:
 	int getVolume() const { return _masterVolume; }
 	void setLooping(bool loop) { _isLooping = loop; }
 
-	// MidiDriver interface
-	int open();
-	void close();
-	void send(uint32 b);
-	void metaEvent(byte type, byte *data, uint16 length);
+	// MidiDriver_BASE interface
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 private:
 
@@ -254,11 +252,25 @@ MidiPlayer_MSC::MidiPlayer_MSC(MidiDriver *driver)
 		_volume[i] = 127;
 	}
 
-	open();
+	int ret = _driver->open();
+	if (ret == 0) {
+		_parser = createParser_MSC();
+		_parser->setMidiDriver(this);
+		_parser->setTimerRate(_driver->getBaseTempo());
+		_driver->setTimerCallback(this, &timerCallback);
+	}
 }
 
 MidiPlayer_MSC::~MidiPlayer_MSC() {
-	close();
+	stop();
+
+	Common::StackLock lock(_mutex);
+	_driver->setTimerCallback(NULL, NULL);
+	_driver->close();
+	delete _driver;
+	_driver = 0;
+	_parser->setMidiDriver(NULL);
+	delete _parser;
 }
 
 void MidiPlayer_MSC::play(Common::SeekableReadStream *stream) {
@@ -326,29 +338,6 @@ void MidiPlayer_MSC::setVolumeInternal(int volume) {
 	}
 }
 
-int MidiPlayer_MSC::open() {
-	int ret = _driver->open();
-	if (ret == 0) {
-		_parser = createParser_MSC();
-		_parser->setMidiDriver(this);
-		_parser->setTimerRate(_driver->getBaseTempo());
-		_driver->setTimerCallback(this, &timerCallback);
-	}
-	return ret;
-}
-
-void MidiPlayer_MSC::close() {
-	stop();
-
-	Common::StackLock lock(_mutex);
-	_driver->setTimerCallback(NULL, NULL);
-	_driver->close();
-	delete _driver;
-	_driver = 0;
-	_parser->setMidiDriver(NULL);
-	delete _parser;
-}
-
 void MidiPlayer_MSC::send(uint32 b) {
 	const byte ch = b & 0x0F;
 	byte param2 = (b >> 16) & 0xFF;
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index 6d80b5d..f924364 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -57,11 +57,9 @@ public:
 	int getVolume() const { return _masterVolume; }
 	void setLooping(bool loop) { _isLooping = loop; }
 
-	// MidiDriver interface
-	int open();
-	void close();
-	void send(uint32 b);
-	void metaEvent(byte type, byte *data, uint16 length);
+	// MidiDriver_BASE interface
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 private:
 
@@ -87,11 +85,25 @@ MidiPlayer::MidiPlayer(MidiDriver *driver)
 		_channelsVolume[i] = 127;
 	}
 
-	open();
+	int ret = _driver->open();
+	if (ret == 0) {
+		_parser = MidiParser::createParser_SMF();
+		_parser->setMidiDriver(this);
+		_parser->setTimerRate(_driver->getBaseTempo());
+		_driver->setTimerCallback(this, &timerCallback);
+	}
 }
 
 MidiPlayer::~MidiPlayer() {
-	close();
+	stop();
+
+	Common::StackLock lock(_mutex);
+	_driver->setTimerCallback(NULL, NULL);
+	_driver->close();
+	delete _driver;
+	_driver = 0;
+	_parser->setMidiDriver(NULL);
+	delete _parser;
 }
 
 void MidiPlayer::play(Common::SeekableReadStream *stream) {
@@ -161,29 +173,6 @@ void MidiPlayer::setVolume(int volume) {
 	}
 }
 
-int MidiPlayer::open() {
-	int ret = _driver->open();
-	if (ret == 0) {
-		_parser = MidiParser::createParser_SMF();
-		_parser->setMidiDriver(this);
-		_parser->setTimerRate(_driver->getBaseTempo());
-		_driver->setTimerCallback(this, &timerCallback);
-	}
-	return ret;
-}
-
-void MidiPlayer::close() {
-	stop();
-
-	Common::StackLock lock(_mutex);
-	_driver->setTimerCallback(NULL, NULL);
-	_driver->close();
-	delete _driver;
-	_driver = 0;
-	_parser->setMidiDriver(NULL);
-	delete _parser;
-}
-
 void MidiPlayer::send(uint32 b) {
 	byte volume, ch = (byte)(b & 0xF);
 	switch (b & 0xFFF0) {
diff --git a/engines/queen/music.h b/engines/queen/music.h
index 898abb4..09d29fb 100644
--- a/engines/queen/music.h
+++ b/engines/queen/music.h
@@ -56,9 +56,9 @@ public:
 	void queueClear();
 	void toggleVChange();
 
-	//MidiDriver interface implementation
-	void send(uint32 b);
-	void metaEvent(byte type, byte *data, uint16 length);
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 protected:
 
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index b683505..6db55c2 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -55,27 +55,20 @@ MusicDriver::MusicDriver() : _isGM(false) {
 	if (isMT32())
 		_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
 
-	this->open();
+	int retValue = _driver->open();
+	if (retValue == 0) {
+		if (_nativeMT32)
+			_driver->sendMT32Reset();
+		else
+			_driver->sendGMReset();
+	}
 }
 
 MusicDriver::~MusicDriver() {
-	this->close();
+	_driver->close();
 	delete _driver;
 }
 
-int MusicDriver::open() {
-	int retValue = _driver->open();
-	if (retValue)
-		return retValue;
-
-	if (_nativeMT32)
-		_driver->sendMT32Reset();
-	else
-		_driver->sendGMReset();
-
-	return 0;
-}
-
 void MusicDriver::setVolume(int volume) {
 	volume = CLIP(volume, 0, 255);
 
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 0b7d21d..745f322 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -56,18 +56,14 @@ public:
 	bool isMT32() { return _driverType == MT_MT32 || _nativeMT32; }
 	void setGM(bool isGM) { _isGM = isGM; }
 
-	//MidiDriver interface implementation
-	int open();
-	bool isOpen() const;
-	void close() { _driver->close(); }
-	void send(uint32 b);
-
-	void metaEvent(byte type, byte *data, uint16 length) {}
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length) {}
 
 	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _driver->setTimerCallback(timerParam, timerProc); }
 	uint32 getBaseTempo()	{ return _driver->getBaseTempo(); }
 
-	Common::Mutex _mutex;
+	Common::Mutex _mutex;	// FIXME: Make _mutex protected
 
 protected:
 
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index 3e0d87b..235f03a 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -386,18 +386,41 @@ void DeleteMidiBuffer() {
 	midiBuffer.pDat = NULL;
 }
 
-MidiMusicPlayer::MidiMusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false) {
+MidiMusicPlayer::MidiMusicPlayer() : _parser(0), _driver(0), _looping(false), _isPlaying(false) {
+	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+	bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+	//bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
+
+	_driver = MidiDriver::createMidi(dev);
+	assert(_driver);
+	if (native_mt32)
+		_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+
 	memset(_channel, 0, sizeof(_channel));
 	memset(_channelVolume, 0, sizeof(_channelVolume));
 	_masterVolume = 0;
-	this->open();
+
+	int ret = _driver->open();
+	if (ret == 0) {
+		if (native_mt32)
+			_driver->sendMT32Reset();
+		else
+			_driver->sendGMReset();
+
+		_driver->setTimerCallback(this, &onTimer);
+	}
+
 	_xmidiParser = MidiParser::createParser_XMIDI();
 }
 
 MidiMusicPlayer::~MidiMusicPlayer() {
 	_driver->setTimerCallback(NULL, NULL);
 	stop();
-	this->close();
+	if (_driver) {
+		_driver->close();
+		delete _driver;
+		_driver = 0;
+	}
 	_xmidiParser->setMidiDriver(NULL);
 	delete _xmidiParser;
 }
@@ -419,28 +442,6 @@ void MidiMusicPlayer::setVolume(int volume) {
 	}
 }
 
-int MidiMusicPlayer::open() {
-	// Don't ever call open without first setting the output driver!
-	if (!_driver)
-		return 255;
-
-	int ret = _driver->open();
-	if (ret)
-		return ret;
-
-	_driver->setTimerCallback(this, &onTimer);
-	return 0;
-}
-
-void MidiMusicPlayer::close() {
-	stop();
-	if (_driver) {
-		_driver->close();
-		delete _driver;
-	}
-	_driver = 0;
-}
-
 void MidiMusicPlayer::send(uint32 b) {
 	byte channel = (byte)(b & 0x0F);
 	if ((b & 0xFFF0) == 0x07B0) {
diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h
index a75f2b8..1857032 100644
--- a/engines/tinsel/music.h
+++ b/engines/tinsel/music.h
@@ -62,7 +62,7 @@ void dumpMusic();
 
 class MidiMusicPlayer : public MidiDriver_BASE {
 public:
-	MidiMusicPlayer(MidiDriver *driver);
+	MidiMusicPlayer();
 	~MidiMusicPlayer();
 
 	bool isPlaying() { return _isPlaying; }
@@ -78,16 +78,12 @@ public:
 	void resume();
 	void setLoop(bool loop) { _looping = loop; }
 
-	//MidiDriver interface implementation
-	int open();
-	void close();
-	void send(uint32 b);
-
-	void metaEvent(byte type, byte *data, uint16 length);
+	// MidiDriver_BASE interface implementation
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 	// The original sets the "sequence timing" to 109 Hz, whatever that
 	// means. The default is 120.
-
 	uint32 getBaseTempo()	{ return _driver ? (109 * _driver->getBaseTempo()) / 120 : 0; }
 
 protected:
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 2333553..ef0fe1c 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -856,23 +856,8 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
 	if (cd_num >= 0)
 		_system->getAudioCDManager()->openCD(cd_num);
 
-	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
-	bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-	//bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
-
-	_driver = MidiDriver::createMidi(dev);
-	if (native_mt32)
-		_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
-	_midiMusic = new MidiMusicPlayer(_driver);
+	_midiMusic = new MidiMusicPlayer();
 	_pcmMusic = new PCMMusicPlayer();
-	//_midiMusic->setNativeMT32(native_mt32);
-	//_midiMusic->setAdLib(adlib);
-
-	if (native_mt32)
-		_driver->sendMT32Reset();
-	else
-		_driver->sendGMReset();
 
 	_musicVolume = ConfMan.getInt("music_volume");
 
@@ -896,7 +881,6 @@ TinselEngine::~TinselEngine() {
 	delete _midiMusic;
 	delete _pcmMusic;
 	delete _console;
-	delete _driver;
 	_screenSurface.free();
 	FreeSaveScenes();
 	FreeTextBuffer();
diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp
index c6c7a60..4349a29 100644
--- a/engines/touche/midi.cpp
+++ b/engines/touche/midi.cpp
@@ -36,11 +36,34 @@ MidiPlayer::MidiPlayer()
 	: _driver(0), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0) {
 	memset(_channelsTable, 0, sizeof(_channelsTable));
 	memset(_channelsVolume, 0, sizeof(_channelsVolume));
-	open();
+
+	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+	_nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+	_driver = MidiDriver::createMidi(dev);
+	int ret = _driver->open();
+	if (ret == 0) {
+		_parser = MidiParser::createParser_SMF();
+		_parser->setMidiDriver(this);
+		_parser->setTimerRate(_driver->getBaseTempo());
+		_driver->setTimerCallback(this, &timerCallback);
+
+		if (_nativeMT32)
+			_driver->sendMT32Reset();
+		else
+			_driver->sendGMReset();
+	}
 }
 
 MidiPlayer::~MidiPlayer() {
-	close();
+	stop();
+
+	Common::StackLock lock(_mutex);
+	_driver->setTimerCallback(NULL, NULL);
+	_driver->close();
+	delete _driver;
+	_driver = 0;
+	_parser->setMidiDriver(NULL);
+	delete _parser;
 }
 
 void MidiPlayer::play(Common::ReadStream &stream, int size, bool loop) {
@@ -88,37 +111,6 @@ void MidiPlayer::setVolume(int volume) {
 	}
 }
 
-int MidiPlayer::open() {
-	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
-	_nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-	_driver = MidiDriver::createMidi(dev);
-	int ret = _driver->open();
-	if (ret == 0) {
-		_parser = MidiParser::createParser_SMF();
-		_parser->setMidiDriver(this);
-		_parser->setTimerRate(_driver->getBaseTempo());
-		_driver->setTimerCallback(this, &timerCallback);
-
-		if (_nativeMT32)
-			_driver->sendMT32Reset();
-		else
-			_driver->sendGMReset();
-	}
-	return ret;
-}
-
-void MidiPlayer::close() {
-	stop();
-
-	Common::StackLock lock(_mutex);
-	_driver->setTimerCallback(NULL, NULL);
-	_driver->close();
-	delete _driver;
-	_driver = 0;
-	_parser->setMidiDriver(NULL);
-	delete _parser;
-}
-
 void MidiPlayer::send(uint32 b) {
 	byte volume, ch = (byte)(b & 0xF);
 	switch (b & 0xFFF0) {
diff --git a/engines/touche/midi.h b/engines/touche/midi.h
index a750f12..bc5adc6 100644
--- a/engines/touche/midi.h
+++ b/engines/touche/midi.h
@@ -57,11 +57,9 @@ public:
 	int getVolume() const { return _masterVolume; }
 	void setLooping(bool loop) { _isLooping = loop; }
 
-	// MidiDriver interface
-	int open();
-	void close();
-	void send(uint32 b);
-	void metaEvent(byte type, byte *data, uint16 length);
+	// MidiDriver_BASE interface
+	virtual void send(uint32 b);
+	virtual void metaEvent(byte type, byte *data, uint16 length);
 
 private:
 






More information about the Scummvm-git-logs mailing list