Patch #1839861 (Possible workaround for bugs related to cloneToFadeOutTrack): Fixes bug #1848399 and apparently also #1527274 & #1763227

svn-id: r30111
This commit is contained in:
Max Horn 2008-01-01 11:27:29 +00:00
parent a8d3967f63
commit 305f60e0db
4 changed files with 63 additions and 50 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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;