diff options
| author | Přemysl Janouch <p.janouch@gmail.com> | 2016-10-04 18:33:14 +0200 | 
|---|---|---|
| committer | Přemysl Janouch <p.janouch@gmail.com> | 2016-10-04 18:33:14 +0200 | 
| commit | 859c9d273793dd4d28ae67b9008be333b3aa68cb (patch) | |
| tree | e13490b4ca2866bddb832435dab67d8309655df5 | |
| parent | 87f5eddea0bcc4645be09acc64f2253cb1a9c3cb (diff) | |
| download | nncmpp-859c9d273793dd4d28ae67b9008be333b3aa68cb.tar.gz nncmpp-859c9d273793dd4d28ae67b9008be333b3aa68cb.tar.xz nncmpp-859c9d273793dd4d28ae67b9008be333b3aa68cb.zip | |
Enhance time tracking
Now with eliminated timer drift.
| -rw-r--r-- | nncmpp.c | 44 | 
1 files changed, 30 insertions, 14 deletions
| @@ -130,6 +130,14 @@ update_curses_terminal_size (void)  #endif  // HAVE_RESIZETERM && TIOCGWINSZ  } +static int64_t +clock_msec (clockid_t clock) +{ +	struct timespec tp; +	hard_assert (clock_gettime (clock, &tp) != -1); +	return (int64_t) tp.tv_sec * 1000 + (int64_t) tp.tv_nsec / 1000000; +} +  // --- Application -------------------------------------------------------------  // Function names are prefixed mostly because of curses which clutters the @@ -215,6 +223,8 @@ static struct app_context  	struct str_map song_info;           ///< Current song info  	struct poller_timer elapsed_event;  ///< Seconds elapsed event +	int64_t elapsed_since;              ///< Time of the next tick +  	// TODO: initialize these to -1  	int song_elapsed;                   ///< Song elapsed in seconds  	int song_duration;                  ///< Song duration in seconds @@ -1584,8 +1594,12 @@ mpd_on_info_response (const struct mpd_response *response,  	// Note that we may receive a "time" field twice, however the right one  	// wins here due to the order we send the commands in + +	// The contents of these values overlap and we try to get what we can +	// FIXME: don't change the values, for fuck's sake  	char *time     = str_map_find (&map, "time");  	char *duration = str_map_find (&map, "duration"); +	char *elapsed  = str_map_find (&map, "elapsed");  	if (time)  	{  		char *colon = strchr (time, ':'); @@ -1602,8 +1616,10 @@ mpd_on_info_response (const struct mpd_response *response,  	if (duration && xstrtoul (&tmp, duration, 10))  		g_ctx.song_duration = tmp; -	// TODO: use "time" as a fallback (no milliseconds there) -	char *period, *elapsed = str_map_find (&map, "elapsed"); +	// We could also just poll the server each half a second but let's not +	int msec_past_second = 0; + +	char *period;  	if (elapsed && (period = strchr (elapsed, '.')))  	{  		// For some reason this is much more precise @@ -1613,12 +1629,12 @@ mpd_on_info_response (const struct mpd_response *response,  		if (g_ctx.state == PLAYER_PLAYING  		 && xstrtoul (&tmp, period, 10)) -		{ -			// TODO: initialize the timer and create a callback -			poller_timer_set (&g_ctx.elapsed_event, 1000 - tmp); -		} +			msec_past_second = tmp;  	} +	poller_timer_set (&g_ctx.elapsed_event, 1000 - msec_past_second); +	g_ctx.elapsed_since = clock_msec (CLOCK_BEST) - msec_past_second; +	// The server sends -1 when nothing is being played right now  	char *volume = str_map_find (&map, "volume");  	if (volume && xstrtoul (&tmp, volume, 10))  		g_ctx.volume = tmp; @@ -1631,10 +1647,14 @@ static void  mpd_on_tick (void *user_data)  {  	(void) user_data; -	// FIXME: this is doomed to drift unless we use POSIX CLOCK_MONOTONIC -	poller_timer_set (&g_ctx.elapsed_event, 1000); +	int64_t diff_msec = clock_msec (CLOCK_BEST) - g_ctx.elapsed_since; +	int elapsed_sec = diff_msec / 1000; +	int elapsed_msec = diff_msec % 1000; + +	g_ctx.song_elapsed += elapsed_sec; +	g_ctx.elapsed_since += elapsed_sec * 1000; +	poller_timer_set (&g_ctx.elapsed_event, 1000 - elapsed_msec); -	g_ctx.song_elapsed++;  	// TODO: try to be more efficient in the redrawing procedures  	app_redraw ();  } @@ -1891,11 +1911,7 @@ debug_tab_push (const char *message, chtype attrs)  		&g_debug_tab.items[g_debug_tab.super.item_count++];  	item->text = xstrdup (message);  	item->attrs = attrs; - -	struct timespec tp; -	hard_assert (clock_gettime (CLOCK_REALTIME, &tp) != -1); -	item->timestamp = (int64_t) tp.tv_sec * 1000 -		+ (int64_t) tp.tv_nsec / 1000000; +	item->timestamp = clock_msec (CLOCK_REALTIME);  	app_redraw_view ();  } | 
