From a1632855167b61fd987b2bc8f3e6d2ef0972d0ea Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 13 Mar 2022 20:49:41 +0100 Subject: [PATCH] para_play: Compute the current time more accurately. Currently get_play_time() throws away the subsecond part of the timeval and returns a number in seconds. We can improve on that by letting the function return milliseconds instead. However, with milliseconds we must perform multiplications using 64 bit integers to avoid integer overflows. This also affects the pause and play commands, which should now reposition the stream more accurately. It still won't be perfect, though, because play.c has no way of knowing the number of the chunk which is currently being decoded. --- play.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/play.c b/play.c index b6055724..262f69ee 100644 --- a/play.c +++ b/play.c @@ -192,6 +192,7 @@ static char get_playback_state(void) assert(false); }; +/* returns number of milliseconds */ static long unsigned get_play_time(void) { char state = get_playback_state(); @@ -201,16 +202,16 @@ static long unsigned get_play_time(void) return 0; if (pt->num_chunks == 0 || pt->seconds == 0) return 0; - /* where the stream started (in seconds) */ - result = pt->start_chunk * pt->seconds / pt->num_chunks; + /* where the stream started (in milliseconds) */ + result = 1000ULL * pt->start_chunk * pt->seconds / pt->num_chunks; if (pt->wn.btrn) { /* Add the uptime of the writer node */ struct timeval diff = {.tv_sec = 0}, wstime; btr_get_node_start(pt->wn.btrn, &wstime); if (wstime.tv_sec > 0) tv_diff(now, &wstime, &diff); - result += diff.tv_sec; + result += tv2ms(&diff); } - result = PARA_MIN(result, pt->seconds); + result = PARA_MIN(result, pt->seconds * 1000); result = PARA_MAX(result, 0UL); return result; } @@ -840,20 +841,20 @@ EXPORT_PLAY_CMD_HANDLER(play); static int com_pause(__a_unused struct lls_parse_result *lpr) { char state; - long unsigned seconds, ss; + uint64_t ms; + unsigned long cn; /* chunk num */ state = get_playback_state(); pt->playing = false; if (state != 'P') return 0; - seconds = get_play_time(); + ms = get_play_time(); pt->playing = false; - ss = 0; + cn = 0; if (pt->seconds > 0) - ss = seconds * pt->num_chunks / pt->seconds + 1; - ss = PARA_MAX(ss, 0UL); - ss = PARA_MIN(ss, pt->num_chunks); - pt->start_chunk = ss; + cn = ms * pt->num_chunks / pt->seconds / 1000 + 1; + cn = PARA_MIN(cn, pt->num_chunks); + pt->start_chunk = cn; pt->rq = CRT_REPOS; kill_stream(); return 0; @@ -953,7 +954,7 @@ static int com_ff(struct lls_parse_result *lpr) return ret; if (pt->playing && !pt->fn.btrn) return 0; - seconds += get_play_time(); + seconds += (get_play_time() + 500) / 1000; seconds = PARA_MIN(seconds, (typeof(seconds))pt->seconds - 4); seconds = PARA_MAX(seconds, 0); pt->start_chunk = pt->num_chunks * seconds / pt->seconds; @@ -1188,7 +1189,7 @@ static unsigned get_time_string(char **result) length = pt->seconds; if (length == 0) return xasprintf(result, "0:00 [0:00] (0%%/0:00)"); - seconds = get_play_time(); + seconds = (get_play_time() + 500) / 1000; return xasprintf(result, "#%u: %d:%02d [%d:%02d] (%d%%/%d:%02d) %s", pt->current_file, seconds / 60, -- 2.39.5