From: Andre Noll Date: Sun, 13 Mar 2022 19:49:41 +0000 (+0100) Subject: para_play: Compute the current time more accurately. X-Git-Tag: v0.7.2~27 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=a1632855167b61fd987b2bc8f3e6d2ef0972d0ea;p=paraslash.git 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. --- 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,