#include <errno.h>
#include <mpd/client.h>
+#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#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;
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)
{
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);