|
|
|
|
@ -17,9 +17,11 @@ extern "C" {
|
|
|
|
|
#include "radio/radio_audio.h" |
|
|
|
|
#include "radio/radio.h" |
|
|
|
|
#include "chat/chat_setting.h" |
|
|
|
|
#include "config_parser.h" |
|
|
|
|
#include "u_async.h" |
|
|
|
|
#include "debug_config.h" |
|
|
|
|
#include "silero_vad.h" |
|
|
|
|
#include "mem.h" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define REQUIRE(condition) do { if (!(condition)) qFatal("radio panel line %d: %s", __LINE__, #condition); } while (0) |
|
|
|
|
@ -107,7 +109,7 @@ int main(int argc, char** argv) {
|
|
|
|
|
pump(750); // Полное кольцо prefetch до начала речи.
|
|
|
|
|
int previousPackets = packets; |
|
|
|
|
probability = 0.9f; |
|
|
|
|
await([&]() { return engine->isTransmitting(); }); |
|
|
|
|
await([&]() { return engine->isTransmitting() && begins == 1 && packets >= previousPackets + 30; }); |
|
|
|
|
REQUIRE(!engine->isTalking() && ptt->property("transmitting").toBool() && begins == 1); |
|
|
|
|
REQUIRE(packets >= previousPackets + 30); |
|
|
|
|
int beforeManual = begins; |
|
|
|
|
@ -120,7 +122,7 @@ int main(int argc, char** argv) {
|
|
|
|
|
pump(100); |
|
|
|
|
REQUIRE(!engine->isTalking() && engine->isTransmitting() && begins == beforeManual); |
|
|
|
|
probability = 0; |
|
|
|
|
await([&]() { return !engine->isTransmitting(); }); |
|
|
|
|
await([&]() { return !engine->isTransmitting() && ends == 1; }); |
|
|
|
|
REQUIRE(!ptt->property("transmitting").toBool() && ends == 1); |
|
|
|
|
qInfo("radio panel: automatic TX, 600ms prefetch, actual UI state and manual/hotkey handover PASS"); |
|
|
|
|
|
|
|
|
|
@ -157,6 +159,11 @@ int main(int argc, char** argv) {
|
|
|
|
|
REQUIRE(saved.contains("radio_vad_enabled=1") && saved.contains("radio_vad_threshold=65") && |
|
|
|
|
saved.contains("radio_vad_hangover_ms=400") && saved.contains("radio_vad_compressor_max_gain_db=30") && |
|
|
|
|
saved.contains("radio_opus_bitrate=32")); |
|
|
|
|
// Как при рестарте приложения: runtime-настройки заново читаются парсером из сохранённого INI.
|
|
|
|
|
auto* parsed = parse_config(configPath.toUtf8().constData()); |
|
|
|
|
REQUIRE(parsed); |
|
|
|
|
instance.chat_settings = parsed->global.chat_settings; |
|
|
|
|
free_config(parsed); |
|
|
|
|
engine->loadSettings(configPath); |
|
|
|
|
await([&]() { return !engine->settingsBusy(); }); |
|
|
|
|
REQUIRE(engine->vadEnabled() && engine->setting("radio_vad_threshold") == 65); |
|
|
|
|
@ -195,6 +202,15 @@ int main(int argc, char** argv) {
|
|
|
|
|
uasync_destroy(instance.ua, 0); |
|
|
|
|
instance.ua = nullptr; |
|
|
|
|
manager->shutdown(); |
|
|
|
|
size_t allocated = u_get_allocated_count(); |
|
|
|
|
instance.ua = uasync_create(); |
|
|
|
|
REQUIRE(instance.ua); |
|
|
|
|
engine->loadSettings(configPath); |
|
|
|
|
REQUIRE(engine->settingsBusy() && instance.ua->posted_tasks_head); |
|
|
|
|
uasync_destroy(instance.ua, 0); |
|
|
|
|
instance.ua = nullptr; |
|
|
|
|
REQUIRE(u_get_allocated_count() == allocated); |
|
|
|
|
qInfo("radio panel: pending settings request freed on core shutdown PASS"); |
|
|
|
|
qInfo("radio panel: saved settings, channel change, device menus, range validation and config failure PASS"); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|