From 6c2ae2f6bb57554e0d153f5bf8b246dfefef162b Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch
Date: Sun, 18 Oct 2020 06:55:03 +0200 Subject: Give up and implement elapsed time polling Playback may sometimes stall but it won't produce any events. This popular workaround likes to jump around, though. It might be a good idea to use some kind of hybrid approach. Therefore this is disabled by default so far. Updates #1 --- nncmpp.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/nncmpp.c b/nncmpp.c index 51ba3b9..859f292 100644 --- a/nncmpp.c +++ b/nncmpp.c @@ -610,6 +610,7 @@ static struct app_context struct poller_timer elapsed_event; ///< Seconds elapsed event int64_t elapsed_since; ///< Time of the last tick + bool elapsed_poll; ///< Poll MPD for the elapsed time? // TODO: initialize these to -1 int song; ///< Current song index @@ -692,6 +693,13 @@ tab_selection_range (struct tab *self) // --- Configuration ----------------------------------------------------------- +static void +on_poll_elapsed_time_changed (struct config_item *item) +{ + // This is only set once, on application startup + g.elapsed_poll = item->value.boolean; +} + static struct config_schema g_config_settings[] = { { .name = "address", @@ -704,6 +712,11 @@ static struct config_schema g_config_settings[] = { .name = "root", .comment = "Where all the files MPD is playing are located", .type = CONFIG_ITEM_STRING }, + { .name = "poll_elapsed_time", + .comment = "Whether to actively poll MPD for the elapsed time", + .type = CONFIG_ITEM_BOOLEAN, + .on_change = on_poll_elapsed_time_changed, + .default_ = "off" }, {} }; @@ -3406,12 +3419,19 @@ mpd_update_playback_state (void) mpd_read_time (duration, &g.song_duration, NULL); strv_free (&fields); - // We could also just poll the server each half a second but let's not poller_timer_reset (&g.elapsed_event); if (g.state == PLAYER_PLAYING) { + int until_next = 1000 - msec_past_second; + + // We could make use of "until_next", however this might create + // an intensive busy loop when playback stalls (typically because of + // some network issues). Half a second will work reasonably well. + if (g.elapsed_poll) + until_next = 500; + // Set a timer for when the next round second of playback happens - poller_timer_set (&g.elapsed_event, 1000 - msec_past_second); + poller_timer_set (&g.elapsed_event, until_next); // Remember when the last round second was, relative to monotonic time g.elapsed_since = clock_msec (CLOCK_BEST) - msec_past_second; } @@ -3539,7 +3559,7 @@ mpd_on_info_response (const struct mpd_response *response, } static void -mpd_on_tick (void *user_data) +mpd_on_elapsed_time_tick (void *user_data) { (void) user_data; @@ -3572,6 +3592,15 @@ mpd_request_info (void) mpd_client_idle (c, 0); } +static void +mpd_on_elapsed_time_tick_poll (void *user_data) +{ + (void) user_data; + + // As soon as the reply arrives, we (may) set the timer again + mpd_request_info (); +} + static void mpd_on_events (unsigned subsystems, void *user_data) { @@ -3923,7 +3952,9 @@ app_init_poller_events (void) poller_timer_set (&g.connect_event, 0); g.elapsed_event = poller_timer_make (&g.poller); - g.elapsed_event.dispatcher = mpd_on_tick; + g.elapsed_event.dispatcher = g.elapsed_poll + ? mpd_on_elapsed_time_tick_poll + : mpd_on_elapsed_time_tick; g.refresh_event = poller_idle_make (&g.poller); g.refresh_event.dispatcher = app_on_refresh; -- cgit v1.2.3-70-g09d2