feat: media_async + media_index modules, media_files table, tests

- media_async: thread-per-task async engine with primitives (sha256, sign, copy, uuid, file_size)
- media_index: media_files DB table with register_async for indexing chunks
- chat_msg: async media submission via register_async, simplified chat_msg_submit fields
- voice_recorder/attachment_sender: write single file (no chunk splitting on caller side)
- inputbar/messagelist: updated to new simplified submit interface
- test_media_async: 4-thread stress test (200K ops / 2 sec, 0 errors)
- test_media_index: 9 cases covering commit edge cases + async flow
- build: Makefile.am, CMakeLists.txt, utun_sources.cmake updated
This commit is contained in:
evgeny committed 2026-07-29 14:15:10 +03:00
1 parent ce5a84da24
commit 65dbfa6813
43 files changed
+1983 -391

No files matched your search

+15 -20
View File
@@ -233,21 +233,15 @@ void InputBar::onPttReleased() {
qPrintable(mediaPath), QDir(mediaPath).exists(), qPrintable(m_channelIdForRecord));
QString fileName = VoiceEncoder::generateFileName();
QString tempPath = mediaPath + "/" + fileName;
QString mediaFile = mediaPath + "/" + fileName;
float durationSec = 0;
int frames = VoiceEncoder::encodeToFile(pcm, pcmSize, 48000, 1, tempPath, durationSec);
int frames = VoiceEncoder::encodeToFile(pcm, pcmSize, 48000, 1, mediaFile, durationSec);
if (frames <= 0) {
QFile::remove(tempPath);
QFile::remove(mediaFile);
return;
}
MediaBlockInfo blk = media_split_to_blocks(tempPath, mediaPath, true);
if (blk.numBlocks <= 0) {
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "InputBar: block split failed");
return;
}
m_voiceFilePath = QString("%1/%2_%3_%4.%5").arg(mediaPath, blk.dt, blk.basename, blk.suffix, blk.ext);
m_voiceFilePath = mediaFile;
const auto& wf = m_recorder->waveformLevels();
QString wfStr = "wf=";
@@ -267,10 +261,9 @@ void InputBar::onPttReleased() {
wfStr += b64[idx];
}
wfStr += QString(";dur=%1;").arg(durationMs);
GUI_INFO("InputBar: voice message ready: dt=%s stem=%s blocks=%d dur=%.1fs",
qPrintable(blk.dt), qPrintable(blk.basename), blk.numBlocks, durationSec);
emit sendVoiceMessage(blk.dt, blk.basename, blk.suffix, blk.ext,
blk.numBlocks, blk.blockSize, durationMs, wfStr);
GUI_INFO("InputBar: voice message ready: file=%s dur=%.1fs",
qPrintable(mediaFile), durationSec);
emit sendVoiceMessage(mediaFile, mediaFile, durationMs, wfStr);
}
void InputBar::onAttachClicked() {
@@ -285,13 +278,15 @@ void InputBar::onAttachClicked() {
VoiceEncoder::ensureMediaDir(mediaPath);
QDir().mkpath(mediaPath);
MediaBlockInfo blk = media_split_to_blocks(srcPath, mediaPath, false);
if (blk.numBlocks <= 0) { DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "InputBar::onAttachClicked: split failed"); return; }
QDateTime now = QDateTime::currentDateTime();
QString ts = now.toString("yyyyMMdd-HHmmss");
int rnd = rand() & 0xFFFF;
QString destPath = QString("%1/%2_%3_%4.%5")
.arg(mediaPath, ts).arg(fi.completeBaseName()).arg(rnd, 4, 16, QChar('0')).arg(fi.suffix().isEmpty() ? "bin" : fi.suffix());
GUI_INFO("InputBar::onAttachClicked: file=%s dt=%s blocks=%d",
qPrintable(fi.fileName()), qPrintable(blk.dt), blk.numBlocks);
emit sendFileAttachment(blk.dt, blk.basename, blk.suffix, blk.ext,
blk.numBlocks, blk.blockSize, fi.fileName());
GUI_INFO("InputBar::onAttachClicked: src=%s dest=%s",
qPrintable(srcPath), qPrintable(destPath));
emit sendFileAttachment(srcPath, destPath, fi.fileName());
}
void InputBar::resizeEvent(QResizeEvent* event) {