+/** @brief Called when a NOP completes */
+static void nop_completed(void attribute((unused)) *v) {
+ nop_in_flight = 0;
+}
+
+/** @brief Called from time to time to arrange for a NOP to be sent
+ *
+ * At most one NOP remains in flight at any moment. If the client is not
+ * currently connected then no NOP is sent.
+ */
+static gboolean maybe_send_nop(gpointer attribute((unused)) data) {
+ if(!nop_in_flight && (disorder_eclient_state(client) & DISORDER_CONNECTED)) {
+ nop_in_flight = 1;
+ disorder_eclient_nop(client, nop_completed, 0);
+ }
+ if(rtp_supported) {
+ const int old_state = rtp_is_running;
+ rtp_is_running = rtp_running();
+ if(old_state != rtp_is_running)
+ control_monitor(0);
+ }
+ return TRUE; /* keep call me please */
+}
+
+/** @brief Called when a rtp-address command succeeds */
+static void got_rtp_address(void attribute((unused)) *v,
+ int attribute((unused)) nvec,
+ char attribute((unused)) **vec) {
+ ++suppress_actions;
+ rtp_address_in_flight = 0;
+ rtp_supported = 1;
+ rtp_is_running = rtp_running();
+ control_monitor(0);
+ --suppress_actions;
+}
+
+/** @brief Called when a rtp-address command fails */
+static void no_rtp_address(struct callbackdata attribute((unused)) *cbd,
+ int attribute((unused)) code,
+ const char attribute((unused)) *msg) {
+ ++suppress_actions;
+ rtp_address_in_flight = 0;
+ rtp_supported = 0;
+ rtp_is_running = 0;
+ control_monitor(0);
+ --suppress_actions;
+}
+
+/** @brief Called to check whether RTP play is available */
+static void check_rtp_address(void) {
+ if(!rtp_address_in_flight) {
+ struct callbackdata *const cbd = xmalloc(sizeof *cbd);
+ cbd->onerror = no_rtp_address;
+ disorder_eclient_rtp_address(client, got_rtp_address, cbd);
+ }
+}
+