aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sound/music.cpp
diff options
context:
space:
mode:
authorMartin Kiewitz2010-06-21 22:07:03 +0000
committerMartin Kiewitz2010-06-21 22:07:03 +0000
commit1041067a0c1ca2ac528338d99eaa1df677538265 (patch)
tree616f0510349ec005432bb9b9d3d1a4ded3519c43 /engines/sci/sound/music.cpp
parent6c854f30da2579c8e7059948c700fd0bcc72366d (diff)
downloadscummvm-rg350-1041067a0c1ca2ac528338d99eaa1df677538265.tar.gz
scummvm-rg350-1041067a0c1ca2ac528338d99eaa1df677538265.tar.bz2
scummvm-rg350-1041067a0c1ca2ac528338d99eaa1df677538265.zip
SCI: instead of queueing inside midiparser, we are queueing now globally in SciMusic, also some little cleanup
svn-id: r50130
Diffstat (limited to 'engines/sci/sound/music.cpp')
-rw-r--r--engines/sci/sound/music.cpp94
1 files changed, 69 insertions, 25 deletions
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index 6c697c86e5..b6ab7f9f70 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -46,6 +46,8 @@ SciMusic::SciMusic(SciVersion soundVersion)
for (int i = 0; i < 16; i++)
_usedChannel[i] = 0;
+
+ _queuedCommandCount = 0;
}
SciMusic::~SciMusic() {
@@ -102,6 +104,49 @@ void SciMusic::init() {
_driverFirstChannel = _pMidiDrv->getFirstChannel();
}
+void SciMusic::miditimerCallback(void *p) {
+ SciMusic *sciMusic = (SciMusic *)p;
+
+ Common::StackLock lock(sciMusic->_mutex);
+ sciMusic->onTimer();
+}
+
+void SciMusic::onTimer() {
+ const MusicList::iterator end = _playList.end();
+ // sending out queued commands that were "sent" via main thread
+ sendMidiCommandsFromQueue();
+
+ for (MusicList::iterator i = _playList.begin(); i != end; ++i)
+ (*i)->onTimer();
+
+ // for sending out fade commands immediately
+ sendMidiCommandsFromQueue();
+}
+
+void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) {
+ putMidiCommandInQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+}
+
+void SciMusic::putMidiCommandInQueue(uint32 midi) {
+ if (_queuedCommandCount >= 1000)
+ error("driver queue is full");
+ _queuedCommands[_queuedCommandCount] = midi;
+ _queuedCommandCount++;
+}
+
+// This sends the stored commands from queue to driver (is supposed to get called only during onTimer())
+// at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get
+// a crash during piano scene in lsl5)
+void SciMusic::sendMidiCommandsFromQueue() {
+ int curCommand = 0;
+
+ while (curCommand < _queuedCommandCount) {
+ _pMidiDrv->send(_queuedCommands[curCommand]);
+ curCommand++;
+ }
+ _queuedCommandCount = 0;
+}
+
void SciMusic::clearPlayList() {
Common::StackLock lock(_mutex);
@@ -127,14 +172,6 @@ void SciMusic::stopAll() {
}
}
-
-void SciMusic::miditimerCallback(void *p) {
- SciMusic *aud = (SciMusic *)p;
-
- Common::StackLock lock(aud->_mutex);
- aud->onTimer();
-}
-
void SciMusic::soundSetSoundOn(bool soundOnFlag) {
Common::StackLock lock(_mutex);
@@ -219,8 +256,10 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
// Find out what channels to filter for SCI0
channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel());
- pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
+ pSnd->pMidiParser->mainThreadBegin();
+ pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
+ pSnd->pMidiParser->mainThreadEnd();
_mutex.unlock();
}
}
@@ -255,12 +294,6 @@ void SciMusic::freeChannels(MusicEntry *caller) {
}
}
-void SciMusic::onTimer() {
- const MusicList::iterator end = _playList.end();
- for (MusicList::iterator i = _playList.begin(); i != end; ++i)
- (*i)->onTimer();
-}
-
void SciMusic::soundPlay(MusicEntry *pSnd) {
_mutex.lock();
@@ -316,18 +349,21 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
DisposeAfterUse::NO);
}
} else {
- _mutex.lock();
if (pSnd->pMidiParser) {
+ _mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->tryToOwnChannels();
pSnd->pMidiParser->setVolume(pSnd->volume);
if (pSnd->status == kSoundStopped) {
pSnd->pMidiParser->sendInitCommands();
pSnd->pMidiParser->jumpToTick(0);
- } else
+ } else {
// Fast forward to the last position and perform associated events when loading
pSnd->pMidiParser->jumpToTick(pSnd->ticker, true);
+ }
+ pSnd->pMidiParser->mainThreadEnd();
+ _mutex.unlock();
}
- _mutex.unlock();
}
pSnd->status = kSoundPlaying;
@@ -342,8 +378,10 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
if (pSnd->pMidiParser) {
_mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->stop();
freeChannels(pSnd);
+ pSnd->pMidiParser->mainThreadEnd();
_mutex.unlock();
}
}
@@ -354,7 +392,9 @@ void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
_pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127
} else if (pSnd->pMidiParser) {
_mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->setVolume(volume);
+ pSnd->pMidiParser->mainThreadEnd();
_mutex.unlock();
}
}
@@ -369,13 +409,15 @@ void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) {
void SciMusic::soundKill(MusicEntry *pSnd) {
pSnd->status = kSoundStopped;
- _mutex.lock();
if (pSnd->pMidiParser) {
+ _mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->unloadMusic();
+ pSnd->pMidiParser->mainThreadEnd();
delete pSnd->pMidiParser;
pSnd->pMidiParser = NULL;
+ _mutex.unlock();
}
- _mutex.unlock();
if (pSnd->pStreamAud) {
_pMixer->stopHandle(pSnd->hCurrentAud);
@@ -409,8 +451,10 @@ void SciMusic::soundPause(MusicEntry *pSnd) {
} else {
if (pSnd->pMidiParser) {
_mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->pause();
freeChannels(pSnd);
+ pSnd->pMidiParser->mainThreadEnd();
_mutex.unlock();
}
}
@@ -458,10 +502,12 @@ void SciMusic::sendMidiCommand(uint32 cmd) {
void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) {
Common::StackLock lock(_mutex);
- if (pSnd->pMidiParser)
- pSnd->pMidiParser->sendToDriverQueue(cmd);
- else
+ if (!pSnd->pMidiParser)
error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj));
+
+ pSnd->pMidiParser->mainThreadBegin();
+ pSnd->pMidiParser->sendFromScriptToDriver(cmd);
+ pSnd->pMidiParser->mainThreadEnd();
}
void SciMusic::printPlayList(Console *con) {
@@ -567,8 +613,6 @@ void MusicEntry::onTimer() {
// Only process MIDI streams in this thread, not digital sound effects
if (pMidiParser) {
- // Process manual commands first
- pMidiParser->sendQueueToDriver();
pMidiParser->onTimer();
ticker = (uint16)pMidiParser->getTick();
}