diff --git a/tools/chatgui/src/messagedelegate.cpp b/tools/chatgui/src/messagedelegate.cpp index bb395fbc..d7f00eaa 100644 --- a/tools/chatgui/src/messagedelegate.cpp +++ b/tools/chatgui/src/messagedelegate.cpp @@ -1084,10 +1084,12 @@ void MessageDelegate::paintBody(QPainter* painter, const QStyleOptionViewItem& o auto* view = qobject_cast(const_cast(option.widget)); if (view && s_voiceView != view) { s_voiceView = view; - QObject::connect(view, &QObject::destroyed, QCoreApplication::instance(), [] { - if (s_voiceView) return; // Уничтожен прежний view, текущий продолжает воспроизведение. + GUI_DEBUG("voice delegate: tracking view=%p", static_cast(view)); + QObject::connect(view, &QObject::destroyed, QCoreApplication::instance(), [view] { + if (s_voiceView && s_voiceView.data() != view) return; // Другой текущий view продолжает воспроизведение. + s_voiceView = nullptr; MessageDelegate::stopAllAutoPlay(); - GUI_DEBUG("voice delegate: view destroyed, playback state released"); + GUI_DEBUG("voice delegate: view=%p destroyed, playback state released", static_cast(view)); }); } drawBubble(painter, L, option); diff --git a/tools/chatgui/tests/test_desktop_commands.cpp b/tools/chatgui/tests/test_desktop_commands.cpp index c74492a4..8c4437d5 100644 --- a/tools/chatgui/tests/test_desktop_commands.cpp +++ b/tools/chatgui/tests/test_desktop_commands.cpp @@ -225,7 +225,7 @@ private slots: QTest::newRow(qPrintable(name + (temporary ? "-owned-source" : "-borrowed-source"))) << name << temporary; } void attachmentOwnership() { - QFETCH(QString, scenario); QFETCH(bool, temporary); DesktopCore core; QVERIFY(core.start()); + QFETCH(QString, scenario); QFETCH(bool, temporary); std::atomic releases{0}; DesktopCore core; QVERIFY(core.start()); const quint64 channel = chat_core_create_channel_auto(core.inst, "Attachment ownership"); QVERIFY(channel); core.poll(); const QByteArray source = core.directory.filePath("recording.raw").toUtf8(); @@ -234,11 +234,10 @@ private slots: #ifdef UTUN_TEST_DESKTOP_HOOKS watching = true; #endif - std::atomic releases{0}; - struct PcmOwner { std::atomic* releases; int16_t samples[4800]; }; + struct PcmOwner { std::atomic* releases; int16_t samples[24000]; }; auto* owner = static_cast(u_calloc(1, sizeof(PcmOwner))); QVERIFY(owner); owner->releases = &releases; auto* request = static_cast(u_calloc(1, sizeof(attachment_send_req))); QVERIFY(request); - request->pcm = owner->samples; request->pcm_count = 4800; request->pcm_owner = owner; + request->pcm = owner->samples; request->pcm_count = 24000; request->pcm_owner = owner; request->pcm_release = [](void* arg) { auto* pcm = static_cast(arg); ++*pcm->releases; u_free(pcm); }; request->info.kind = ATTACHMENT_VOICE; request->request_id = 77; qstrncpy(request->target, qPrintable(QString::number(channel)), sizeof(request->target)); @@ -399,7 +398,10 @@ private slots: QFETCH(int, action); QFETCH(QString, scenario); QFETCH(bool, window); DesktopCore core; QVERIFY(core.start()); std::unique_ptr form; - if (window) form = std::make_unique(nullptr, nullptr, QString()); // UtunNode остаётся владельцу fixture. + if (window) { + form = std::make_unique(nullptr, nullptr, QString()); // UtunNode остаётся владельцу fixture. + core.poll(); QCoreApplication::processEvents(); // Отделить стартовые настройки media от проверяемой команды. + } if (scenario == "unavailable") gui_bridge_set_inst(nullptr); if (scenario == "stopped") uasync_mark_stopped(core.ua); #ifdef UTUN_TEST_DESKTOP_HOOKS