CINE: Make PC sound code thread safe, since the MIDI output might run the callback in an extra thread.

This commit is contained in:
Johannes Schickel 2011-12-11 04:54:18 +01:00
parent 42fd697544
commit 6ba090b45a

View File

@ -26,6 +26,7 @@
#include "common/system.h" #include "common/system.h"
#include "common/textconsole.h" #include "common/textconsole.h"
#include "common/timer.h" #include "common/timer.h"
#include "common/mutex.h"
#include "cine/cine.h" #include "cine/cine.h"
#include "cine/sound.h" #include "cine/sound.h"
@ -200,6 +201,7 @@ public:
private: private:
MidiDriver *_output; MidiDriver *_output;
UpdateCallback _callback; UpdateCallback _callback;
Common::Mutex _mutex;
void writeInstrument(int offset, const byte *data, int size); void writeInstrument(int offset, const byte *data, int size);
void selectInstrument(int channel, int unk, int instrument, int volume); void selectInstrument(int channel, int unk, int instrument, int volume);
@ -241,6 +243,7 @@ private:
byte *_sfxData; byte *_sfxData;
byte *_instrumentsData[NUM_INSTRUMENTS]; byte *_instrumentsData[NUM_INSTRUMENTS];
PCSoundDriver *_driver; PCSoundDriver *_driver;
Common::Mutex _mutex;
}; };
@ -595,7 +598,7 @@ void AdLibSoundDriverADL::playSample(const byte *data, int size, int channel, in
} }
MidiSoundDriverH32::MidiSoundDriverH32(MidiDriver *output) MidiSoundDriverH32::MidiSoundDriverH32(MidiDriver *output)
: _output(output), _callback(0) { : _output(output), _callback(0), _mutex() {
} }
MidiSoundDriverH32::~MidiSoundDriverH32() { MidiSoundDriverH32::~MidiSoundDriverH32() {
@ -607,6 +610,8 @@ MidiSoundDriverH32::~MidiSoundDriverH32() {
} }
void MidiSoundDriverH32::setUpdateCallback(UpdateCallback upCb, void *ref) { void MidiSoundDriverH32::setUpdateCallback(UpdateCallback upCb, void *ref) {
Common::StackLock lock(_mutex);
Common::TimerManager *timer = g_system->getTimerManager(); Common::TimerManager *timer = g_system->getTimerManager();
assert(timer); assert(timer);
@ -619,6 +624,8 @@ void MidiSoundDriverH32::setUpdateCallback(UpdateCallback upCb, void *ref) {
} }
void MidiSoundDriverH32::setupChannel(int channel, const byte *data, int instrument, int volume) { void MidiSoundDriverH32::setupChannel(int channel, const byte *data, int instrument, int volume) {
Common::StackLock lock(_mutex);
if (volume < 0 || volume > 100) if (volume < 0 || volume > 100)
volume = 0; volume = 0;
@ -631,6 +638,8 @@ void MidiSoundDriverH32::setupChannel(int channel, const byte *data, int instrum
} }
void MidiSoundDriverH32::setChannelFrequency(int channel, int frequency) { void MidiSoundDriverH32::setChannelFrequency(int channel, int frequency) {
Common::StackLock lock(_mutex);
int note, oct; int note, oct;
findNote(frequency, &note, &oct); findNote(frequency, &note, &oct);
note %= 12; note %= 12;
@ -640,10 +649,14 @@ void MidiSoundDriverH32::setChannelFrequency(int channel, int frequency) {
} }
void MidiSoundDriverH32::stopChannel(int channel) { void MidiSoundDriverH32::stopChannel(int channel) {
Common::StackLock lock(_mutex);
_output->send(0xB1 + channel, 0x7B, 0x00); _output->send(0xB1 + channel, 0x7B, 0x00);
} }
void MidiSoundDriverH32::playSample(const byte *data, int size, int channel, int volume) { void MidiSoundDriverH32::playSample(const byte *data, int size, int channel, int volume) {
Common::StackLock lock(_mutex);
stopChannel(channel); stopChannel(channel);
volume = volume * 8 / 5; volume = volume * 8 / 5;
@ -659,6 +672,8 @@ void MidiSoundDriverH32::playSample(const byte *data, int size, int channel, int
} }
void MidiSoundDriverH32::notifyInstrumentLoad(const byte *data, int size, int channel) { void MidiSoundDriverH32::notifyInstrumentLoad(const byte *data, int size, int channel) {
Common::StackLock lock(_mutex);
if (data[0] < 0x80 || data[0] > 0xC0) if (data[0] < 0x80 || data[0] > 0xC0)
return; return;
@ -722,7 +737,7 @@ void MidiSoundDriverH32::selectInstrument(int channel, int unk, int instrument,
} }
PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver) PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver)
: _playing(false), _driver(driver) { : _playing(false), _driver(driver), _mutex() {
memset(_instrumentsData, 0, sizeof(_instrumentsData)); memset(_instrumentsData, 0, sizeof(_instrumentsData));
_sfxData = NULL; _sfxData = NULL;
_fadeOutCounter = 0; _fadeOutCounter = 0;
@ -730,12 +745,15 @@ PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver)
} }
PCSoundFxPlayer::~PCSoundFxPlayer() { PCSoundFxPlayer::~PCSoundFxPlayer() {
Common::StackLock lock(_mutex);
_driver->setUpdateCallback(NULL, NULL); _driver->setUpdateCallback(NULL, NULL);
stop(); stop();
} }
bool PCSoundFxPlayer::load(const char *song) { bool PCSoundFxPlayer::load(const char *song) {
debug(9, "PCSoundFxPlayer::load('%s')", song); debug(9, "PCSoundFxPlayer::load('%s')", song);
Common::StackLock lock(_mutex);
/* stop (w/ fade out) the previous song */ /* stop (w/ fade out) the previous song */
while (_fadeOutCounter != 0 && _fadeOutCounter < 100) { while (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
@ -779,6 +797,7 @@ bool PCSoundFxPlayer::load(const char *song) {
void PCSoundFxPlayer::play() { void PCSoundFxPlayer::play() {
debug(9, "PCSoundFxPlayer::play()"); debug(9, "PCSoundFxPlayer::play()");
Common::StackLock lock(_mutex);
if (_sfxData) { if (_sfxData) {
for (int i = 0; i < NUM_CHANNELS; ++i) { for (int i = 0; i < NUM_CHANNELS; ++i) {
_instrumentsChannelTable[i] = -1; _instrumentsChannelTable[i] = -1;
@ -793,6 +812,7 @@ void PCSoundFxPlayer::play() {
} }
void PCSoundFxPlayer::stop() { void PCSoundFxPlayer::stop() {
Common::StackLock lock(_mutex);
if (_playing || _fadeOutCounter != 0) { if (_playing || _fadeOutCounter != 0) {
_fadeOutCounter = 0; _fadeOutCounter = 0;
_playing = false; _playing = false;
@ -805,6 +825,7 @@ void PCSoundFxPlayer::stop() {
} }
void PCSoundFxPlayer::fadeOut() { void PCSoundFxPlayer::fadeOut() {
Common::StackLock lock(_mutex);
if (_playing) { if (_playing) {
_fadeOutCounter = 1; _fadeOutCounter = 1;
_playing = false; _playing = false;
@ -816,6 +837,7 @@ void PCSoundFxPlayer::updateCallback(void *ref) {
} }
void PCSoundFxPlayer::update() { void PCSoundFxPlayer::update() {
Common::StackLock lock(_mutex);
if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) { if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) {
++_updateTicksCounter; ++_updateTicksCounter;
if (_updateTicksCounter > _eventsDelay) { if (_updateTicksCounter > _eventsDelay) {