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. 54
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt
  2. 15
      tools/chatgui-android/libutun_lite/voice_recorder.c

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

@ -183,35 +183,37 @@ fun InputBar(
.background(pttBg, RoundedCornerShape(4.dp)) .background(pttBg, RoundedCornerShape(4.dp))
.pointerInput(hasMicPerm) { .pointerInput(hasMicPerm) {
awaitPointerEventScope { awaitPointerEventScope {
val down = awaitPointerEvent()
val ch = down.changes.firstOrNull() ?: return@awaitPointerEventScope
if (!ch.pressed) return@awaitPointerEventScope
ch.consume()
if (!hasMicPerm) {
permLauncher.launch(Manifest.permission.RECORD_AUDIO)
return@awaitPointerEventScope
}
onPttPressed()
var locked = false
var totalDragY = 0f
var lastY = ch.position.y
while (true) { while (true) {
val event = awaitPointerEvent() val down = awaitPointerEvent()
val change = event.changes.firstOrNull() ?: break val ch = down.changes.firstOrNull() ?: continue
if (change.pressed) { if (!ch.pressed) continue
val dy = change.position.y - lastY ch.consume()
lastY = change.position.y
totalDragY += dy if (!hasMicPerm) {
if (totalDragY < -lockThresholdPx && !locked) { locked = true; onPttLock() } permLauncher.launch(Manifest.permission.RECORD_AUDIO)
change.consume() continue
} else { }
change.consume(); break
onPttPressed()
var locked = false
var totalDragY = 0f
var lastY = ch.position.y
while (true) {
val event = awaitPointerEvent()
val change = event.changes.firstOrNull() ?: break
if (change.pressed) {
val dy = change.position.y - lastY
lastY = change.position.y
totalDragY += dy
if (totalDragY < -lockThresholdPx && !locked) { locked = true; onPttLock() }
change.consume()
} else {
change.consume(); break
}
} }
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