From ff04cd6d6926598985ac8975df9a9e0d8bdbcdc7 Mon Sep 17 00:00:00 2001 From: Eladash Date: Thu, 4 Jun 2020 20:54:31 +0300 Subject: [PATCH] cellAudio: Fix event queue attachment --- rpcs3/Emu/Cell/Modules/cellAudio.cpp | 29 +++++++++++++++++++++------- rpcs3/Emu/Cell/Modules/cellAudio.h | 4 +++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.cpp b/rpcs3/Emu/Cell/Modules/cellAudio.cpp index 6e69533e71..925660cadd 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudio.cpp @@ -460,7 +460,7 @@ void cell_audio_thread::advance(u64 timestamp, bool reset) for (const auto& key_inf : keys) { - if (const auto queue = lv2_event_queue::find(key_inf.key)) + if ((queues[queue_count] = key_inf.port.lock())) { if (key_inf.flags & CELL_AUDIO_EVENTFLAG_NOMIX) { @@ -483,11 +483,12 @@ void cell_audio_thread::advance(u64 timestamp, bool reset) if ((event_period ^ key_inf.start_period) & (periods - 1)) { // The time has not come for this key to receive event + queues[queue_count].reset(); continue; } event_sources[queue_count] = key_inf.source; - queues[queue_count++] = queue; + queue_count++; } } @@ -1429,21 +1430,35 @@ error_code AudioSetNotifyEventQueue(u64 key, u32 iFlags) return CELL_AUDIO_ERROR_NOT_INIT; } - if (!lv2_event_queue::find(key)) + auto q = lv2_event_queue::find(key); + + if (!q) { return CELL_AUDIO_ERROR_TRANS_EVENT; } - for (const auto& k : g_audio->keys) // check for duplicates + for (auto i = g_audio->keys.cbegin(); i != g_audio->keys.cend();) // check for duplicates { - if (k.key == key) + auto port = i->port.lock(); + + if (port == q) { return CELL_AUDIO_ERROR_TRANS_EVENT; } + + if (!lv2_event_queue::check(port)) + { + // Cleanup, avoid cases where there are multiple ports with the same key + i = g_audio->keys.erase(i); + } + else + { + i++; + } } // Set unique source associated with the key - g_audio->keys.push_back({g_audio->event_period, iFlags, ((process_getpid() + u64{}) << 32) + lv2_event_port::id_base + (g_audio->key_count++ * lv2_event_port::id_step), key}); + g_audio->keys.push_back({g_audio->event_period, iFlags, ((process_getpid() + u64{}) << 32) + lv2_event_port::id_base + (g_audio->key_count++ * lv2_event_port::id_step), std::move(q)}); g_audio->key_count %= lv2_event_port::id_count; return CELL_OK; @@ -1481,7 +1496,7 @@ error_code AudioRemoveNotifyEventQueue(u64 key, u32 iFlags) for (auto i = g_audio->keys.cbegin(); i != g_audio->keys.cend(); i++) { - if (i->key == key) + if ([&](auto port){ return lv2_event_queue::check(port) && port->key == key; }(i->port.lock())) { if (i->flags != iFlags) { diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.h b/rpcs3/Emu/Cell/Modules/cellAudio.h index bff53fa9fc..695971f206 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.h +++ b/rpcs3/Emu/Cell/Modules/cellAudio.h @@ -6,6 +6,8 @@ #include "Emu/Audio/AudioBackend.h" #include "Emu/Audio/AudioDumper.h" +struct lv2_event_queue; + // Error codes enum CellAudioError : u32 { @@ -358,7 +360,7 @@ public: u8 start_period; // Starting event_period u32 flags; // iFlags u64 source; // Event source - u64 key; // Key + std::weak_ptr port; // Underlying event port }; std::vector keys;