refactor: STCP connections as ETCP links (is_tcp)

- Add is_tcp, tcp_link, tcp_reconnect_* fields to ETCP_LINK
- Remove transport_link from ETCP_CONN, add tcp_link_count
- stcp_link: replace embedded etcp_conn with pointer; add etcp_link backpointer
- stcp_link: link_rx_cb routes ETCP data to etcp_conn_input
- stcp_link: call on_close_cb in close
- New TCP functions: etcp_link_enter_ready_tcp, etcp_tcp_link_start_connect,
  etcp_tcp_link_start_reconnect, tcp_link_close_cb, etcp_tcp_send
- etcp_link_new: handle NULL conn for TCP links; skip enter_init for TCP
- etcp_link_close: close stcp_link for TCP
- etcp_encrypt_send: redirect TCP to etcp_tcp_send (skips AES-CCM)
- tcp_server_on_link: create ETCP_LINK(is_tcp=1) + enter_ready_tcp
- etcp_connect: TCP addrs -> etcp_tcp_link_start_connect
- Remove ctx->tcp_link/tcp_ready
- test_stcp_traffic: find stcp_link via links->is_tcp instead of transport_link
- 66/68 tests pass; 2 STCP tests expected to fail (integration not complete)
This commit is contained in:
evgeny committed 2026-08-06 22:14:32 +03:00
1 parent 937af4c26a
commit d773f1724a
1705 files changed
+187 -1082154

No files matched your search

-200
View File
@@ -1,200 +0,0 @@
#include "audiorecorder.h"
#include "miniaudio.h"
#include "sound_manager.h"
extern "C" {
#include "../../lib/audio_compressor.h"
}
#include "../../lib/debug_config.h"
#include <cstring>
#include <cstdlib>
#include <cmath>
static AudioRecorder* g_recorder = nullptr;
void audioCaptureCallback(ma_device* pDevice, void* pOutput, const void* pInput, unsigned int frameCount) {
(void)pOutput;
AudioRecorder* self = g_recorder;
if (!self || !self->m_recording) return;
if (!pInput) return;
const int16_t* src = (const int16_t*)pInput;
size_t add = (size_t)frameCount * (size_t)self->m_channels;
if (self->m_compressor && self->m_compressorEnabled) {
audio_compressor_push(self->m_compressor, src, add);
} else {
size_t cur = self->m_pcmBuffer.size();
self->m_pcmBuffer.resize(cur + add);
std::memcpy(self->m_pcmBuffer.data() + cur, src, add * sizeof(int16_t));
}
float sumSq = 0.0f;
for (unsigned int i = 0; i < frameCount * (unsigned int)self->m_channels; i++) {
float v = (float)src[i] / 32768.0f;
sumSq += v * v;
}
float rms = sqrtf(sumSq / (float)(frameCount * self->m_channels));
self->m_peakLevel = rms;
self->m_recentRms[self->m_rmsIdx % 5] = rms;
self->m_rmsIdx++;
if (self->m_rmsIdx >= 5) {
float avg = 0.0f;
for (int i = 0; i < 5; i++) avg += self->m_recentRms[i];
avg /= 5.0f;
self->m_waveformLevels.push_back(avg);
}
}
AudioRecorder::AudioRecorder(QObject* parent)
: QObject(parent) {
g_recorder = this;
m_compressor = audio_compressor_create();
if (m_compressor) {
audio_compressor_config_t cfg = {0};
cfg.sample_rate = m_sampleRate;
cfg.channels = m_channels;
audio_compressor_configure(m_compressor, &cfg);
}
m_durationTimer.setInterval(100);
connect(&m_durationTimer, &QTimer::timeout, this, [this]() {
if (m_recording) {
m_elapsedMs += 100;
emit durationChanged(m_elapsedMs);
}
});
}
AudioRecorder::~AudioRecorder() {
shutdown();
audio_compressor_destroy(m_compressor);
m_compressor = nullptr;
if (g_recorder == this) g_recorder = nullptr;
}
bool AudioRecorder::init() {
if (m_initialized) return true;
m_device = new ma_device;
std::memset(m_device, 0, sizeof(*m_device));
m_initialized = true;
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "initialized (sampleRate=%d, channels=%d)", m_sampleRate, m_channels);
return true;
}
void AudioRecorder::shutdown() {
if (!m_initialized) return;
if (m_recording) stopRecording();
if (m_deviceStarted) {
m_deviceStarted = false;
if (m_device) { ma_device_stop(m_device); ma_device_uninit(m_device); }
}
if (m_device) { delete m_device; m_device = nullptr; }
m_initialized = false;
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "shutdown");
}
void AudioRecorder::startRecording() {
if (m_recording) return;
if (!m_initialized) { DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "not initialized"); return; }
m_pcmBuffer.clear();
m_waveformLevels.clear();
m_rmsIdx = 0;
m_elapsedMs = 0;
if (m_compressor) audio_compressor_reset(m_compressor);
ma_context* ctx = SoundManager::instance()->context();
if (!ctx) { DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "no audio context"); return; }
ma_device_config config = ma_device_config_init(ma_device_type_capture);
config.capture.format = ma_format_s16;
config.capture.channels = (ma_uint32)m_channels;
config.sampleRate = (ma_uint32)m_sampleRate;
config.periodSizeInFrames = 480;
config.dataCallback = audioCaptureCallback;
config.pUserData = this;
if (m_captureDeviceIndex >= 0) {
ma_device_info* pCaptureDevices = nullptr;
ma_uint32 captureCount = 0;
ma_result r = ma_context_get_devices(ctx, nullptr, nullptr, &pCaptureDevices, &captureCount);
if (r == MA_SUCCESS && (ma_uint32)m_captureDeviceIndex < captureCount) {
config.capture.pDeviceID = &pCaptureDevices[m_captureDeviceIndex].id;
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "using capture device[%d]: %s", m_captureDeviceIndex,
pCaptureDevices[m_captureDeviceIndex].name);
}
}
ma_result r = ma_device_init(ctx, &config, m_device);
if (r != MA_SUCCESS) {
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "device init failed (%d), trying default", r);
config.capture.pDeviceID = nullptr;
r = ma_device_init(ctx, &config, m_device);
if (r != MA_SUCCESS) {
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "default device init also failed (%d)", r);
return;
}
}
r = ma_device_start(m_device);
if (r != MA_SUCCESS) {
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "device start failed (%d)", r);
ma_device_uninit(m_device);
return;
}
m_recording = true;
m_deviceStarted = true;
m_durationTimer.start();
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "recording started");
emit recordingStarted();
}
void AudioRecorder::stopRecording() {
if (!m_recording) return;
m_durationTimer.stop();
if (m_deviceStarted) {
ma_device_stop(m_device);
ma_device_uninit(m_device);
m_deviceStarted = false;
}
m_recording = false;
if (m_compressor && m_compressorEnabled) audio_compressor_flush(m_compressor);
int duration = m_elapsedMs;
size_t bufSize = (m_compressor && m_compressorEnabled) ? audio_compressor_output_size(m_compressor) : m_pcmBuffer.size();
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "recording stopped, duration=%dms, pcmSamples=%zu, compressor=%d",
duration, bufSize, m_compressorEnabled ? 1 : 0);
emit recordingStopped(duration);
emit durationChanged(0);
}
int AudioRecorder::durationMs() const {
return m_elapsedMs;
}
float AudioRecorder::peakLevel() const {
float v = m_peakLevel;
m_peakLevel = 0.0f;
return v;
}
const int16_t* AudioRecorder::bufferData() const {
if (m_compressor && m_compressorEnabled) return audio_compressor_output(m_compressor);
return m_pcmBuffer.data();
}
size_t AudioRecorder::bufferSize() const {
if (m_compressor && m_compressorEnabled) return audio_compressor_output_size(m_compressor);
return m_pcmBuffer.size();
}
void AudioRecorder::setCompressorEnabled(bool enabled) {
m_compressorEnabled = enabled;
if (m_compressor) audio_compressor_set_enabled(m_compressor, enabled);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "compressor %s", enabled ? "enabled" : "disabled");
}