Browse Source

android: fix voice file creation (mkdir errno logging), PTT while(true)

- voice_recorder: proper mkdir with errno/EEXIST check, errno logged on fopen failure
- MessageBubble: pointerInput wrapped in while(true) so PTT works after first gesture
topo_upd
evgeny 2 months ago
parent
commit
9fca8d5e1f
  1. 8
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt
  2. 15
      tools/chatgui-android/libutun_lite/voice_recorder.c

8
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt

@ -183,14 +183,15 @@ fun InputBar(
.background(pttBg, RoundedCornerShape(4.dp)) .background(pttBg, RoundedCornerShape(4.dp))
.pointerInput(hasMicPerm) { .pointerInput(hasMicPerm) {
awaitPointerEventScope { awaitPointerEventScope {
while (true) {
val down = awaitPointerEvent() val down = awaitPointerEvent()
val ch = down.changes.firstOrNull() ?: return@awaitPointerEventScope val ch = down.changes.firstOrNull() ?: continue
if (!ch.pressed) return@awaitPointerEventScope if (!ch.pressed) continue
ch.consume() ch.consume()
if (!hasMicPerm) { if (!hasMicPerm) {
permLauncher.launch(Manifest.permission.RECORD_AUDIO) permLauncher.launch(Manifest.permission.RECORD_AUDIO)
return@awaitPointerEventScope continue
} }
onPttPressed() onPttPressed()
@ -213,6 +214,7 @@ fun InputBar(
} }
onPttReleased() onPttReleased()
} }
}
}, },
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {

15
tools/chatgui-android/libutun_lite/voice_recorder.c

@ -15,6 +15,7 @@
#include <pthread.h> #include <pthread.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#define MEDIA_BLOCK_MIN (10 * 1024 * 1024) #define MEDIA_BLOCK_MIN (10 * 1024 * 1024)
#define MEDIA_BLOCK_MAX (25 * 1024 * 1024) #define MEDIA_BLOCK_MAX (25 * 1024 * 1024)
@ -263,13 +264,21 @@ int voice_recorder_stop(int* out_duration_ms) {
/* ensure media dir exists */ /* ensure media dir exists */
char media_dir[1024]; char media_dir[1024];
snprintf(media_dir, sizeof(media_dir), "%s/media/%s", g_rec->db_path, g_rec->channel_id); snprintf(media_dir, sizeof(media_dir), "%s/media/%s", g_rec->db_path, g_rec->channel_id);
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "voice_recorder_stop: db_path=%s ch=%s media_dir=%s",
g_rec->db_path, g_rec->channel_id, media_dir);
{ {
char tmp[1024]; size_t off = 0; char tmp[1024]; size_t off = 0;
for (size_t i = 0; media_dir[i] && off < sizeof(tmp) - 1; i++) { for (size_t i = 0; media_dir[i] && off < sizeof(tmp) - 1; i++) {
tmp[off++] = media_dir[i]; tmp[off++] = media_dir[i];
if (media_dir[i] == '/' && off > 1) { tmp[off] = '\0'; mkdir(tmp, 0755); } if (media_dir[i] == '/' && off > 1) {
tmp[off - 1] = '\0';
if (mkdir(tmp, 0755) != 0 && errno != EEXIST)
DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "voice_recorder_stop: mkdir(%s) errno=%d", tmp, errno);
tmp[off - 1] = '/';
} }
mkdir(tmp, 0755); }
if (mkdir(tmp, 0755) != 0 && errno != EEXIST)
DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "voice_recorder_stop: mkdir(%s) errno=%d", tmp, errno);
} }
/* encode to Opus and write blocks */ /* encode to Opus and write blocks */
@ -288,7 +297,7 @@ int voice_recorder_stop(int* out_duration_ms) {
snprintf(temp_path, sizeof(temp_path), "%s/%s_%s_%s.opus", media_dir, dt, basename, suffix); snprintf(temp_path, sizeof(temp_path), "%s/%s_%s_%s.opus", media_dir, dt, basename, suffix);
FILE* of = fopen(temp_path, "wb"); FILE* of = fopen(temp_path, "wb");
if (!of) { if (!of) {
DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "voice_recorder_stop: cannot create %s", temp_path); DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "voice_recorder_stop: cannot create %s (errno=%d)", temp_path, errno);
opus_codec_encoder_destroy(enc); opus_codec_encoder_destroy(enc);
voice_cleanup_locked(g_rec); voice_cleanup_locked(g_rec);
pthread_mutex_unlock(&g_rec->mtx); pthread_mutex_unlock(&g_rec->mtx);

Loading…
Cancel
Save