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.
+/* returns number of milliseconds */
static long unsigned get_play_time(void)
{
char state = get_playback_state();
static long unsigned get_play_time(void)
{
char state = get_playback_state();
return 0;
if (pt->num_chunks == 0 || pt->seconds == 0)
return 0;
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);
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 += tv2ms(&diff);
- result = PARA_MIN(result, pt->seconds);
+ result = PARA_MIN(result, pt->seconds * 1000);
result = PARA_MAX(result, 0UL);
return result;
}
result = PARA_MAX(result, 0UL);
return result;
}
static int com_pause(__a_unused struct lls_parse_result *lpr)
{
char state;
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;
state = get_playback_state();
pt->playing = false;
if (state != 'P')
return 0;
- seconds = get_play_time();
- 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;
pt->rq = CRT_REPOS;
kill_stream();
return 0;
return ret;
if (pt->playing && !pt->fn.btrn)
return 0;
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;
seconds = PARA_MIN(seconds, (typeof(seconds))pt->seconds - 4);
seconds = PARA_MAX(seconds, 0);
pt->start_chunk = pt->num_chunks * seconds / pt->seconds;
length = pt->seconds;
if (length == 0)
return xasprintf(result, "0:00 [0:00] (0%%/0:00)");
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,
return xasprintf(result, "#%u: %d:%02d [%d:%02d] (%d%%/%d:%02d) %s",
pt->current_file,
seconds / 60,