Commit Graph
256 Commits
Author SHA1 Message Date
evgeny b6f9ebc8a8 chatgui: TCP link status via stcp_link_is_ready 2026-08-03 21:04:46 +03:00
evgeny 8023f6ee70 stcp: separate v4/v6 sockets, protocol byte in chat addr format, error on bind fail
- stcp_server_create: support AF_INET and AF_INET6 V6ONLY=1 (no dual-stack)
- Add listen_family to stcp_link_config
- init_sockets: return error (not partial) on any bind failure
- add chat_core_sync_my_addresses() call at chatgui startup
- collect_my_addrs: add proto byte (1=UDP, 2=TCP) to binary format
- chat_sync.c JOIN/WELCOME/PEER_UPSERT: read proto byte, write protocol column
- member_sync.c: read proto byte, dynamic protocol bind
- topo_node.c: debug logs for nodeinfo changed detection
- node_config.cpp: type=public for all servers
2026-08-03 20:35:46 +03:00
evgeny 3deaa0eabe stcp: multiple servers support via linked list in UTUN_INSTANCE
- Replace instance->stcp_server (single pointer) with stcp_servers linked list
- Add stcp_server_list_add/destroy_all/count API in stcp_link.h/c
- Fix port extraction for both AF_INET and AF_INET6 in init_sockets
- Filter out 0.0.0.0 and [::] addresses in chat_profile.c TCP address sync
- Add type=public to servers in node_config.cpp saveFull()
2026-08-03 19:39:50 +03:00
evgeny e1e54df4f4 fix: invite не затирает имя узла, имя читается из member_sync peers.userinfo
- conn_mgr_core.c: убрана запись node_name из cm_handle_invite_info_resp
- topo_node_sqlite.c: name в nodes не перезаписывается пустой строкой
- android_jni_bridge.c: bridge_get_node_name читает peers_<ch>.userinfo если nodes.name пуст
2026-08-03 18:50:11 +03:00
evgeny c2191aad3b chat: user-friendly INFO logs for invite/connect flow
- chat_sync.c: invite entry, JOINED/TIMEOUT messages
- conn_mgr_core.c: invite start (addrs+udp+tcp), NCD UP/DOWN/TIMEOUT,
  TCP connect/ready/close, membership check send/receive/confirm/deny,
  overall timeout
- node_conn_direct.c: NCD event names instead of numbers
2026-08-02 20:32:01 +03:00
evgeny 50156e12af android: member list screen + link status dots, ipv6 autoconnect fixes
Android chatgui:
- New MemberListScreen with member list, detail card, edit dialog
- Link status dots (green/red/grey) per address in detail card (1s poll)
- Self-node name coloured green
- ChatScreen: people icon in TopAppBar

IPv6 autoconnect fixes (3 bugs in conn_mgr/topo):
- topo_node_sqlite_node_load: load v6 addresses from DB
- topo_node_registry_store: merge v6_addrs into existing node
- cm_sock_v6_classify: wildcard [::] treated as CM_V6_DIR
- cm_add_v6_link: htons(port) was missing

Memory fixes:
- strdup→u_strdup in bridge (7 instances)
- u_realloc cap update before success check (3 instances)
- char sql[256]→[512] for truncated SELECT

Chat member hash now includes addresses for change detection

Linux chatgui:
- Link status dots in AccountList detail panel (1s poll)
- Self-node name in green in member list
2026-08-01 23:40:58 +03:00
evgeny af3e2ee869 chatgui: IPv4+IPv6 dual-stack listen by default
- Default config creates [server:lan] (0.0.0.0) + [server:lan6] ([::])
- Network settings save also writes [server:lan6] section
- Sets IPV6_V6ONLY=1 on IPv6 sockets to avoid conflict with IPv4
- interface_addr for [::] bind prefers permanent IPv6 over temporary
2026-08-01 19:52:28 +03:00
evgeny 51d6c782ac voice playback: miniaudio cursor ground truth + EMA smooth decay
- SoundManager: add currentPcmCursor()/isCurrentPcmPlaying() via ma_sound_get_cursor_in_pcm_frames / ma_sound_is_playing
- messagedelegate: replace wall-clock position tracking with real miniaudio cursor, remove 200ms hardcoded delay
- messagedelegate: end-of-playback detection via isCurrentPcmPlaying() instead of wall-clock comparison (was killing audio ~200ms early)
- messagedelegate: EMA smoothing of displayFrac/displayElapsed (0.15 factor, 16ms timer)
- messagedelegate: timer continues after audio stops to animate EMA decay to 0 (not mouse-move dependent)
- media_delivery: download progress callback, Ed25519 sig verify, author fallback, content hash check
- conn_mgr: already-connected returns OK with callback instead of error
- chatgui: voice download-pending auto-play, file download progress bar, media bar colors
2026-07-31 00:17:03 +03:00
evgeny 70797f921e feature: media auto-download + manual download + UI download state indication (Android + desktop)
C-layer:
- chat_event.h: CHAT_EVT_ATTACHMENT_DOWNLOADED (14)
- chat_msg.c: fixed md_auto_download (non-NULL done_cb, correct media_base from db_path, use chat_setting for autoload checks)
- chat_msg.c: added chat_core_attachment_download + trampoline for manual download
- chat_core.h: exported attachment_dl_req + trampoline

Android (Kotlin + JNI):
- Message: downloadState field (parse from localAttrs)
- ChatRepository: parse localAttrs for download state
- NativeLib: attachmentDownload() JNI
- MessageBubble: FileBubble with download status icon + tap-to-download
- ChatViewModel: downloadAttachment() + CHAT_EVT_ATTACHMENT_DOWNLOADED handler
- ChatScreen: wire onDownloadFile handler
- android_jni_bridge: utun_bridge_attachment_download + JNI + localAttrs in JSON

Desktop (Qt/C++):
- messagedelegate.h: MsgFileDownloadStateRole, MsgChannelIdRole
- messagelist.cpp: parse localAttrs for file download state
- messagedelegate.cpp: FileBubble with download icon/text + click handler via chat_core_attachment_download_trampoline
- gui_bridge.h: GUI_EVT_ATTACHMENT_DOWNLOADED (14) + callback typedef
- gui_bridge_impl.cpp: event dispatch + setter
- mainwindow.cpp: callback registration -> refresh message list
2026-07-30 00:01:38 +03:00
evgeny b8920cf483 chat_settings: [chat] config section + live sync + fix test segfault
- New chat_setting.c/h: unified chat settings API (int/str getters)
- Config parser supports [chat] section, calls chat_setting_set per key
- chat_core exposes chat_core_set_setting / trampoline for GUI bridge
- chatgui: AudioDevice + Storage pages persist to [chat] config + live apply
- chatgui-android: ConfigProvider, NativeLib, headless handle chat settings
- MessageList: 200 msg limit, fixed saveChannelState via trampoline
- test_media_delivery_full: fix segfault at shutdown (mon() timer vs freed conns)
2026-07-29 21:18:49 +03:00
evgeny 65dbfa6813 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
2026-07-29 14:15:10 +03:00
evgeny 4ffa59d968 unify voice waveform format: base64 wf={100chars};dur={ms}; for both desktop and Android
- inputbar.cpp: CSV waveform → base64 log-scale (same as voice_recorder.c)
- messagelist.cpp: sendVoiceMessage removes displayName|dur_sec| prefix, uses wfStr directly
  setVoiceMessageRoles: decodes new format wf={base64};dur={ms};|... from data field
- messagedelegate.cpp: waveform values now pre-normalized 0..1, no log recalculation needed
- VoiceEncoder: no changes needed (was already compatible)

Both platforms now store identical format in chat_msg_submit.data:
  wf=ABCDef...100chars;dur=NNNN;|file_size|block_size|num_blocks|sigs_hex
2026-07-29 01:43:11 +03:00
evgeny 3c75c8f687 icons: replace emoji text with PNG resources + add media_dir debug logs 2026-07-29 01:27:23 +03:00
evgeny 1dac0b8c81 unify compressor: remove C++ duplicate audiocompressor, use lib/audio_compressor.c in chatgui 2026-07-29 00:52:05 +03:00
evgeny e751e6ee69 android: voice messages + attachments architecture plan, build fixes 2026-07-28 23:07:23 +03:00
evgeny 064bed06f2 android: fix key regeneration, Clear DB, uasync eventfd, udp log from config
- jni_on_event: fix JNI_EDETACHED — AttachCurrentThread/DetachCurrentThread
- u_async.c: pipe→eventfd for reliable cross-thread wakeup
  add process_posted_tasks in poll() path, fix EINTR (saved_errno)
- bridge_debug_hook: keep udp_log_write, remove mutex from udp_log
- memory_pool.c: alloc/free logs INFO→DEBUG (reduce spam)
- instance_lite.c: chat_event_set_handler before ensure_keys,
  KEYS_GENERATED events, fchmod 0600 on keys.conf,
  UDP log from config [log_udp] section, regenerate_trampoline
- config_parser: parse [log_udp] ip/port
- NativeLib.kt: remove callbacksSet, simplify init/stop/destroy
- ChatViewModel.kt: unified event callback in init, pubKey StateFlow,
  requestRegenerateKeys, clearState fix
- SettingsScreen.kt: pubKey.collectAsState(), Clear DB via restart()
- HeadlessService.kt: remove setUdpLogTarget (now from config)
- android_udp_log.c: simplified — no mutex, buffer+send+timer in one thread
- utun_instance.c: NULL-check tcp_connections before destroy
- chat_event.h: +CHAT_EVT_KEYS_GENERATED 11, -NODE_CHANGED
- logreceiver: UDP log receiver tool
2026-07-28 16:29:33 +03:00
evgeny d0cca27edd invite: add proto field (UDP/TCP/BOTH) to invite link binary format
Format per v4 addr: family(1) + socketId(1) + proto(1) + addr(4) + port(2) = 9 bytes (was 8)
Proto values: 0x01=UDP, 0x02=TCP, 0x03=BOTH
Affects: invite_link_c.h/c (Android), invite_link.h/cpp (desktop), chat_sync.c, conn_mgr.c, joindialog.cpp, utun_node.cpp
2026-07-28 00:34:07 +03:00
Evgeny 2d53b3120f ffmpeg: add build script and CMake integration 2026-07-27 17:59:07 +03:00
Evgeny d497a8dc92 media_blocks: fix missing QJsonArray include 2026-07-27 17:16:02 +03:00
Evgeny d4a396f888 media: Ed25519-подписи блоков, local_attrs, MediaBlockReader, файловые вложения 2026-07-27 17:09:31 +03:00
Evgeny 6b765de5cc feat: voice playback delay compensation + waveform click-to-seek 2026-07-27 14:53:53 +03:00
Evgeny da953c6c7a fix: mic test level bar dynamic color too 2026-07-27 14:25:47 +03:00
Evgeny f08b63466c исправлены include-пути в chatgui GUI-файлах и utun_node.cpp после переноса chat в src/chat/ 2026-07-27 13:35:40 +03:00
Evgeny ed6132fcda перенос chat-логики из chatgui/transport в src/chat/
- Создан src/chat/ с chat_event.h/c — система нотификаций
- Перенесены chat_core, chat_msg, chat_channel, chat_profile, chat_status
- Перенесены chat_sync, member_sync, merkle_sync, db_sync
- gui_bridge_post() заменён на chat_event_post() с возможностью регистрации обработчика
- chat_event_set_handler() — chatgui регистрирует мост в gui_bridge
- Без обработчика: события логируются через DEBUG_DEBUG + log_dump
- chat интегрирован в utun_instance.c (при db_path в конфиге)
- Обновлены include-пути, Makefile.am, CMakeLists.txt
- Из chatgui удалены старые transport/ файлы, обновлён utun_node.cpp
2026-07-27 12:58:33 +03:00
Evgeny 4595052b5b fix: level bar dynamic color — red only above 85% 2026-07-27 12:20:06 +03:00
Evgeny d5b97ff104 fix: immediate compressor apply + dead code removal + qDebug→DEBUG_* conversion 2026-07-27 12:11:50 +03:00
Evgeny 5ec1cb78be fix: use DEBUG_* macros instead of qDebug in AudioRecorder/AudioCompressor 2026-07-27 11:56:49 +03:00
Evgeny f1b599f0c0 feat: voice compressor with RMS+peak leveling, sliding window envelope, rate-limited gain 2026-07-27 11:24:47 +03:00
Evgeny 7004b110ae feat: mic level bar in recording overlay
- InputBar: QProgressBar with gradient (green→yellow→red) in recording overlay
- updateRecordingUI: computes dB from peakLevel, updates bar every 100ms
- showRecordOverlay: resets bar to 0 on new recording
2026-07-27 09:35:16 +03:00
Evgeny 5593bfdc0c fix: logarithmic waveform scale + visible idle color + duration display
- Waveform bars: linear→logarithmic (dB mapping -60..0dB)
- Colors: idle gray visible (130 alpha), played blue, unplayed dim blue
- Min bar height: 1→2px
- Duration: fallback to MsgVoiceDurationRole when not playing (was 0:00/0:00)
- Debug log: wfN, width, first value, dB, barH
2026-07-27 09:19:34 +03:00
Evgeny e050f3f1f9 fix: waveform repaint via viewport()->update() instead of activeWindow()
- Timer now calls s_voiceView->viewport()->update() for correct delegate repaint
- s_voiceView captured from option.widget in paint() voice section
- Previously activeWindow()->update() didn't reach QListView viewport
2026-07-27 09:13:33 +03:00
Evgeny 05c7b4d47e feat: waveform display + 3px progress bar in bubble + sliding window RMS
- AudioRecorder: sliding window RMS (avg 5 frames), waveformLevels() getter
- InputBar: downsample RMS to 100 samples, encode as wf0,wf1,... in textData
- MessageList: parse 3rd pipe-separated field as waveform, store in MsgVoiceWaveformRole
- MessageDelegate: new voice layout (16px play btn + 25px waveform + 3px progress bar)
- MessageDelegate: waveform bars colored by progress (blue before, gray after)
- Progress bar integrated at bottom of waveform area as colored fill
2026-07-27 09:07:14 +03:00
Evgeny 70a0a70b88 fix: crash — no delete of ma_sound/ma_audio_buffer during playback
- stopCurrentPcm(): only ma_sound_stop, no delete/uninit in runtime
- playRawPcm(): just stop old sound, create new objects (old ones leak until shutdown)
- shutdown(): cleanup accumulated ma_sound + ma_audio_buffer after engine uninit
- root cause: deleting audio objects from GUI thread while miniaudio worker reads them
2026-07-27 08:16:37 +03:00
Evgeny 8bd4a7218c fix: true pause/resume with position preservation
- SoundManager: pauseCurrentPcm()/resumeCurrentPcm() — stop/start without destroy
- VoicePlayState: added paused/pausedPosSec fields
- editorEvent: 3-state logic — playing→pause, paused→resume, stopped→new
- Different file click: stops old with full cleanup, plays new from start
- Timer: skips paused items, full cleanup on auto-complete
2026-07-27 08:07:19 +03:00
Evgeny 830f729f52 fix: pause support + old message skip + stopCurrentPcm
- SoundManager: added stopCurrentPcm() for pause/stop of PCM playback
- messagedelegate: call stopCurrentPcm on pause, new play, and timer complete
- messagelist: skip old double-nested JSON messages (raw starts with '{')
- sound_manager.h: void* for ma_audio_buffer to avoid header dependency
2026-07-27 00:38:15 +03:00
Evgeny 2687c3ed82 fix: play button not responding + debug logging to log file
- chatview: QListView::mousePressEvent(event) instead of event->accept()
  (Qt needs base class press to set pressedIndex for editorEvent to fire)
- messagedelegate: GUI_DEBUG replaces qDebug (writes to log file)
- voiceplayback: DEBUG_DEBUG/DEBUG_WARN + debug_config.h include
- voicemessageencoder: same debug migration
- inputbar: GUI_INFO replaces qDebug
- messagelist: DEBUG_DEBUG/DEBUG_WARN replaces qDebug/qWarning
2026-07-27 00:30:09 +03:00
Evgeny 01012675d0 fix: voice playback coordinate bug + debug logging + device name encoding
- messagedelegate: editorEvent now adjusts me->pos() by option.rect.topLeft()
- voiceplayback: enhanced debug logging for file open/decode/play
- messagelist: debug voice file path + exists check
- inputbar: debug mediaDir path on record
- sound_manager: debug in playRawPcm, decodeDeviceName() for mixed encodings
- voiceencoder: debug file write path
2026-07-27 00:22:00 +03:00
Evgeny 324d285145 fix: voice message display and playback — complete flow
- db_manager: getMessagesSince() now parses m.contentType from JSON (was missing)
- messagelist: setVoiceMessageRoles uses data directly as payload, not re-parsed as JSON
  (data is already the 'd' field value extracted by db_manager)
2026-07-27 00:13:58 +03:00
Evgeny fd3b125ecb fix: voice message JSON double-nesting, '{' display
- req->data now stores 'filename|duration' instead of full nested JSON
- chat_core_submit_message builds the JSON with d='filename|duration'
- setVoiceMessageRoles splits d field by '|' to extract filename and duration
2026-07-26 22:16:09 +03:00
Evgeny ca9d1384f2 fix: PCM copy, device name encoding, double shutdown
- playRawPcm: ma_audio_buffer_init_copy instead of ma_audio_buffer_ref (copies PCM)
- enumerateDevices: fromLocal8Bit instead of fromUtf8 for device names
- AudioRecorder: m_deviceStarted flag prevents double ma_device_uninit
- stopMicTest: delete instead of deleteLater to avoid deferred double shutdown
2026-07-26 22:01:46 +03:00
Evgeny a4ae1c6b41 fix: RMS mic level, 25ms timer, speaker test, overlay recording indicator
- AudioRecorder: peak replaced with RMS (sqrt mean of squares)
- AudioDeviceSettings: level meter timer 100ms -> 25ms
- SoundManager: playRawPcm uses ma_audio_buffer_ref instead of ma_decoder (fixes speaker test)
- InputBar: recording overlay positioned over text input, no layout shift
- messagelist: removed old recording indicator widget
2026-07-26 21:27:57 +03:00
Evgeny 850a260aac fix: voice message display, playback, recording UI, audio settings
- messagelist: parse content_type from JSON when DB column is empty
- messagelist: recording indicator (red dot + timer + cancel button)
- messagedelegate: editorEvent for play/pause toggle + progress bar
- messagedelegate: VoicePlayState tracking with QTimer
- InputBar: proper recordingContext (mediaDir + channelId)
- DbManager: dbPath() for media directory resolution
- AudioRecorder: peakLevel() for mic level meter
- VoiceEncoder: codec quality presets (Low/Standard/High)
- audiodevicesettingspage: Default device option first
- audiodevicesettingspage: mic level meter + test microphone
- audiodevicesettingspage: test speaker button
- audiodevicesettingspage: codec preset combo (Low/Standard/High)
- mainwindow: load opus_codec_preset from ui_state on startup
2026-07-26 21:19:29 +03:00
Evgeny 4fde0b0325 feat: integrate Opus codec into lib/libopus + voice messages in chatgui
- Add lib/libopus/ (opus v1.6.1 embedded source: CELT 18 .c, SILK 77 .c, SILK float 28 .c, OPUS core 14 .c)
- Add lib/opus_codec.h/.c (wrapper: encoder, decoder, raw PCM int16)
- Add tests/test_opus_codec.c (7 tests: silence, sine, compression, PLC, null, defaults, multi-frame)
- chatgui: AudioRecorder (miniaudio capture, 48kHz mono)
- chatgui: VoiceEncoder (PCM→Opus file with custom container)
- chatgui: VoicePlayer (Opus→PCM playback via SoundManager)
- chatgui: PTT button in InputBar, voice message send/receive in MessageList
- chatgui: AudioDeviceSettingsPage (device selection, persisted in ui_state)
- chatgui: MessageDelegate voice message rendering (play button + duration)
- Update autotools: configure.ac, Makefile.am, src/Makefile.am, tests/Makefile.am
- Update CMake: chatgui CMakeLists.txt, libutun CMakeLists.txt (link libopus_internal.a)
2026-07-26 20:34:38 +03:00
Evgeny 4a23593020 member_sync: add merkle_sync_broadcast relay to other SYNCED sessions 2026-07-26 18:44:45 +03:00
Evgeny ef1e064bdc merkle_sync: broadcast relay for star topology + all 6 test stages pass
- Replace active/synced with sess_state (SESS_SYNCING/SESS_SYNCED)
- Add merkle_sync_broadcast() API for relaying changes to SYNCED peers
- apply_items callback now receives from_peer parameter
- _handle_hashes: reset pending_count on session reuse (overwrite fix)
- _handle_batch: send broadcast to synced sessions on new items
- Test Stage 5: sequential B->A + C->A with relay (no 3rd sync needed)
- Test Stage 6: cancel + start_overwrite pass
- Fix _wait_for: remove i_phase global timeout dependency
2026-07-26 18:20:10 +03:00
Evgeny a1ecab997e merkle_sync: fix 4 protocol bugs + add test suite (Stages 1-4)
- g_merkle singleton → per-instance msync (utun_instance.h)
- level_prefix: off-by-one shift (63→64)
- _handle_hashes: differs |= for shared buckets with different hashes
- _handle_batch: sub_pl double-level-offset (next_lvl→lvl)
- pending[] array replaces pending_requests counter
- member_sync: mask_shift 63→64 alignment
- test_merkle_sync.c: prefix arithmetic, tree building, 2-instance integration, randomized 50-iter sync
2026-07-26 17:42:27 +03:00
Evgeny 0e11d858e8 chatgui: fix all animations showing the same TGS (rlottie model cache key collision)
lottie_animation_from_data uses 'key' as a cache key for parsed models.
All LottieIcon instances were created with key="", causing rlottie's
model cache to return the first loaded animation for all subsequent
requests. Only visible on Windows where rlottie cache is enabled by
default.

Fix: pass unique animPath as key to each LottieIcon constructor.
Also replaced fprintf(stderr) diag with GUI_INFO logging via
AnimTimer::logRegisteredIcons() in debug_ui.h.
2026-07-26 15:18:59 +03:00
Evgeny 49da899964 chatgui: channel sorting by name or last message time with preview
- Add last_msg_at column to channels table
- Update last_msg_at on every message insert (send/receive)
- Parameterize getChannels() with ChannelSortMode enum (Alphabetical/Recent)
- Add getChannelLastMessage() for preview text in channel list
- Add sorting combo to Profile settings page (stored in ui_state)
- Reload channels on message receive when sort is recent
2026-07-26 11:08:59 +03:00
Evgeny 332df381d1 chatgui: propagate local nick changes to message authors via MsgAuthorNodeIdRole + reloadLocalNicks 2026-07-26 10:11:31 +03:00
Evgeny 22db84816e chatgui: add local_nick TEXT to peers table DDL, remove ALTER TABLE hacks 2026-07-26 09:45:00 +03:00