From 305f60e0dbefa3861f5ca3614a2b930aca8afc2c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 1 Jan 2008 11:27:29 +0000 Subject: [PATCH] Patch #1839861 (Possible workaround for bugs related to cloneToFadeOutTrack): Fixes bug #1848399 and apparently also #1527274 & #1763227 svn-id: r30111 --- engines/scumm/imuse_digi/dimuse.cpp | 16 ++++--- engines/scumm/imuse_digi/dimuse.h | 3 +- engines/scumm/imuse_digi/dimuse_script.cpp | 49 ++++++++++++---------- engines/scumm/imuse_digi/dimuse_track.cpp | 45 ++++++++++---------- 4 files changed, 63 insertions(+), 50 deletions(-) diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp index 776b8401458..dba7e921b81 100644 --- a/engines/scumm/imuse_digi/dimuse.cpp +++ b/engines/scumm/imuse_digi/dimuse.cpp @@ -158,7 +158,6 @@ void IMuseDigital::saveOrLoad(Serializer *ser) { if (!ser->isSaving()) { if (!track->used) continue; - track->readyToRemove = false; if ((track->toBeRemoved) || (track->souStreamUsed) || (track->curRegion == -1)) { track->streamSou= NULL; track->stream = NULL; @@ -231,9 +230,10 @@ void IMuseDigital::callback() { for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { Track *track = _track[l]; - if (track->used && !track->readyToRemove) { + if (track->used) { + // Remove tracks if necessary if (track->toBeRemoved) { - track->readyToRemove = true; + flushTrack(track); continue; } @@ -249,7 +249,9 @@ void IMuseDigital::callback() { track->volFadeUsed = false; } if (track->vol == 0) { - track->toBeRemoved = true; + // Fade out complete -> remove this track + flushTrack(track); + continue; } } } else if (track->volFadeStep > 0) { @@ -357,6 +359,8 @@ void IMuseDigital::callback() { } while (feedSize != 0); } else if (track->streamSou) { if (_mixer->isReady()) { + // FIXME: Can't we replace track->mixerStreamRunning by + // _mixer->isSoundHandleActive(track->mixChanHandle) ? if (!track->mixerStreamRunning) { track->mixerStreamRunning = true; _mixer->playInputStream(type, &track->mixChanHandle, track->streamSou, -1, vol, pan, false); @@ -375,7 +379,7 @@ void IMuseDigital::switchToNextRegion(Track *track) { debug(5, "switchToNextRegion(track:%d)", track->trackId); if (track->trackId >= MAX_DIGITAL_TRACKS) { - track->toBeRemoved = true; + flushTrack(track); debug(5, "exit (fadetrack can't go next region) switchToNextRegion(trackId:%d)", track->trackId); return; } @@ -383,7 +387,7 @@ void IMuseDigital::switchToNextRegion(Track *track) { int num_regions = _sound->getNumRegions(track->soundDesc); if (++track->curRegion == num_regions) { - track->toBeRemoved = true; + flushTrack(track); debug(5, "exit (end of regions) switchToNextRegion(track:%d)", track->trackId); return; } diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h index f4a8a7467c1..d6aa6d271f3 100644 --- a/engines/scumm/imuse_digi/dimuse.h +++ b/engines/scumm/imuse_digi/dimuse.h @@ -83,7 +83,6 @@ private: char soundName[15]; // sound name but also filename of sound in bundle data bool used; // flag mean that track is used bool toBeRemoved; // flag mean that track need to be free - bool readyToRemove; // flag mean that track is ready to stop bool mixerStreamRunning; // flag mean sound mixer's stream is running bool souStreamUsed; // flag mean that track use stream from sou file bool sndDataExtComp;// flag mean that sound data is compressed by scummvm tools @@ -152,6 +151,8 @@ private: void setDigMusicSequence(int seqId); void playDigMusic(const char *songName, const imuseDigTable *table, int attribPos, bool sequence); + void flushTrack(Track *track); + public: IMuseDigital(ScummEngine_v7 *scumm, Audio::Mixer *mixer, int fps); virtual ~IMuseDigital(); diff --git a/engines/scumm/imuse_digi/dimuse_script.cpp b/engines/scumm/imuse_digi/dimuse_script.cpp index b9ba72bb931..b9e242e5295 100644 --- a/engines/scumm/imuse_digi/dimuse_script.cpp +++ b/engines/scumm/imuse_digi/dimuse_script.cpp @@ -163,32 +163,37 @@ void IMuseDigital::parseScriptCmds(int cmd, int b, int c, int d, int e, int f, i } } +void IMuseDigital::flushTrack(Track *track) { + track->toBeRemoved = true; + if (track->stream) { + // Finalize the appendable stream + track->stream->finish(); + // There might still be some data left in the buffers of the + // appendable stream. We play it nice and wait till all of it + // played. + if (track->stream->endOfStream()) { + _mixer->stopHandle(track->mixChanHandle); + delete track->stream; + track->stream = NULL; + _sound->closeSound(track->soundDesc); + track->soundDesc = NULL; + track->used = false; + } + } else if (track->streamSou) { + _mixer->stopHandle(track->mixChanHandle); + delete track->streamSou; + track->streamSou = NULL; + track->used = false; + } +} + void IMuseDigital::flushTracks() { Common::StackLock lock(_mutex, "IMuseDigital::flushTracks()"); debug(5, "flushTracks()"); for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { Track *track = _track[l]; - if (track->used && track->readyToRemove) { - if (track->stream) { - // Finalize the appendable stream - track->stream->finish(); - // There might still be some data left in the buffers of the - // appendable stream. We play it nice and wait till all of it - // played. - if (track->stream->endOfStream()) { - _mixer->stopHandle(track->mixChanHandle); - delete track->stream; - track->stream = NULL; - _sound->closeSound(track->soundDesc); - track->soundDesc = NULL; - track->used = false; - } - } else if (track->streamSou) { - _mixer->stopHandle(track->mixChanHandle); - delete track->streamSou; - track->streamSou = NULL; - track->used = false; - } + if (track->used && track->toBeRemoved) { + flushTrack(track); } } } @@ -288,7 +293,7 @@ int IMuseDigital::getSoundStatus(int sound) const { Track *track = _track[l]; if (track->soundId == sound) { if ((track->streamSou && _mixer->isSoundHandleActive(track->mixChanHandle)) || - (track->stream && track->used && !track->readyToRemove)) { + (track->stream && !track->stream->endOfStream())) { return 1; } } diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp index 1a9d59a2145..faaae470e72 100644 --- a/engines/scumm/imuse_digi/dimuse_track.cpp +++ b/engines/scumm/imuse_digi/dimuse_track.cpp @@ -59,7 +59,22 @@ int IMuseDigital::allocSlot(int priority) { } if (lowest_priority <= priority) { assert(trackId != -1); - _track[trackId]->toBeRemoved = true; + Track *track = _track[trackId]; + while (1) { + if (!track->used) { + break; + } + // The designated track is not yet available. So, we call flushTrack() + // to get it processed (and thus made ready for us). Since the actual + // processing is done by another thread, we also call parseEvents to + // give it some time (and to avoid busy waiting/looping). + flushTrack(track); + _mutex.unlock(); + #ifndef __PLAYSTATION2__ + _vm->parseEvents(); + #endif + _mutex.lock(); + } debug(5, "IMuseDigital::allocSlot(): Removed sound %d from track %d", _track[trackId]->soundId, trackId); } else { debug(5, "IMuseDigital::allocSlot(): Priority sound too low"); @@ -71,6 +86,7 @@ int IMuseDigital::allocSlot(int priority) { } void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, int volGroupId, Audio::AudioStream *input, int hookId, int volume, int priority) { + Common::StackLock lock(_mutex, "IMuseDigital::startSound()"); debug(5, "IMuseDigital::startSound(%d)", soundId); int l = allocSlot(priority); @@ -80,21 +96,6 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, } Track *track = _track[l]; - while (1) { - _mutex.lock(); - if (!track->used) { - break; - } - // The designated track is not yet available. So, we call flushTracks() - // to get it processed (and thus made ready for us). Since the actual - // processing is done by another thread, we also call parseEvents to - // give it some time (and to avoid busy waiting/looping). - flushTracks(); - _mutex.unlock(); -#ifndef __PLAYSTATION2__ - _vm->parseEvents(); -#endif - } track->pan = 64; track->vol = volume * 1000; @@ -113,7 +114,6 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, track->dataMod12Bit = 0; track->mixerFlags = 0; track->toBeRemoved = false; - track->readyToRemove = false; track->soundType = soundType; int bits = 0, freq = 0, channels = 0; @@ -191,7 +191,6 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, } track->used = true; - _mutex.unlock(); } void IMuseDigital::setPriority(int soundId, int priority) { @@ -309,7 +308,7 @@ void IMuseDigital::fadeOutMusic(int fadeDelay) { Track *track = _track[l]; if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) { cloneToFadeOutTrack(track, fadeDelay); - track->toBeRemoved = true; + flushTrack(track); } } } @@ -319,9 +318,14 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(Track *track, int fadeDel Track *fadeTrack = 0; debug(0, "IMuseDigital::cloneToFadeOutTrack(%d, %d)", track->trackId, fadeDelay); + + if (track->toBeRemoved) { + error("IMuseDigital::cloneToFadeOutTrack: Tried to clone a track to be removed"); + return NULL; + } if (_track[track->trackId + MAX_DIGITAL_TRACKS]->used) { - warning("IMuseDigital::cloneToFadeOutTrack: Not free fade track"); + warning("IMuseDigital::cloneToFadeOutTrack: No free fade track"); return NULL; } @@ -360,7 +364,6 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(Track *track, int fadeDel } fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundDesc), makeMixerFlags(fadeTrack->mixerFlags)); _mixer->playInputStream(type, &fadeTrack->mixChanHandle, fadeTrack->stream, -1, fadeTrack->vol / 1000, fadeTrack->pan, false); - fadeTrack->mixerStreamRunning = true; fadeTrack->used = true;