[Scummvm-git-logs] scummvm master -> ecc72dce23e231b3eeb7f91a8edcb9121c37abdc
tsoliman
tarek at bashasoliman.com
Tue Sep 21 21:35:49 UTC 2021
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
ecc72dce23 SCI: Don't poll input events from MIDI thread
Commit: ecc72dce23e231b3eeb7f91a8edcb9121c37abdc
https://github.com/scummvm/scummvm/commit/ecc72dce23e231b3eeb7f91a8edcb9121c37abdc
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2021-09-21T16:35:46-05:00
Commit Message:
SCI: Don't poll input events from MIDI thread
In March, b67c2d72d6c40fda2d67cfaf6a8aab9f44f7cd1e moved some MIDI
initialization from the main thread to the MIDI thread. This caused
MidiPlayer_Midi::sysEx() to run on the MIDI thread for the first time.
This is a problem because it calls SciEngine:sleep(), which polls
events, and that causes MacOS to throw an exception for calling
SDL_PollEvent() on a non-main thread.
While investigating, it also turns out that MidiPlayer_Midi::sysEx()
and MidiPlayer_Fb01::sysEx() were calling OSystem::updateScreen(),
and that also shouldn't be happening on a non-main thread.
Now SciEngine::sleep() is only called on the main thread, and
OSystem::delayMillis() is called on the MIDI timer thread.
Continuing to call sleep() on the main thread keeps the UI responsive
when loading patches, which can take several seconds.
The OSystem::updateScreen() calls had no effect and have been removed.
Fixes bug #12947
Changed paths:
engines/sci/sound/drivers/fb01.cpp
engines/sci/sound/drivers/midi.cpp
diff --git a/engines/sci/sound/drivers/fb01.cpp b/engines/sci/sound/drivers/fb01.cpp
index ce9d28055f..9e9ad2ad9b 100644
--- a/engines/sci/sound/drivers/fb01.cpp
+++ b/engines/sci/sound/drivers/fb01.cpp
@@ -783,7 +783,6 @@ void MidiPlayer_Fb01::sysEx(const byte *msg, uint16 length) {
delay += 10;
g_system->delayMillis(delay);
- g_system->updateScreen();
}
byte MidiPlayer_Fb01::getPlayId() const {
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index 6b3015d733..7a967b308c 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -149,6 +149,7 @@ public:
void close() override;
void send(uint32 b) override;
void sysEx(const byte *msg, uint16 length) override;
+ uint16 sysExNoDelay(const byte *msg, uint16 length) override;
bool hasRhythmChannel() const override { return true; }
byte getPlayId() const override;
int getPolyphony() const override {
@@ -179,8 +180,8 @@ private:
uint8 lookupGmRhythmKey(const char *iname);
uint8 getGmInstrument(const Mt32ToGmMap &Mt32Ins);
- void sendMt32SysEx(const uint32 addr, Common::SeekableReadStream &data, const int len, bool noDelay);
- void sendMt32SysEx(const uint32 addr, const SciSpan<const byte> &data, bool noDelay);
+ void sendMt32SysEx(const uint32 addr, Common::SeekableReadStream &data, const int len, bool noDelay, bool mainThread);
+ void sendMt32SysEx(const uint32 addr, const SciSpan<const byte> &data, bool noDelay, bool mainThread);
void setMt32Volume(byte volume);
void resetMt32();
@@ -507,7 +508,7 @@ void MidiPlayer_Midi::setReverb(int8 reverb) {
assert(reverb < kReverbConfigNr);
if (_hasReverb && _reverb != reverb) {
- sendMt32SysEx(0x100001, SciSpan<const byte>(_reverbConfig[reverb], 3), true);
+ sendMt32SysEx(0x100001, SciSpan<const byte>(_reverbConfig[reverb], 3), true, true);
}
_reverb = reverb;
@@ -580,7 +581,7 @@ void MidiPlayer_Midi::initTrack(SciSpan<const byte> &header) {
// assign channels
debugC(5, kDebugLevelSound, "MidiPlayer_Midi::initTrack(): Channels assigned to MT-32 parts: 0x%.02x 0x%.02x 0x%.02x 0x%.02x 0x%.02x 0x%.02x 0x%.02x 0x%.02x 0x%.02x", msg[0], msg[1], msg[2], msg[3], msg[4], msg[5], msg[6], msg[7], msg[8]);
Sci::SciSpan<const byte> s(msg, 9);
- sendMt32SysEx(0x10000D, s, false);
+ sendMt32SysEx(0x10000D, s, false, false);
}
bool MidiPlayer_Midi::isMt32GmPatch(const SciSpan<const byte> &data) {
@@ -632,7 +633,7 @@ bool MidiPlayer_Midi::isMt32GmPatch(const SciSpan<const byte> &data) {
return isMt32Gm;
}
-void MidiPlayer_Midi::sendMt32SysEx(const uint32 addr, Common::SeekableReadStream &stream, int len, bool noDelay = false) {
+void MidiPlayer_Midi::sendMt32SysEx(const uint32 addr, Common::SeekableReadStream &stream, int len, bool noDelay = false, bool mainThread = true) {
if (len + 8 > kMaxSysExSize) {
warning("SysEx message exceed maximum size; ignoring");
return;
@@ -651,15 +652,24 @@ void MidiPlayer_Midi::sendMt32SysEx(const uint32 addr, Common::SeekableReadStrea
_sysExBuf[7 + len] = chk & 0x7f;
- if (noDelay)
- _driver->sysEx(_sysExBuf, len + 8);
- else
- sysEx(_sysExBuf, len + 8);
+ uint16 delay = sysExNoDelay(_sysExBuf, len + 8);
+ if (!noDelay && delay > 0) {
+ // Use the appropriate delay technique based on the current thread.
+ // On the main thread, use SciEngine::sleep() to keep the UI responsive,
+ // which is important because loading patches can take several seconds.
+ // On a timer thread however, SciEngine::sleep() can't be used because
+ // it polls events and updates the screen, which isn't thread safe. (bug #12947)
+ if (mainThread) {
+ g_sci->sleep(delay);
+ } else {
+ g_system->delayMillis(delay);
+ }
+ }
}
-void MidiPlayer_Midi::sendMt32SysEx(const uint32 addr, const SciSpan<const byte> &buf, bool noDelay = false) {
+void MidiPlayer_Midi::sendMt32SysEx(const uint32 addr, const SciSpan<const byte> &buf, bool noDelay = false, bool mainThread = true) {
Common::MemoryReadStream stream(buf.toStream());
- sendMt32SysEx(addr, stream, buf.size(), noDelay);
+ sendMt32SysEx(addr, stream, buf.size(), noDelay, mainThread);
}
@@ -1229,7 +1239,7 @@ void MidiPlayer_Midi::resetMt32() {
if (_mt32Type != kMt32TypeEmulated) {
// This seems to require a longer delay than usual
- g_sci->sleep(150);
+ g_sci->sleep(150); // note that sleep() can only be called from main thread, see bug #12947
}
}
@@ -1409,19 +1419,26 @@ void MidiPlayer_Midi::close() {
}
void MidiPlayer_Midi::sysEx(const byte *msg, uint16 length) {
+ uint16 delay = sysExNoDelay(msg, length);
+
+ if (delay > 0)
+ g_system->delayMillis(delay);
+}
+
+uint16 MidiPlayer_Midi::sysExNoDelay(const byte *msg, uint16 length) {
_driver->sysEx(msg, length);
+ uint16 delay = 0;
if (_mt32Type != kMt32TypeEmulated) {
// Wait the time it takes to send the SysEx data
- uint32 delay = (length + 2) * 1000 / 3125;
+ delay = (length + 2) * 1000 / 3125;
// Plus an additional delay for the MT-32 rev00
if (_mt32Type == kMt32TypeReal)
delay += 40;
-
- g_system->updateScreen();
- g_sci->sleep(delay);
}
+
+ return delay;
}
byte MidiPlayer_Midi::getPlayId() const {
More information about the Scummvm-git-logs
mailing list