]> Untitled Git - mpdstream/commitdiff
Test with poll
authorHugo Villeneuve <hvilleneuve@dimonoff.com>
Thu, 2 Apr 2026 14:47:53 +0000 (10:47 -0400)
committerHugo Villeneuve <hvilleneuve@dimonoff.com>
Thu, 2 Apr 2026 14:47:53 +0000 (10:47 -0400)
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
src/main.c

index 08dc18dddddf51171cd821818b98a9121dbbfd16..c65358c483445c07b0da9d4f385432063c18859d 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <errno.h>
 #include <mpd/client.h>
+#include <poll.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -22,6 +23,8 @@
 #define URI_PREFIX_HTTP                "http://"
 #define URI_PREFIX_HTTPS       "https://"
 
+#define MPDSTREAM_POLL_TIMEOUT 10000 // Set to 3000??????????
+
 extern struct options_t options;
 
 static enum mpd_state last_state;
@@ -188,6 +191,78 @@ end:
        return 0;
 }
 
+void mpdstream_monitor_loop(struct pollfd *pfd)
+{
+       int rc;
+
+       while (true) {
+               bool recv_idle = false;
+
+               (void) mpdstream_monitor_status();
+
+               /*
+                * Configure idle event(s):
+                *   MPD_IDLE_PLAYER: state has changed: play, stop, pause, seek, etc
+                */
+               rc = mpd_send_idle_mask(mpdc, MPD_IDLE_PLAYER);
+               if (!rc) {
+                       log_warn("Unable to set idle mask\n");
+                       continue; /* Or abort/break? */
+               }
+
+               /* Wait for event, or timeout. */
+               rc = poll(pfd, 1, MPDSTREAM_POLL_TIMEOUT);
+               if (rc < 0) {
+                       if (errno == EAGAIN) {
+                               log_warn("poll returned EAGAIN\n");
+                       } else if (errno == EINTR) {
+                               /* Signal occurred, continue... */
+                               log_warn("poll returned EINTR\n");
+                       } else {
+                               log_err("poll error: %s\n", strerror(errno));
+                               // return -1;
+                       }
+               } else if (rc == 0) {
+                       /* Timeout. */
+                       log_debug("poll TIMEOUT\n");
+
+                       /*
+                        * Tells MPD to leave the "idle" mode. MPD will then
+                        * respond with a list of events which have occurred
+                        * (which may be empty).
+                        */
+                       mpd_send_noidle(mpdc);
+                       recv_idle = true;
+               } else {
+                       if (pfd->revents & POLLIN) {
+                               /* Data received. */
+                               recv_idle = true;
+                       } else if (pfd->revents & (POLLHUP | POLLERR | POLLNVAL)) {
+                               // The connection is broken
+                               log_err("MPD connection lost or error occurred\n");
+                               return;
+                       }
+               }
+
+               if (recv_idle) {
+                       enum mpd_idle events;
+
+                       /*
+                        * Waits until MPD sends the list of idle events
+                        * and returns it in a bit mask.
+                        */
+                       events = mpd_recv_idle(mpdc, 0);
+                       if (events == 0) {
+                               /* Maybe empty in case of valid timeout. */
+                               (void) mpd_check_for_error();
+                               log_debug("Empty idle event\n");
+                       } else if (events & MPD_IDLE_PLAYER) {
+                               log_debug("MPD_IDLE_PLAYER idle event\n");
+                       }
+               }
+       }
+}
+
 int
 main(int argc, char **argv)
 {
@@ -199,42 +274,33 @@ main(int argc, char **argv)
        if (rc)
                exit(EXIT_FAILURE);
 
-       mpdc = mpd_connection_new(options.host, options.port, 0);
-       if (mpdc == NULL) {
-               log_err("MPD connection error: out of memory\n");
-               exit(EXIT_FAILURE);
-       }
+       while (true) {
+               struct pollfd pfd;
 
-       if (mpd_check_for_error())
-               exit(EXIT_FAILURE);
+               mpdc = mpd_connection_new(options.host, options.port, 0);
+               if (mpdc == NULL) {
+                       log_err("MPD connection error: out of memory\n");
+                       exit(EXIT_FAILURE);
+               }
 
-       log_debug("Waiting for events...\n");
+               if (mpd_check_for_error())
+                       exit(EXIT_FAILURE);
 
-       is_stream = false;
-       song_id = -1;
-       last_state = -1;
+               pfd.fd = mpd_connection_get_fd(mpdc);
+               pfd.events = POLLIN;
 
-       while (true) {
-               enum mpd_idle mask;
+               is_stream = false;
+               song_id = -1;
+               last_state = -1;
 
-               (void) mpdstream_monitor_status();
+               log_debug("Waiting for events...\n");
 
-               /*
-                * Wait for specified event(s):
-                *   MPD_IDLE_PLAYER: state has changed: play, stop, pause, seek, etc
-                */
-               mask = mpd_run_idle_mask(mpdc, MPD_IDLE_PLAYER | MPD_IDLE_QUEUE);
-               if (mask == 0) {
-                       (void) mpd_check_for_error();
-                       log_warn("Empty idle event");
-                       continue; /* Or abort/break? */
-               } else if (mask &= ~MPD_IDLE_QUEUE) {
-                       log_debug("MPD_IDLE_QUEUE idle event");
-                       continue;
-               }
+               /* Should only return in case of connection error(s). */
+               mpdstream_monitor_loop(&pfd);
+
+               mpd_connection_free(mpdc);
        }
 
-       mpd_connection_free(mpdc);
        closelog();
 
        exit(EXIT_SUCCESS);