From 8da99fc5d1820ffb70180167998321d3bc3ade68 Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Sun, 27 Sep 2020 18:01:14 -0700 Subject: [PATCH] Fix the ZFP dialog desync bug introduced post 0.7. The core issue is that the sound-advancement callbacks (used only for altering the ZFP dialog locations) were altered to be launched asynchronously from the main thread. This meant that new dialog could be detected before the waiting callbacks had run. This patch moves audio callbacks back into the audio decoding thread and protects them with the speech-channel mutex. This should guarantee that cur_sub_chunk only appears as a value when consulting the current subtitles after the callback has run completely. Logic has also been added to CheckSubtitles to raise a warning in the logs if the values get out of sync. --- sc2/src/libs/sound/trackplayer.c | 4 +++- sc2/src/uqm/comm.c | 21 +++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/sc2/src/libs/sound/trackplayer.c b/sc2/src/libs/sound/trackplayer.c index edff1943b..8068fc388 100644 --- a/sc2/src/libs/sound/trackplayer.c +++ b/sc2/src/libs/sound/trackplayer.c @@ -198,10 +198,12 @@ StopTrack (void) static void DoTrackTag (TFB_SoundChunk *chunk) { + LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); if (chunk->callback) - Callback_add(chunk->callback, 0); + chunk->callback(0); cur_sub_chunk = chunk; + UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } // This func is called by PlayStream() when stream is about diff --git a/sc2/src/uqm/comm.c b/sc2/src/uqm/comm.c index 6336de8a9..ff2818c43 100644 --- a/sc2/src/uqm/comm.c +++ b/sc2/src/uqm/comm.c @@ -532,7 +532,7 @@ UpdateAnimations (bool paused) BatchGraphics (); // Advance and draw ambient, transit and talk animations change = ProcessCommAnimations (clear_subtitles, paused); - if (change) + if (change || clear_subtitles) RedrawSubtitles (); UnbatchGraphics (); clear_subtitles = FALSE; @@ -1608,15 +1608,28 @@ static void CheckSubtitles (void) { const UNICODE *pStr; + POINT baseline; + TEXT_ALIGN align; pStr = GetTrackSubtitle (); + baseline = CommData.AlienTextBaseline; + align = CommData.AlienTextAlign; - if (pStr != SubtitleText.pStr) + if (pStr != SubtitleText.pStr || + SubtitleText.baseline.x != baseline.x || + SubtitleText.baseline.y != baseline.y || + SubtitleText.align != align) { // Subtitles changed clear_subtitles = TRUE; // Baseline may be updated by the ZFP - SubtitleText.baseline = CommData.AlienTextBaseline; - SubtitleText.align = CommData.AlienTextAlign; + SubtitleText.baseline = baseline; + SubtitleText.align = align; + // Make a note in the logs if the update was multiframe + if (SubtitleText.pStr == pStr) + { + log_add (log_Warning, "Dialog text and location changed out of sync"); + } + SubtitleText.pStr = pStr; // may have been cleared too if (pStr)