]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
para_play: Compute the current time more accurately.
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 13 Mar 2022 19:49:41 +0000 (20:49 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Mon, 3 Oct 2022 20:42:13 +0000 (22:42 +0200)
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

diff --git a/play.c b/play.c
index b60557244f5755b620c10240c60a2b73e28983e1..262f69ee4dc3d57686904fafb5597e1d955a189d 100644 (file)
--- 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,