mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
fix(tci): дефекты живого прогона — length аудио, маршруты тапов, MOX, рекордер, EOF сокета
Восемь дефектов, найденных прогоном настоящего TCI-клиента (три приёмника: NFM, DIGU, FMRAW) и его отчётом. 1. UI доп. панорам не перерисовывался: rfSliceState рассылался, но ветки в MainForm.OnControllerState не было (частоту несёт отдельный rfSliceFreq). 2. Stream.length у аудио — сэмплы НА КАНАЛ (§4.3), у IQ — вещественные отсчёты (§3.4: комплексных = length/channels). Было ×каналы везде, у стерео получалось вдвое больше. Развилка в TCIFillHeader + разбор TX-аудио в HandleBinary. 3+4. Дыры в маршрутах аудио движка: demod-тап звался только для DMR/FMRAW (у DIGU не было RX_AUDIO), а пост-громкостный — только для нецифровых (у FMRAW не было LINEOUT). Плюс мьют слайса больше не убивает RX_AUDIO: движку сообщают SetAudioTapsActive. 5. Клиент, поставивший TRX, уходил — MOX оставался. FTrxOwner + StopTxOf; TCIMicRequested снимается и по окончании любой передачи. 6. Гонка снятия IQ-тапа: SetIQTap(nil) возвращался раньше, чем DSP-поток выходил из вызова. FIQTapLock (порядок FSliceLock → FIQTapLock). 7. Рекордер был кольцом «последние N секунд», а §4.3 говорит про МАКСИМАЛЬНОЕ время записи с удалением по истечении. Переделан в линейный буфер с окном по часам от START. 8. TCIServer.HandleClient считал recv = 0 таймаутом: ноль — это EOF, errno при нём не трогается и несёт EAGAIN от прошлого истёкшего TCI_POLL_MS. Обычный TCP-разрыв без close-кадра не освобождал слот до остановки сервера, и после нескольких аварийных отключений новые клиенты упирались в TCI_MAX_CLIENTS. Теперь R = 0 рвёт связь безусловно, errno спрашивается только при R < 0. Попутно: MainForm.RecreateDSPEngine (смена sample rate до START) терял внутренние колбэки контроллера — введён AttachEngineCallbacks. Стенд test/tci заведён в репозиторий (run.sh, 126/126 зелёных, включая сквозной прогон через живой WDSP), доп. проверки на оба пути отключения клиента. doc/TCI.md приведена в соответствие: правило про recv = 0 в §1.1, единицы Stream.length, линейный буфер рекордера. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+10
-3
@@ -1203,9 +1203,16 @@ begin
|
||||
if not Pending then
|
||||
begin
|
||||
R := Ws.Recv;
|
||||
// R <= 0 — либо разрыв, либо просто истёк TCI_POLL_MS. Второе штатно:
|
||||
// просыпаемся, чтобы отдать накопившуюся очередь.
|
||||
if (R <= 0) and not SockRecvTimedOut then Break;
|
||||
// R = 0 — клиент закрыл свою сторону (EOF). Это НЕ ошибка, errno при
|
||||
// этом не трогается и вполне может нести EAGAIN от прошлого истёкшего
|
||||
// TCI_POLL_MS — спрашивать его тут нельзя, иначе обычный TCP-разрыв
|
||||
// без close-кадра выглядит как таймаут и слот клиента не освобождается
|
||||
// до остановки сервера. Место в буфере есть всегда (кадр крупнее
|
||||
// буфера рвётся выше), так что нулю иного смысла нет.
|
||||
if R = 0 then Break;
|
||||
// R < 0 — ошибка: либо разрыв, либо просто истёк TCI_POLL_MS. Второе
|
||||
// штатно: просыпаемся, чтобы отдать накопившуюся очередь.
|
||||
if (R < 0) and not SockRecvTimedOut then Break;
|
||||
end;
|
||||
Pending := False;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user