aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2008-01-01 11:27:29 +0000
committerMax Horn2008-01-01 11:27:29 +0000
commit305f60e0dbefa3861f5ca3614a2b930aca8afc2c (patch)
treefe546c9f565ff4c9a999158e97a4e6af107a8d0f
parenta8d3967f63f51c77b8a934ec05b09803185afa12 (diff)
downloadscummvm-rg350-305f60e0dbefa3861f5ca3614a2b930aca8afc2c.tar.gz
scummvm-rg350-305f60e0dbefa3861f5ca3614a2b930aca8afc2c.tar.bz2
scummvm-rg350-305f60e0dbefa3861f5ca3614a2b930aca8afc2c.zip
Patch #1839861 (Possible workaround for bugs related to cloneToFadeOutTrack): Fixes bug #1848399 and apparently also #1527274 & #1763227
svn-id: r30111
-rw-r--r--engines/scumm/imuse_digi/dimuse.cpp16
-rw-r--r--engines/scumm/imuse_digi/dimuse.h3
-rw-r--r--engines/scumm/imuse_digi/dimuse_script.cpp49
-rw-r--r--engines/scumm/imuse_digi/dimuse_track.cpp45
4 files changed, 63 insertions, 50 deletions
diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index 776b840145..dba7e921b8 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 f4a8a7467c..d6aa6d271f 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 b9ba72bb93..b9e242e529 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 1a9d59a214..faaae470e7 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;