From 6185869c6da7567a9262cda46559f146b7252e0c Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 1 Oct 2026 18:11:54 +0300 Subject: [PATCH] Use fixed conversation targets for Android media preparation --- .../com/utun/chat/data/ConversationTarget.kt | 8 ++ .../libutun_lite/video_sender.c | 100 ++++-------------- 2 files changed, 30 insertions(+), 78 deletions(-) create mode 100644 tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConversationTarget.kt diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConversationTarget.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConversationTarget.kt new file mode 100644 index 00000000..d6a74ce5 --- /dev/null +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConversationTarget.kt @@ -0,0 +1,8 @@ +package com.utun.chat.data + +/** Адресат фиксируется до записи, выбора файла или фоновой подготовки. */ +sealed class ConversationTarget(val id: String) { + class Channel(id: String) : ConversationTarget(id) + class Pm(id: String) : ConversationTarget(id) + val nativeId: String get() = if (this is Pm) "dm:$id" else id +} diff --git a/tools/chatgui-android/libutun_lite/video_sender.c b/tools/chatgui-android/libutun_lite/video_sender.c index 7bc24e90..95b19c0d 100644 --- a/tools/chatgui-android/libutun_lite/video_sender.c +++ b/tools/chatgui-android/libutun_lite/video_sender.c @@ -1,87 +1,31 @@ -#include "video_sender.h" -#include "instance_lite.h" -#include "../../../lib/debug_config.h" -#include "../../../lib/mem.h" -#include "../../../lib/u_async.h" -#include "../../../src/chat/chat_core.h" +/* Android уже подготовил MP4 и прочитал метаданные в IO; ядро принимает фиксированный target. */ #include -#include #include -#include -#include -#include -#include +#include "../../../lib/mem.h" +#include "../../../lib/debug_config.h" +#include "../../../lib/u_async.h" +#include "../../../src/media_async/attachment_send.h" +#include "video_sender.h" +#include "instance_lite.h" int video_send(const char* channel_id, const char* src_file_path, const char* db_path, int duration_ms, int width, int height) { - if (!channel_id || !src_file_path || !db_path) { - DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "video_send: invalid args"); - return -1; - } - + (void)db_path; struct UASYNC* ua = instance_lite_get_uasync(); - if (!ua) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "video_send: no uasync"); return -1; } - - struct stat st; memset(&st, 0, sizeof(st)); - if (stat(src_file_path, &st) != 0 || st.st_size <= 0) { - DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "video_send: source not found or empty: %s", src_file_path); - return -1; - } - - char path_copy[1024]; - snprintf(path_copy, sizeof(path_copy), "%s", src_file_path); - char* fname = basename(path_copy); - char original_basename[256]; - snprintf(original_basename, sizeof(original_basename), "%s", fname); - char* dot = strrchr(fname, '.'); - if (dot) *dot = '\0'; - - time_t t = time(NULL); - struct tm tm_buf; localtime_r(&t, &tm_buf); - char dt[32]; snprintf(dt, sizeof(dt), "%04d%02d%02d-%02d%02d%02d", - tm_buf.tm_year + 1900, tm_buf.tm_mon + 1, tm_buf.tm_mday, - tm_buf.tm_hour, tm_buf.tm_min, tm_buf.tm_sec); - int rnd = rand() & 0xFFFF; - char suffix[8]; snprintf(suffix, sizeof(suffix), "%04x", rnd); - - /* ensure media dir exists */ - char media_dir[1024]; - snprintf(media_dir, sizeof(media_dir), "%s/media/%s", db_path, channel_id); - { - char tmp[1024]; size_t off = 0; - for (size_t i = 0; media_dir[i] && off < sizeof(tmp) - 1; i++) { - tmp[off++] = media_dir[i]; - if (media_dir[i] == '/' && off > 1) { tmp[off] = '\0'; mkdir(tmp, 0755); } - } - mkdir(tmp, 0755); + if (!channel_id || !src_file_path || !uasync_is_running(ua) || duration_ms <= 0 || duration_ms > 86400000 || + width <= 0 || width > 16384 || height <= 0 || height > 16384 || strlen(src_file_path) >= 1024) { + DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "video send: invalid metadata/target or stopped core"); return -1; } - - char media_file[1024]; - snprintf(media_file, sizeof(media_file), "%s/%s_%s_%s.mp4", media_dir, dt, fname, suffix); - - size_t datalen = strlen(original_basename); - struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + datalen + 1); - if (!req) return -1; - - req->inst = instance_lite_get_instance(); - snprintf(req->channel_id, sizeof(req->channel_id), "%s", channel_id); - snprintf(req->content_type, sizeof(req->content_type), "video/mp4"); - snprintf(req->media_src, sizeof(req->media_src), "%s", src_file_path); - snprintf(req->media_dest, sizeof(req->media_dest), "%s", media_file); - req->media_copy = 1; - req->media_video = 0; - req->duration_ms = duration_ms; - req->width = width; - req->height = height; - req->data = (uint8_t*)(req + 1); - memcpy(req->data, original_basename, datalen); - req->data_len = (uint32_t)datalen; - req->timestamp = 0; - - DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "video_send: ch=%s src=%s dst=%s name=%s size=%lld dur=%d %dx%d", - channel_id, src_file_path, media_file, original_basename, (long long)st.st_size, - duration_ms, width, height); - - uasync_post(ua, chat_core_submit_trampoline, req); + struct attachment_send_req* req = u_calloc(1, sizeof(*req)); + struct posted_task* post = u_calloc(1, sizeof(*post)); + if (!req || !post) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "video send: allocation failed"); u_free(req); u_free(post); return -1; } + req->inst = instance_lite_get_instance(); req->is_dm = !strncmp(channel_id, "dm:", 3); + snprintf(req->target, sizeof(req->target), "%s", channel_id + (req->is_dm ? 3 : 0)); + snprintf(req->source, sizeof(req->source), "%s", src_file_path); + req->info.kind = ATTACHMENT_VIDEO; req->info.duration_ms = (uint32_t)duration_ms; + req->info.width = (uint16_t)width; req->info.height = (uint16_t)height; + req->temporary_source = 1; /* CameraX и picker создают принадлежащие приложению cache-файлы. */ + post->callback = attachment_send_trampoline; post->arg = req; + uasync_post_reserved(ua, post); return 0; }