From a6f63f6cb2df7c6dd89bf928bd307f65f2b1e78f Mon Sep 17 00:00:00 2001 From: jcorporation Date: Thu, 9 Aug 2018 22:15:00 +0100 Subject: [PATCH] Feat: first code for mpd idle api --- src/mpd_client.c | 86 +++++++++++++++++++++++++++++++++++++++++++----- src/mpd_client.h | 4 ++- src/mympd.c | 11 +++---- 3 files changed, 85 insertions(+), 16 deletions(-) diff --git a/src/mpd_client.c b/src/mpd_client.c index 2401bb8..06a61b9 100644 --- a/src/mpd_client.c +++ b/src/mpd_client.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -73,7 +74,16 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { if (cmd_id == -1) cmd_id = get_cmd_id("MPD_API_UNKNOWN"); - + + mpd_send_noidle(mpd.conn); + mpd_response_finish(mpd.conn); +/* + enum mpd_idle idle_event; + mpd_connection_set_timeout(mpd.conn, 1); + idle_event = mpd_recv_idle(mpd.conn, false); +*/ + mpd_connection_set_timeout(mpd.conn, mpd.timeout); + switch(cmd_id) { case MPD_API_UNKNOWN: n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Unknown request\"}"); @@ -468,6 +478,8 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { mpd.conn_state = MPD_FAILURE; } + mpd_send_idle(mpd.conn); + if (n == 0) n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"No response for cmd %s\"}", cmd); @@ -547,12 +559,15 @@ static int mympd_notify_callback(struct mg_connection *c, const char *param) { return 0; } -void mympd_poll(struct mg_mgr *s) { +void mympd_poll(struct mg_mgr *s, int timeout) { + struct pollfd fds[1]; + int pollrc; + switch (mpd.conn_state) { case MPD_DISCONNECTED: /* Try to connect */ fprintf(stdout, "MPD Connecting to %s: %d\n", config.mpdhost, config.mpdport); - mpd.conn = mpd_connection_new(config.mpdhost, config.mpdport, 3000); + mpd.conn = mpd_connection_new(config.mpdhost, config.mpdport, mpd.timeout); if (mpd.conn == NULL) { fprintf(stderr, "Out of memory."); mpd.conn_state = MPD_FAILURE; @@ -578,8 +593,9 @@ void mympd_poll(struct mg_mgr *s) { } fprintf(stderr, "MPD connected.\n"); - mpd_connection_set_timeout(mpd.conn, 10000); + mpd_connection_set_timeout(mpd.conn, mpd.timeout); mpd.conn_state = MPD_CONNECTED; + mpd_send_idle(mpd.conn); break; case MPD_FAILURE: @@ -594,14 +610,68 @@ void mympd_poll(struct mg_mgr *s) { break; case MPD_CONNECTED: - mpd.buf_size = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.queue_version); - for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) { - mympd_notify_callback(c, NULL); + fds[0].fd = mpd_connection_get_fd(mpd.conn); + fds[0].events = POLLIN; + pollrc = poll(fds, 1, timeout); + if (pollrc > 0) { + mpd_send_noidle(mpd.conn); + mympd_parse_idle(s); + mpd_send_idle(mpd.conn); } break; } } +void mympd_parse_idle(struct mg_mgr *s) { + mpd_connection_set_timeout(mpd.conn, 100); + enum mpd_idle idle_bitmask = mpd_recv_idle(mpd.conn, false); + + for (unsigned j = 0;; ++j) { + enum mpd_idle idle_event = 1 << j; + const char *idle_name = mpd_idle_name(idle_event); + if (idle_name == NULL) + break; + if (idle_bitmask & idle_event) { + #ifdef DEBUG + fprintf(stderr,"IDLE: %s\n",idle_name); + #endif + switch(idle_event) { + case MPD_IDLE_DATABASE: + break; + case MPD_IDLE_STORED_PLAYLIST: + break; + case MPD_IDLE_QUEUE: + break; + case MPD_IDLE_PLAYER: + break; + case MPD_IDLE_MIXER: + break; + case MPD_IDLE_OUTPUT: + break; + case MPD_IDLE_OPTIONS: + break; + case MPD_IDLE_UPDATE: + break; + case MPD_IDLE_STICKER: + break; + case MPD_IDLE_SUBSCRIPTION: + break; + case MPD_IDLE_MESSAGE: + break; + } + } + + } + +//old behaviour + if (idle_bitmask > 0) { + mpd_connection_set_timeout(mpd.conn, mpd.timeout); + mpd.buf_size = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.queue_version); + for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) + mympd_notify_callback(c, NULL); + } +} + char* mympd_get_tag(struct mpd_song const *song, enum mpd_tag_type tag) { char *str; str = (char *)mpd_song_get_tag(song, tag, 0); @@ -1432,5 +1502,5 @@ int mympd_put_stats(char *buffer) { void mympd_disconnect() { mpd.conn_state = MPD_DISCONNECT; - mympd_poll(NULL); + mympd_poll(NULL, 100); } diff --git a/src/mpd_client.h b/src/mpd_client.h index 6c3cde8..c00343d 100644 --- a/src/mpd_client.h +++ b/src/mpd_client.h @@ -117,6 +117,7 @@ struct t_mpd { int song_id; int next_song_id; unsigned queue_version; + int timeout; } mpd; typedef struct { @@ -146,7 +147,8 @@ struct t_mpd_client_session { unsigned queue_version; }; -void mympd_poll(struct mg_mgr *s); +void mympd_poll(struct mg_mgr *sm, int timeout); +void mympd_parse_idle(struct mg_mgr *s); void callback_mympd(struct mg_connection *nc, const struct mg_str msg); int mympd_close_handler(struct mg_connection *c); int mympd_put_state(char *buffer, int *current_song_id, int *next_song_id, unsigned *queue_version); diff --git a/src/mympd.c b/src/mympd.c index 6474077..0f3a6e5 100644 --- a/src/mympd.c +++ b/src/mympd.c @@ -149,7 +149,6 @@ int main(int argc, char **argv) { struct mg_mgr mgr; struct mg_connection *nc; struct mg_connection *nc_http; - unsigned int current_timer = 0, last_timer = 0; struct mg_bind_opts bind_opts; const char *err; @@ -171,6 +170,8 @@ int main(int argc, char **argv) { config.coverimage = "folder.jpg"; config.statefile = "/var/lib/mympd/mympd.state"; + mpd.timeout = 3000; + if (argc == 2) { if (ini_parse(argv[1], inihandler, &config) < 0) { printf("Can't load '%s'\n", argv[1]); @@ -255,12 +256,8 @@ int main(int argc, char **argv) { printf("myMPD started on ssl port %s\n", config.sslport); while (s_signal_received == 0) { - mg_mgr_poll(&mgr, 200); - current_timer = time(NULL); - if (current_timer - last_timer) { - last_timer = current_timer; - mympd_poll(&mgr); - } + mympd_poll(&mgr, 100); + mg_mgr_poll(&mgr, 100); } mg_mgr_free(&mgr); mympd_disconnect();