gboolean mpd_connect(void) { mpd.conn = mpd_connection_new(prefs.mpd_server, prefs.mpd_port, 10000); mpd.idle_source = 0; if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) { g_warning("Failed to connect to MPD: %s", mpd_connection_get_error_message(mpd.conn)); return FALSE; } else if (mpd_connection_cmp_server_version(mpd.conn, 0, 14, 0) < 0) { g_critical("MPD too old, please upgrade to 0.14 or newer"); return FALSE; } else { GIOChannel *channel; mpd_command_list_begin(mpd.conn, TRUE); if (prefs.mpd_password) mpd_send_password(mpd.conn, prefs.mpd_password); mpd_send_status(mpd.conn); mpd_send_current_song(mpd.conn); mpd_command_list_end(mpd.conn); mpd.status = mpd_recv_status(mpd.conn); if (!mpd_response_next(mpd.conn)) { mpd_report_error(); return FALSE; } mpd.song = mpd_recv_song(mpd.conn); if (!mpd_response_finish(mpd.conn)) { mpd_report_error(); return FALSE; } g_message("Connected to MPD"); irc_say("Connected to MPD"); mpd_send_idle_mask(mpd.conn, MPD_IDLE_PLAYER); channel = g_io_channel_unix_new( mpd_connection_get_fd(mpd.conn)); mpd.idle_source = g_io_add_watch(channel, G_IO_IN, (GIOFunc) mpd_parse, NULL); g_io_channel_unref(channel); return TRUE; } }
void mpd_poll() { // printf("%d\n", mpd.conn_state); switch (mpd.conn_state) { case MPD_DISCONNECTED: syslog(LOG_INFO, "%s - MPD Connecting...\n", __func__); mpd.conn = mpd_connection_new(NULL, NULL, 3000); if (mpd.conn == NULL) { syslog(LOG_ERR, "%s - Out of memory.", __func__); mpd.conn_state = MPD_FAILURE; return; } if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) { syslog(LOG_ERR, "%s - MPD connection: %s\n", __func__, mpd_connection_get_error_message(mpd.conn)); mpd.conn_state = MPD_FAILURE; return; } syslog(LOG_INFO, "%s - MPD connected.\n", __func__); mpd_connection_set_timeout(mpd.conn, 10000); mpd.conn_state = MPD_CONNECTED; break; case MPD_FAILURE: case MPD_DISCONNECT: case MPD_RECONNECT: syslog(LOG_ERR, "%s - MPD (dis)reconnect or failure\n", __func__); if(mpd.conn != NULL) mpd_connection_free(mpd.conn); mpd.conn = NULL; mpd.conn_state = MPD_DISCONNECTED; break; case MPD_CONNECTED: mpd_put_state(); //TODO: display status /* if (queue_is_empty) { queue_is_empty = 0; get_random_song(mpd.conn, str, rcm.file_path); if (strcmp(str, "") != 0) { syslog(LOG_DEBUG, "%s: add random song %s\n", __func__, str); mpd_run_add(mpd.conn, str); } }*/ break; default: syslog(LOG_INFO, "%s - mpd.conn_state %i\n", __func__, mpd.conn_state); } }
int main(int argc, char **argv) { int t; bool firsttime = true; pid=getpid(); _debug = (bool) getenv("MADAUDIO_DEBUG"); if(!_debug) daemon(0, 0); int flags = LOG_NDELAY | LOG_PID; if(_debug) flags |= LOG_PERROR; openlog("madaudio-unsuspend", flags, LOG_DAEMON); struct mpd_connection *conn; for(t=1000; t > 0; t++) { conn = mpd_connection_new(MADAUDIO_SOCKET, 0, 0); if(conn && mpd_connection_get_error(conn)==MPD_ERROR_SUCCESS) break; debug("can't connect to mpd, retry", pid); usleep(1000); }; debug("connected..."); while(true) { struct mpd_status * status = mpd_run_status(conn); check(conn); if(!status) err(1, "madaudio-unsuspend[%d]: Can't get status\n"); enum mpd_state state = mpd_status_get_state(status); if(state != oldstate) { if(state == MPD_STATE_PLAY) lock_autosuspend(); else { if(!firsttime) unlock_autosuspend(); } }; oldstate = state; firsttime = false; mpd_status_free(status); mpd_run_idle_mask(conn, MPD_IDLE_PLAYER); check(conn); } }
static void mpd_printerror(const char *cmd) { const char *s; if (conn) { //assert(mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS); s = mpd_connection_get_error_message(conn); if (mpd_connection_get_error(conn) == MPD_ERROR_SERVER) /* messages received from the server are UTF-8; the rest is either US-ASCII or locale */ s = charset_from_utf8(s); error("[MPD] %s to [%s]:[%i] failed : [%s]", cmd, host, iport, s); mpd_connection_free(conn); conn = NULL; } }
/* * pgmpc_init * * Initialize connection to mpd server. */ static void pgmpc_init(void) { Assert(mpd_conn == NULL); /* Establish connection to mpd server */ mpd_conn = mpd_connection_new(mpd_host, mpd_port, mpd_timeout * 1000); if (mpd_connection_get_error(mpd_conn) != MPD_ERROR_SUCCESS) pgmpc_print_error(); /* Send password if any */ if (mpd_password[0]) { if (!mpd_run_password(mpd_conn, mpd_password)) pgmpc_print_error(); } }
/*new_connection*/ int new_connection(struct mpd_connection **conn) { *conn = mpd_connection_new(NULL, 0, 30000); if (*conn == NULL) { printf("nd new_connection %s\n", "Out of memory"); return -1; } if (mpd_connection_get_error(*conn) != MPD_ERROR_SUCCESS) { printf("nd new_connection %s\n", mpd_connection_get_error_message(*conn)); mpd_connection_free(*conn); *conn = NULL; return -1; } return 0; }
bool CMPD::Connect() { if(_conn) mpd_connection_free(_conn); _conn = mpd_connection_new(Config->getMHost().c_str(), Config->getMPort(), 0); _connected = _conn && mpd_connection_get_error(_conn) == MPD_ERROR_SUCCESS; if(_connected && Config->getMPassword().size() > 0) { _connected &= mpd_run_password(_conn, Config->getMPassword().c_str()); } if(_connected) mpd_run_subscribe(_conn, "mpdas"); return _connected; }
void Connection::checkErrors() const { mpd_error code = mpd_connection_get_error(m_connection.get()); if (code != MPD_ERROR_SUCCESS) { std::string msg = mpd_connection_get_error_message(m_connection.get()); if (code == MPD_ERROR_SERVER) { mpd_server_error server_code = mpd_connection_get_server_error(m_connection.get()); bool clearable = mpd_connection_clear_error(m_connection.get()); throw ServerError(server_code, msg, clearable); } else { bool clearable = mpd_connection_clear_error(m_connection.get()); throw ClientError(code, msg, clearable); } } }
/* * pgmpc_print_error * * Relay an error from mpd to Postgres. */ static void pgmpc_print_error(void) { const char *message; Assert(mpd_connection_get_error(mpd_conn) != MPD_ERROR_SUCCESS); /* Obtain error message */ message = mpd_connection_get_error_message(mpd_conn); /* Cleanup */ pgmpc_reset(); /* Report error */ ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("mpd command failed: %s", message))); }
static int connect(struct mpd_connection **conn) { *conn = mpd_connection_new(NULL, 0, 30000); if (*conn == NULL) { LOG_ERROR("%s", "Out of memory"); return -1; } if (mpd_connection_get_error(*conn) != MPD_ERROR_SUCCESS) { LOG_ERROR("%s", mpd_connection_get_error_message(*conn)); mpd_connection_free(*conn); *conn = NULL; return -1; } return 1; }
bool CMPD::Connect() { if(_conn) mpd_connection_free(_conn); _conn = mpd_connection_new(_cfg->Get("host").c_str(), _cfg->GetInt("port"), 0); _connected = _conn && mpd_connection_get_error(_conn) == MPD_ERROR_SUCCESS; if(_connected && _cfg->Get("mpdpassword").size() > 0) { _connected &= mpd_run_password(_conn, _cfg->Get("mpdpassword").c_str()); } else if(!_connected) { eprintf("MPD connection error: %s", mpd_connection_get_error_message(_conn)); } if(_connected) mpd_run_subscribe(_conn, "mpdas"); return _connected; }
/* * returns: 0 - error; 1 - ok */ int mgr_mpd_connect( void ) { if (conn != NULL) { if (DEBUG) fprintf(stderr, "DEBUG: [mgr-thread] mpd: close open connection\n"); mpd_connection_free(conn); conn = NULL; } conn = mpd_connection_new(NULL, 0, 30000); if (conn == NULL || mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { fprintf(stderr, "ERROR: MPD: Unable to connect to MPD\n"); return 0; } // SETUP mode: repeat:yes, random:yes if (!mpd_run_repeat(conn, true) || !mpd_run_random(conn, true)) { fprintf(stderr, "ERROR: MPD: Unable to change mode for the created MPD connection\n"); mgr_handle_mpd_error(); return 0; } if (DEBUG) fprintf(stderr, "DEBUG: [mgr-thread] mpd: new MPD connection was created\n"); if (DEBUG) fprintf(stderr, "DEBUG: [mgr-thread] mpd: database update started\n"); // Send update command if (!mpd_run_update(conn, NULL)) { // ALL MUSIC in the folder fprintf(stderr, "ERROR: MPD: Unable to update MPD database\n"); mgr_handle_mpd_error(); return 0; } return 1; }
int main(int argc, char *argv[]) { char *password = NULL; struct mpd_connection *conn = mpd_connection_new(mpd_check_host(NULL, &password), 0, 0); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { fprintf(stderr,"%s: %s\n", argv[0], mpd_connection_get_error_message(conn)); return 1; } if (password != NULL) { if (mpd_run_password(conn, password) == false) { fprintf(stderr, "%s: mpd_run_password %s\n", argv[0], mpd_connection_get_error_message(conn)); free(password); return 2; } } if (notify_init("MPD_Notification") == 0) { fprintf(stderr, "%s: Cannot initialize libnotify.\n", argv[0]); return 3; } infinite_loop(conn); mpd_connection_free(conn); free(password); notify_uninit(); return 0; }
bool mpd_is_in_queue(const char *uri) { bool res = false; struct mpd_entity *entity; struct mpd_connection *conn = mpd_connection_new(NULL, NULL, 3000); if (conn == NULL) { syslog(LOG_ERR, "%s - Out of memory.", __func__); goto DONE; } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { syslog(LOG_ERR, "%s - MPD connection: %s\n", __func__, mpd_connection_get_error_message(conn)); goto DONE; } if (!mpd_send_list_queue_meta(conn)) { syslog(LOG_ERR, "%s: %s", __func__, mpd_connection_get_error_message(conn)); mpd_connection_clear_error(conn); goto DONE; } while((entity = mpd_recv_entity(conn)) != NULL) { const struct mpd_song *song; if(mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG && !res) { song = mpd_entity_get_song(entity); if (strcmp(mpd_song_get_uri(song), uri) == 0) { syslog(LOG_INFO, "%s: %s is already in the queue", __func__, uri); res = true; } } mpd_entity_free(entity); } DONE: if(conn != NULL) mpd_connection_free(conn); return res; }
void print_mpd(yajl_gen json_gen, char *buffer, const char *host, int port, const char *password, const char *format) { const char *walk; char *outwalk = buffer; static char titlebuf[40]; static char artistbuf[40]; static char albumbuf[40]; static char trackbuf[10]; static char datebuf[10]; static struct mpd_connection *conn; struct mpd_status *status = NULL; enum mpd_state state; struct mpd_song *song; /* First run */ if (conn == NULL) { conn = mpd_connection_new(host, port, 1500); if (conn == NULL) { START_COLOR("color_bad"); outwalk += sprintf(outwalk, "%s", "ERROR"); goto print_end; } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { START_COLOR("color_bad"); outwalk += sprintf(outwalk, "%s", "CONNECT ERROR"); mpd_connection_free(conn); conn = NULL; goto print_end; } if (password != NULL && strcmp(password, "") != 0 && !mpd_run_password(conn, password)) { START_COLOR("color_bad"); outwalk += sprintf(outwalk, "%s", "PASS ERROR"); mpd_connection_free(conn); conn = NULL; goto print_end; } } if ((status = mpd_run_status(conn))) { state = mpd_status_get_state(status); } if (!status || (state != MPD_STATE_PLAY && state != MPD_STATE_PAUSE)) { START_COLOR("color_bad"); outwalk += sprintf(outwalk, "%s", "Stopped"); mpd_connection_free(conn); conn = NULL; goto print_end; } mpd_status_free(status); if (state == MPD_STATE_PLAY) START_COLOR("color_good"); else if (state == MPD_STATE_PAUSE) START_COLOR("color_degraded"); song = mpd_run_current_song(conn); COPY_CROP(titlebuf, mpd_song_get_tag(song, MPD_TAG_TITLE, 0)); COPY_CROP(artistbuf, mpd_song_get_tag(song, MPD_TAG_ARTIST, 0)); COPY_CROP(albumbuf, mpd_song_get_tag(song, MPD_TAG_ALBUM, 0)); COPY_CROP(trackbuf, mpd_song_get_tag(song, MPD_TAG_TRACK, 0)); COPY_CROP(datebuf, mpd_song_get_tag(song, MPD_TAG_DATE, 0)); mpd_song_free(song); for (walk = format; *walk != '\0'; walk++) { if (*walk != '%') { *(outwalk++) = *walk; continue; } if (BEGINS_WITH(walk+1, "title")) { if (*titlebuf) outwalk += sprintf(outwalk, "%s", titlebuf); walk += strlen("title"); } else if (BEGINS_WITH(walk+1, "artist")) { if (*artistbuf) outwalk += sprintf(outwalk, "%s", artistbuf); walk += strlen("artist"); } else if (BEGINS_WITH(walk+1, "album")) { if (*albumbuf) outwalk += sprintf(outwalk, "%s", albumbuf); walk += strlen("album"); } else if (BEGINS_WITH(walk+1, "track")) { if (*trackbuf) outwalk += sprintf(outwalk, "%s", trackbuf); walk += strlen("track"); } else if (BEGINS_WITH(walk+1, "date")) { if (*datebuf) outwalk += sprintf(outwalk, "%s", datebuf); walk += strlen("date"); } } print_end: END_COLOR; OUTPUT_FULL_TEXT(buffer); return; }
void cmd_np(irc_session_t* session, const char* cmd, const char* origin, char* args) { struct mpd_connection* conn; struct mpd_song* song; char master_nick[20]; const char* title; const char* album; const char* artist; int out_len = 20 + 18 /* master_nick + " is now playing: "*/; char* out_str; irc_target_get_nick(master_origin, master_nick, 20); conn = mpd_connection_new(NULL, 0, 30000); if(mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { log_and_print("Impossible de se connecter à MPD"); mpd_connection_free(conn); return; } mpd_send_current_song(conn); song = mpd_recv_song(conn); if(song == NULL) { out_len += strlen("THE GAME"); out_str = malloc(out_len * sizeof(char)); strcpy(out_str, master_nick); strcat(out_str, " is now playing: THE GAME"); irc_cmd_msg(session, channel, out_str); free(out_str); return; } title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0); album = mpd_song_get_tag(song, MPD_TAG_ALBUM, 0); artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0); if(title) out_len += strlen(title) + 2; if(album) out_len += strlen(album) + 2; if(artist) out_len += strlen(artist) + 2; out_str = malloc(out_len * sizeof(char)); strcpy(out_str, master_nick); strcat(out_str, " is now playing: "); if(title) strcat(out_str, title); if(artist) { strcat(out_str, " - "); strcat(out_str, artist); } if(album) { strcat(out_str, " - "); strcat(out_str, album); } irc_cmd_msg(session, channel, out_str); free(out_str); mpd_song_free(song); mpd_connection_free(conn); }
int mpd_put_browse(char *buffer, char *path, unsigned int offset) { char *cur = buffer; const char *end = buffer + MAX_SIZE; struct mpd_entity *entity; unsigned int entity_count = 0; if (!mpd_send_list_meta(mpd.conn, path)) RETURN_ERROR_AND_RECOVER("mpd_send_list_meta"); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"browse\",\"data\":[ "); while((entity = mpd_recv_entity(mpd.conn)) != NULL) { const struct mpd_song *song; const struct mpd_directory *dir; const struct mpd_playlist *pl; if(offset > entity_count) { mpd_entity_free(entity); entity_count++; continue; } else if(offset + MAX_ELEMENTS_PER_PAGE - 1 < entity_count) { mpd_entity_free(entity); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\",\"count\":"); cur += json_emit_int(cur, end - cur, entity_count); cur += json_emit_raw_str(cur, end - cur, "} "); break; } switch (mpd_entity_get_type(entity)) { case MPD_ENTITY_TYPE_UNKNOWN: break; case MPD_ENTITY_TYPE_SONG: song = mpd_entity_get_song(entity); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\",\"uri\":"); cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song)); cur += json_emit_raw_str(cur, end - cur, ",\"duration\":"); cur += json_emit_int(cur, end - cur, mpd_song_get_duration(song)); cur += json_emit_raw_str(cur, end - cur, ",\"title\":"); cur += json_emit_quoted_str(cur, end - cur, mpd_get_title(song)); cur += json_emit_raw_str(cur, end - cur, "},"); break; case MPD_ENTITY_TYPE_DIRECTORY: dir = mpd_entity_get_directory(entity); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"directory\",\"dir\":"); cur += json_emit_quoted_str(cur, end - cur, mpd_directory_get_path(dir)); cur += json_emit_raw_str(cur, end - cur, "},"); break; case MPD_ENTITY_TYPE_PLAYLIST: pl = mpd_entity_get_playlist(entity); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"playlist\",\"plist\":"); cur += json_emit_quoted_str(cur, end - cur, mpd_playlist_get_path(pl)); cur += json_emit_raw_str(cur, end - cur, "},"); break; } mpd_entity_free(entity); entity_count++; } if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(mpd.conn)) { fprintf(stderr, "MPD mpd_send_list_meta: %s\n", mpd_connection_get_error_message(mpd.conn)); mpd.conn_state = MPD_FAILURE; return 0; } /* remove last ',' */ cur--; cur += json_emit_raw_str(cur, end - cur, "]}"); return cur - buffer; }
int callback_mpd(struct mg_connection *c) { enum mpd_cmd_ids cmd_id = get_cmd_id(c->content); size_t n = 0; unsigned int uint_buf, uint_buf_2; int int_buf; char *p_charbuf = NULL, *token; if(cmd_id == -1) return MG_TRUE; if(mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST && cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS && cmd_id != MPD_API_GET_DIRBLEAPITOKEN) return MG_TRUE; switch(cmd_id) { case MPD_API_UPDATE_DB: mpd_run_update(mpd.conn, NULL); break; case MPD_API_SET_PAUSE: mpd_run_toggle_pause(mpd.conn); break; case MPD_API_SET_PREV: mpd_run_previous(mpd.conn); break; case MPD_API_SET_NEXT: mpd_run_next(mpd.conn); break; case MPD_API_SET_PLAY: mpd_run_play(mpd.conn); break; case MPD_API_SET_STOP: mpd_run_stop(mpd.conn); break; case MPD_API_RM_ALL: mpd_run_clear(mpd.conn); break; case MPD_API_RM_TRACK: if(sscanf(c->content, "MPD_API_RM_TRACK,%u", &uint_buf)) mpd_run_delete_id(mpd.conn, uint_buf); break; case MPD_API_PLAY_TRACK: if(sscanf(c->content, "MPD_API_PLAY_TRACK,%u", &uint_buf)) mpd_run_play_id(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_RANDOM: if(sscanf(c->content, "MPD_API_TOGGLE_RANDOM,%u", &uint_buf)) mpd_run_random(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_REPEAT: if(sscanf(c->content, "MPD_API_TOGGLE_REPEAT,%u", &uint_buf)) mpd_run_repeat(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_CONSUME: if(sscanf(c->content, "MPD_API_TOGGLE_CONSUME,%u", &uint_buf)) mpd_run_consume(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_SINGLE: if(sscanf(c->content, "MPD_API_TOGGLE_SINGLE,%u", &uint_buf)) mpd_run_single(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_CROSSFADE: if(sscanf(c->content, "MPD_API_TOGGLE_CROSSFADE,%u", &uint_buf)) mpd_run_crossfade(mpd.conn, uint_buf); break; case MPD_API_GET_OUTPUTS: mpd.buf_size = mpd_put_outputs(mpd.buf, 1); c->callback_param = NULL; mpd_notify_callback(c, MG_POLL); break; case MPD_API_TOGGLE_OUTPUT: if (sscanf(c->content, "MPD_API_TOGGLE_OUTPUT,%u,%u", &uint_buf, &uint_buf_2)) { if (uint_buf_2) mpd_run_enable_output(mpd.conn, uint_buf); else mpd_run_disable_output(mpd.conn, uint_buf); } break; case MPD_API_SET_VOLUME: if(sscanf(c->content, "MPD_API_SET_VOLUME,%ud", &uint_buf) && uint_buf <= 100) mpd_run_set_volume(mpd.conn, uint_buf); break; case MPD_API_SET_SEEK: if(sscanf(c->content, "MPD_API_SET_SEEK,%u,%u", &uint_buf, &uint_buf_2)) mpd_run_seek_id(mpd.conn, uint_buf, uint_buf_2); break; case MPD_API_GET_QUEUE: if(sscanf(c->content, "MPD_API_GET_QUEUE,%u", &uint_buf)) n = mpd_put_queue(mpd.buf, uint_buf); break; case MPD_API_GET_BROWSE: p_charbuf = strdup(c->content); if(strcmp(strtok(p_charbuf, ","), "MPD_API_GET_BROWSE")) goto out_browse; uint_buf = strtoul(strtok(NULL, ","), NULL, 10); if((token = strtok(NULL, ",")) == NULL) goto out_browse; free(p_charbuf); p_charbuf = strdup(c->content); n = mpd_put_browse(mpd.buf, get_arg2(p_charbuf), uint_buf); out_browse: free(p_charbuf); break; case MPD_API_ADD_TRACK: p_charbuf = strdup(c->content); if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_TRACK")) goto out_add_track; if((token = strtok(NULL, ",")) == NULL) goto out_add_track; free(p_charbuf); p_charbuf = strdup(c->content); mpd_run_add(mpd.conn, get_arg1(p_charbuf)); out_add_track: free(p_charbuf); break; case MPD_API_ADD_PLAY_TRACK: p_charbuf = strdup(c->content); if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAY_TRACK")) goto out_play_track; if((token = strtok(NULL, ",")) == NULL) goto out_play_track; free(p_charbuf); p_charbuf = strdup(c->content); int_buf = mpd_run_add_id(mpd.conn, get_arg1(p_charbuf)); if(int_buf != -1) mpd_run_play_id(mpd.conn, int_buf); out_play_track: free(p_charbuf); break; case MPD_API_ADD_PLAYLIST: p_charbuf = strdup(c->content); if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAYLIST")) goto out_playlist; if((token = strtok(NULL, ",")) == NULL) goto out_playlist; free(p_charbuf); p_charbuf = strdup(c->content); mpd_run_load(mpd.conn, get_arg1(p_charbuf)); out_playlist: free(p_charbuf); break; case MPD_API_SAVE_QUEUE: p_charbuf = strdup(c->content); if(strcmp(strtok(p_charbuf, ","), "MPD_API_SAVE_QUEUE")) goto out_save_queue; if((token = strtok(NULL, ",")) == NULL) goto out_save_queue; free(p_charbuf); p_charbuf = strdup(c->content); mpd_run_save(mpd.conn, get_arg1(p_charbuf)); out_save_queue: free(p_charbuf); break; case MPD_API_SEARCH: p_charbuf = strdup(c->content); if(strcmp(strtok(p_charbuf, ","), "MPD_API_SEARCH")) goto out_search; if((token = strtok(NULL, ",")) == NULL) goto out_search; free(p_charbuf); p_charbuf = strdup(c->content); n = mpd_search(mpd.buf, get_arg1(p_charbuf)); out_search: free(p_charbuf); break; #ifdef WITH_MPD_HOST_CHANGE /* Commands allowed when disconnected from MPD server */ case MPD_API_SET_MPDHOST: int_buf = 0; p_charbuf = strdup(c->content); if(strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDHOST")) goto out_host_change; if((int_buf = strtol(strtok(NULL, ","), NULL, 10)) <= 0) goto out_host_change; if((token = strtok(NULL, ",")) == NULL) goto out_host_change; strncpy(mpd.host, token, sizeof(mpd.host)); mpd.port = int_buf; mpd.conn_state = MPD_RECONNECT; free(p_charbuf); return MG_TRUE; out_host_change: free(p_charbuf); break; case MPD_API_GET_MPDHOST: n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"mpdhost\", \"data\": " "{\"host\" : \"%s\", \"port\": \"%d\", \"passwort_set\": %s}" "}", mpd.host, mpd.port, mpd.password ? "true" : "false"); break; case MPD_API_GET_DIRBLEAPITOKEN: n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"dirbleapitoken\", \"" "data\": \"%s\"}", dirble_api_token); break; case MPD_API_SET_MPDPASS: p_charbuf = strdup(c->content); if(strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDPASS")) goto out_set_pass; if((token = strtok(NULL, ",")) == NULL) goto out_set_pass; if(mpd.password) free(mpd.password); mpd.password = strdup(token); mpd.conn_state = MPD_RECONNECT; free(p_charbuf); return MG_TRUE; out_set_pass: free(p_charbuf); break; #endif } if(mpd.conn_state == MPD_CONNECTED && mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) { n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\", \"data\": \"%s\"}", mpd_connection_get_error_message(mpd.conn)); /* Try to recover error */ if (!mpd_connection_clear_error(mpd.conn)) mpd.conn_state = MPD_FAILURE; } if(n > 0) mg_websocket_write(c, 1, mpd.buf, n); return MG_TRUE; }
void mpd_poll(struct mg_server *s) { switch (mpd.conn_state) { case MPD_DISCONNECTED: /* Try to connect */ fprintf(stdout, "MPD Connecting to %s:%d\n", mpd.host, mpd.port); mpd.conn = mpd_connection_new(mpd.host, mpd.port, 3000); if (mpd.conn == NULL) { fprintf(stderr, "Out of memory."); mpd.conn_state = MPD_FAILURE; return; } if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) { fprintf(stderr, "MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn)); for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) { c->callback_param = (void *)mpd_connection_get_error_message(mpd.conn); mpd_notify_callback(c, MG_POLL); } mpd.conn_state = MPD_FAILURE; return; } if(mpd.password && !mpd_run_password(mpd.conn, mpd.password)) { fprintf(stderr, "MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn)); for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) { c->callback_param = (void *)mpd_connection_get_error_message(mpd.conn); mpd_notify_callback(c, MG_POLL); } mpd.conn_state = MPD_FAILURE; return; } fprintf(stderr, "MPD connected.\n"); mpd_connection_set_timeout(mpd.conn, 10000); mpd.conn_state = MPD_CONNECTED; /* write outputs */ mpd.buf_size = mpd_put_outputs(mpd.buf, 1); for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) { c->callback_param = NULL; mpd_notify_callback(c, MG_POLL); } break; case MPD_FAILURE: fprintf(stderr, "MPD connection failed.\n"); case MPD_DISCONNECT: case MPD_RECONNECT: if(mpd.conn != NULL) mpd_connection_free(mpd.conn); mpd.conn = NULL; mpd.conn_state = MPD_DISCONNECTED; break; case MPD_CONNECTED: mpd.buf_size = mpd_put_state(mpd.buf, &mpd.song_id, &mpd.queue_version); for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) { c->callback_param = NULL; mpd_notify_callback(c, MG_POLL); } mpd.buf_size = mpd_put_outputs(mpd.buf, 0); for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) { c->callback_param = NULL; mpd_notify_callback(c, MG_POLL); } break; } }
int callback_mpd(struct mg_connection *c) { enum mpd_cmd_ids cmd_id = get_cmd_id(c->content); size_t n = 0; unsigned int uint_buf, uint_buf_2; int int_buf; char *p_charbuf = NULL; if(cmd_id == -1) return MG_CLIENT_CONTINUE; if(mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST && cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS) return MG_CLIENT_CONTINUE; mpd_connection_set_timeout(mpd.conn, 10000); switch(cmd_id) { case MPD_API_UPDATE_DB: mpd_run_update(mpd.conn, NULL); break; case MPD_API_SET_PAUSE: mpd_run_toggle_pause(mpd.conn); break; case MPD_API_SET_PREV: mpd_run_previous(mpd.conn); break; case MPD_API_SET_NEXT: mpd_run_next(mpd.conn); break; case MPD_API_SET_PLAY: mpd_run_play(mpd.conn); break; case MPD_API_SET_STOP: mpd_run_stop(mpd.conn); break; case MPD_API_RM_ALL: mpd_run_clear(mpd.conn); break; case MPD_API_RM_TRACK: if(sscanf(c->content, "MPD_API_RM_TRACK,%u", &uint_buf)) mpd_run_delete_id(mpd.conn, uint_buf); break; case MPD_API_PLAY_TRACK: if(sscanf(c->content, "MPD_API_PLAY_TRACK,%u", &uint_buf)) mpd_run_play_id(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_RANDOM: if(sscanf(c->content, "MPD_API_TOGGLE_RANDOM,%u", &uint_buf)) mpd_run_random(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_REPEAT: if(sscanf(c->content, "MPD_API_TOGGLE_REPEAT,%u", &uint_buf)) mpd_run_repeat(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_CONSUME: if(sscanf(c->content, "MPD_API_TOGGLE_CONSUME,%u", &uint_buf)) mpd_run_consume(mpd.conn, uint_buf); break; case MPD_API_TOGGLE_SINGLE: if(sscanf(c->content, "MPD_API_TOGGLE_SINGLE,%u", &uint_buf)) mpd_run_single(mpd.conn, uint_buf); break; case MPD_API_SET_VOLUME: if(sscanf(c->content, "MPD_API_SET_VOLUME,%ud", &uint_buf) && uint_buf <= 100) mpd_run_set_volume(mpd.conn, uint_buf); break; case MPD_API_SET_SEEK: if(sscanf(c->content, "MPD_API_SET_SEEK,%u,%u", &uint_buf, &uint_buf_2)) mpd_run_seek_id(mpd.conn, uint_buf, uint_buf_2); break; case MPD_API_GET_QUEUE: if(sscanf(c->content, "MPD_API_GET_QUEUE,%u", &uint_buf)) n = mpd_put_queue(mpd.buf, uint_buf); break; case MPD_API_GET_BROWSE: if(sscanf(c->content, "MPD_API_GET_BROWSE,%u,%m[^\t\n]", &uint_buf, &p_charbuf) && p_charbuf != NULL) { n = mpd_put_browse(mpd.buf, p_charbuf, uint_buf); free(p_charbuf); } break; case MPD_API_ADD_TRACK: if(sscanf(c->content, "MPD_API_ADD_TRACK,%m[^\t\n]", &p_charbuf) && p_charbuf != NULL) { mpd_run_add(mpd.conn, p_charbuf); free(p_charbuf); } break; case MPD_API_ADD_PLAY_TRACK: if(sscanf(c->content, "MPD_API_ADD_PLAY_TRACK,%m[^\t\n]", &p_charbuf) && p_charbuf != NULL) { int_buf = mpd_run_add_id(mpd.conn, p_charbuf); if(int_buf != -1) mpd_run_play_id(mpd.conn, int_buf); free(p_charbuf); } break; case MPD_API_ADD_PLAYLIST: if(sscanf(c->content, "MPD_API_ADD_PLAYLIST,%m[^\t\n]", &p_charbuf) && p_charbuf != NULL) { mpd_run_load(mpd.conn, p_charbuf); free(p_charbuf); } break; case MPD_API_SEARCH: if(sscanf(c->content, "MPD_API_SEARCH,%m[^\t\n]", &p_charbuf) && p_charbuf != NULL) { n = mpd_search(mpd.buf, p_charbuf); free(p_charbuf); } break; #ifdef WITH_MPD_HOST_CHANGE /* Commands allowed when disconnected from MPD server */ case MPD_API_SET_MPDHOST: int_buf = 0; if(sscanf(c->content, "MPD_API_SET_MPDHOST,%d,%m[^\t\n ]", &int_buf, &p_charbuf) && p_charbuf != NULL && int_buf > 0) { strncpy(mpd.host, p_charbuf, sizeof(mpd.host)); free(p_charbuf); mpd.port = int_buf; mpd.conn_state = MPD_RECONNECT; return MG_CLIENT_CONTINUE; } break; case MPD_API_GET_MPDHOST: n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"mpdhost\", \"data\": " "{\"host\" : \"%s\", \"port\": \"%d\", \"passwort_set\": %s}" "}", mpd.host, mpd.port, mpd.password ? "true" : "false"); break; case MPD_API_SET_MPDPASS: if(sscanf(c->content, "MPD_API_SET_MPDPASS,%m[^\t\n ]", &p_charbuf)) { if(mpd.password) free(mpd.password); mpd.password = p_charbuf; mpd.conn_state = MPD_RECONNECT; return MG_CLIENT_CONTINUE; } break; #endif } if(mpd.conn_state == MPD_CONNECTED && mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) { n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\", \"data\": \"%s\"}", mpd_connection_get_error_message(mpd.conn)); /* Try to recover error */ if (!mpd_connection_clear_error(mpd.conn)) mpd.conn_state = MPD_FAILURE; } if(n > 0) mg_websocket_write(c, 1, mpd.buf, n); return MG_CLIENT_CONTINUE; }
void MpdWidget::psMpdHB() { timerMpd->stop(); QString dataSender, dataVol, dataTitle; struct mpd_connection *conn; struct mpd_status * status; struct mpd_song *song; // const struct mpd_audio_format *audio_format; conn = mpd_connection_new(NULL, 0, 30000); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { timerMpd->start(); return; } if (aktPlay) { aktPlay = false; mpd_send_command(conn, "play", NULL); timerMpd->start(); return; } if (aktStop) { aktStop = false; mpd_send_command(conn, "stop", NULL); timerMpd->start(); return; } mpd_command_list_begin(conn, true); mpd_send_status(conn); mpd_send_current_song(conn); mpd_command_list_end(conn); // Status status = mpd_recv_status(conn); if (status == NULL) { timerMpd->start(); return ; } // Volume dataVol.number(mpd_status_get_volume(status)); if (labelVol->text().compare(dataVol) != 0) labelVol->setText(dataVol); if (mpd_status_get_error(status) != NULL) new QListWidgetItem(QString("status error: %1"). arg(mpd_status_get_error(status))); mpd_status_free(status); // Status mpd_response_next(conn); // Song song = mpd_recv_song(conn); if (song == NULL) { handle_error(conn); timerMpd->start(); return ; } // Title dataTitle = mpd_song_get_uri(song); if (labelTitle->text().compare(dataTitle) != 0) labelTitle->setText(dataTitle); unsigned int i = 0; QString value; while ((value = mpd_song_get_tag(song, MPD_TAG_TITLE, i++)) != NULL) { if (i > 0) dataSender.append(" "); dataSender.append(value); } if (labelSender->text().compare(dataSender) != 0) { labelSender->setText(dataSender); qDebug() << "refresh"; } mpd_song_free(song); // Song mpd_connection_free(conn); timerMpd->start(); }
/* Execute the given command. In fact, it just will ask MPD to do it. * You will have to check the next "status" or "playlist" update (using the corresponding slot) * to know if the command has really been executed. */ void Player::executeCmd(EMSPlayerCmd cmd) { bool waitResponse = true; /* Wait the responase by default */ bool error = false; if (conn == NULL) { return; } /* Dispatch execution depending on the action */ switch (cmd.action) { case ACTION_ADD: { if(searchTrackInPlaylist(cmd.track) >= 0) { qDebug() << "Do not add track in the playlist as it already exist"; return; } QString filename = getMPDFilename(cmd.track); mpd_send_add(conn, filename.toStdString().c_str()); break; } case ACTION_DEL: { int pos = searchTrackInPlaylist(cmd.track); if (pos >= 0) { mpd_send_delete(conn, pos); } break; } case ACTION_DEL_ALL: { mpd_send_clear(conn); break; } case ACTION_PLAY_POS: { mutex.lock(); int size = playlist.tracks.size(); mutex.unlock(); if (size <= 0 || cmd.uintValue >= (unsigned int)size) { qDebug() << "Asked to play a track after the end of the current playlist"; error = true; break; } mpd_send_play_pos(conn, cmd.uintValue); break; } case ACTION_PLAY_TRACK: { int position = searchTrackInPlaylist(cmd.track); if (position < 0) { qDebug() << "Asked to play a track which is not in the current playlist"; error = true; break; } mpd_send_play_pos(conn, position); break; } case ACTION_PLAY: { mpd_send_play(conn); break; } case ACTION_SEEK: { /* Get current position */ int songId = getCurrentPos(); if (songId >= 0) { mpd_send_seek_pos(conn, songId, cmd.uintValue); } break; } case ACTION_PAUSE: { mpd_send_pause(conn, true); break; } case ACTION_TOGGLE: { mpd_send_toggle_pause(conn); break; } case ACTION_STOP: { mpd_send_stop(conn); break; } case ACTION_NEXT: { mpd_send_next(conn); break; } case ACTION_PREV: { mpd_send_previous(conn); break; } case ACTION_REPEAT: { mutex.lock(); bool repeatTmp = status.repeat; mutex.unlock(); if (cmd.boolValue != repeatTmp) { mpd_send_repeat(conn, cmd.boolValue); } break; } case ACTION_RANDOM: { mutex.lock(); bool randomTmp = status.random; mutex.unlock(); if (cmd.boolValue != randomTmp) { mpd_send_random(conn, cmd.boolValue); } break; } case ACTION_ENABLE_OUTPUT: { if (cmd.uintValue >= 1) { mpd_send_enable_output(conn, cmd.uintValue-1); } break; } case ACTION_DISABLE_OUTPUT: { if (cmd.uintValue >= 1) { mpd_send_disable_output(conn, cmd.uintValue-1); } break; } default: { qCritical() << "Unhandled action in the current command."; waitResponse = false; break; } } if (waitResponse && !mpd_response_finish(conn)) { error = true; qCritical() << "MPD could not execute the current command."; enum mpd_error errorMpd = mpd_connection_get_error(conn); if (errorMpd == MPD_ERROR_SERVER || errorMpd == MPD_ERROR_ARGUMENT) /* Problem with the command */ { QString errorMessage = QString::fromUtf8(mpd_connection_get_error_message(conn)); qCritical() << "Command error : " << errorMessage; if (!mpd_connection_clear_error(conn)) { qCritical() << "This error cannot be cleared, reconnecting..."; connectToMpd(); } } else if (errorMpd == MPD_ERROR_TIMEOUT || errorMpd == MPD_ERROR_RESOLVER || errorMpd == MPD_ERROR_MALFORMED || errorMpd == MPD_ERROR_CLOSED ) /* Assume there is a connection problem, try to reconnect... */ { QString errorMessage = QString::fromUtf8(mpd_connection_get_error_message(conn)); qCritical() << "Connexion error : " << errorMessage; qCritical() << "Reconnecting..."; connectToMpd(); mutex.lock(); queue.push_front(cmd); mutex.unlock(); cmdAvailable.release(1); } } /* Post-action depending on the command * Do the minimum here as the whole status will be * retrieve here. But for playlist ADD/DEL, we need to * store the EMSTrack structure. */ if(!error) { switch (cmd.action) { case ACTION_ADD: { EMSPlaylist newPlaylist; mutex.lock(); playlist.tracks.append(cmd.track); newPlaylist = playlist; mutex.unlock(); emit playlistChanged(newPlaylist); break; } case ACTION_DEL: { int pos = searchTrackInPlaylist(cmd.track); if (pos >= 0) { EMSPlaylist newPlaylist; mutex.lock(); playlist.tracks.removeAt(pos); newPlaylist = playlist; mutex.unlock(); emit playlistChanged(newPlaylist); } break; } case ACTION_DEL_ALL: { EMSPlaylist newPlaylist; mutex.lock(); playlist.tracks.clear(); newPlaylist = playlist; mutex.unlock(); emit playlistChanged(newPlaylist); break; } case ACTION_ENABLE_OUTPUT: { mutex.lock(); for(int i=0; i<outputs.size(); i++) { if (outputs.at(i).id_mpd == cmd.uintValue) { EMSSndCard card = outputs.at(i); card.enabled = true; outputs.replace(i, card); } } emit outputsChanged(outputs); mutex.unlock(); break; } case ACTION_DISABLE_OUTPUT: { mutex.lock(); for(int i=0; i<outputs.size(); i++) { if (outputs.at(i).id_mpd == cmd.uintValue) { EMSSndCard card = outputs.at(i); card.enabled = false; outputs.replace(i, card); } } emit outputsChanged(outputs); mutex.unlock(); break; } default: break; } } }
/* Establish a connection with the MPD server * If the connection failed, the "conn" is set to NULL */ void Player::connectToMpd() { QSettings settings; unsigned int retryPeriod; QString host; unsigned int port; unsigned int timeout; QString password; EMS_LOAD_SETTINGS(retryPeriod, "player/retry_period", EMS_MPD_CONNECTION_RETRY_PERIOD, UInt); EMS_LOAD_SETTINGS(host, "player/host", EMS_MPD_IP, String); EMS_LOAD_SETTINGS(timeout, "player/timeout", EMS_MPD_TIMEOUT, UInt); EMS_LOAD_SETTINGS(port, "player/port", EMS_MPD_PORT, UInt); EMS_LOAD_SETTINGS(password, "player/password", EMS_MPD_PASSWORD, String); if (conn != NULL) { disconnectToMpd(); } /* Try to connect until it success */ while (!conn && !isInterruptionRequested()) { qDebug() << "Connecting to " << QString("%1:%2... (timeout %3ms)").arg(host).arg(port).arg(timeout); conn = mpd_connection_new(host.toStdString().c_str(), port, timeout); if (conn == NULL) { qCritical() << "MPD Connection failed."; } else if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { QString errorMessage = QString::fromUtf8(mpd_connection_get_error_message(conn)); qCritical() << "MPD Connection failed : " << errorMessage; mpd_connection_free(conn); conn = NULL; } else if (!password.isEmpty()) { qDebug() << "Setting password..."; if (!mpd_run_password(conn, password.toStdString().c_str())) { qCritical() << "Setting MPD password failed."; mpd_connection_free(conn); conn = NULL; } } if (!conn) { qCritical() << "Retrying within " << QString("%1 ms").arg(retryPeriod); for (unsigned int i=0; i<retryPeriod; i++) { if (!isInterruptionRequested()) usleep(1000); else break; } } } qDebug() << "Connected to " << host; }
/* * Returns: 0 - error; 1 - ok */ int mgr_mpd_fetch_status( struct mpd_connection *conn, int dump_status ) { struct mpd_status *status; struct mpd_stats *stats; if (DEBUG > 1) fprintf(stderr, "DEBUG: [mgr-thread] mpd: -status fetching...\n"); if (conn == NULL) { fprintf(stderr, "ERROR: MPD: Unable to retrieve the MPD status: not connected\n"); return 0; } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { fprintf(stderr, "ERROR: MPD: Unable to retrieve MPD status: connection error\n"); return 0; } if (DEBUG > 1) fprintf(stderr, "DEBUG: [mgr-thread] mpd: run status\n"); status = mpd_run_status(conn); if (!status) { fprintf(stderr, "ERROR: MPD: Unable to retrieve MPD status\n"); return 0; } cur_mpd_player_status = mpd_status_get_state(status); if (DEBUG > 1) { fprintf(stderr, "DEBUG: [mgr-thread] mpd: +status received:\n"); } if (DEBUG && dump_status) { fprintf(stderr, "DEBUG: [mgr-thread] mpd status: => mode : %s\n", (cur_mpd_player_status == MPD_STATE_PLAY ? "Play" : "Other")); fprintf(stderr, "DEBUG: [mgr-thread] mpd status: => random : %d\n", mpd_status_get_random(status)); fprintf(stderr, "DEBUG: [mgr-thread] mpd status: => repeat : %d\n", mpd_status_get_random(status)); fprintf(stderr, "DEBUG: [mgr-thread] mpd status: => volume : %d\n", mpd_status_get_volume(status)); fprintf(stderr, "DEBUG: [mgr-thread] mpd status: => queue ver : %d\n", mpd_status_get_queue_version(status)); fprintf(stderr, "DEBUG: [mgr-thread] mpd status: => queue len : %d\n", mpd_status_get_queue_length(status)); } cur_mpd_random = mpd_status_get_random(status) ? 1 : 0; cur_mpd_volume = mpd_status_get_volume(status); cur_mpd_status_queue_len = mpd_status_get_queue_length(status); if (DEBUG > 1) fprintf(stderr, "DEBUG: [mgr-thread] mpd: release status\n"); if (mpd_status_get_error(status) != NULL) { fprintf(stderr, "WARNING: MPD: Error Received from MPD: %s\n", mpd_status_get_error(status)); // TODO - clear error } mpd_status_free(status); mpd_response_finish(conn); stats = mpd_run_stats(conn); if (stats == NULL) { fprintf(stderr, "ERROR: MPD: Unable to retrieve MPD statistics\n"); return 0; } cur_mpd_stats_number_of_songs = mpd_stats_get_number_of_songs( stats ); if (DEBUG && dump_status) { fprintf(stderr, "DEBUG: [mgr-thread] mpd stats : => # of songs: %d\n", cur_mpd_stats_number_of_songs); } mpd_stats_free( stats ); return 1; }
/** * Return the success or error status of the last MPD command sent. */ bool Control::get_error_bool() { return (mpd_connection_get_error(conn->h()) == MPD_ERROR_SUCCESS); }
/* fetch a new db tree on root */ static int fetch_db_tree(DB_NODE **p_root,struct mpd_connection *conn) { if (*p_root) return 1; /* create root */ DB_NODE *root = (DB_NODE*)malloc(sizeof(DB_NODE)); root->type = DB_DIRECTORY; /* use calloc for root->uri to ease free_db_tree() */ root->uri = (char *)calloc(2,sizeof(char)); strncpy(root->uri,"/",1); root->rating = 0; root->duration = 0; root->p = NULL; root->s = NULL; root->c = NULL; root->num_c = 0; /* set top node */ DB_NODE *top = root; if (!mpd_send_list_all_meta(conn,"/")) { clear_or_exit_on_error(conn); return 1; } /* add nodes recursively */ struct mpd_entity *entity; while ((entity = mpd_recv_entity(conn))) { DB_NODE *node = (DB_NODE*)malloc(sizeof(DB_NODE)); const char *name = NULL; switch (mpd_entity_get_type(entity)) { case MPD_ENTITY_TYPE_DIRECTORY: node->type = DB_DIRECTORY; name = mpd_directory_get_path(mpd_entity_get_directory(entity)); assert (name && strlen(name)); node->uri = (char *)calloc(strlen(name)+1,sizeof(char)); strncpy(node->uri,name,strlen(name)); node->rating = 0; node->duration = 0; break; case MPD_ENTITY_TYPE_SONG: node->type = DB_SONG; name = mpd_song_get_uri(mpd_entity_get_song(entity)); assert (name && strlen(name)); node->uri = (char *)calloc(strlen(name)+1,sizeof(char)); strncpy(node->uri,name,strlen(name)); node->rating = 0; node->duration = mpd_song_get_duration(mpd_entity_get_song(entity)); break; case MPD_ENTITY_TYPE_PLAYLIST: node->type = DB_PLAYLIST; name = mpd_playlist_get_path(mpd_entity_get_playlist(entity)); assert (name && strlen(name)); node->uri = (char *)calloc(strlen(name)+1,sizeof(char)); strncpy(node->uri,name,strlen(name)); node->rating = 0; node->duration = 0; break; case MPD_ENTITY_TYPE_UNKNOWN: break; } /* backtrace top until it's parent of node */ while (top != root && !(strstr(node->uri,top->uri) && node->uri[strlen(top->uri)] == '/')) top = top->p; /* if current top already has chlidren */ if (top->c) { DB_NODE *node2 = top->c; /* find the last child */ while (node2->s) node2 = node2->s; node2->s = node; node->p = node2->p; node->p->num_c++; } else { top->c = node; node->p = top; node->p->num_c++; } /* no child, no next sibling */ node->c = NULL; node->s = NULL; node->num_c = 0; /* update top node */ if (node->type == DB_DIRECTORY) top = node; mpd_entity_free(entity); } if (mpd_connection_get_error(conn) == MPD_ERROR_SUCCESS) mpd_response_finish(conn); else if (!mpd_connection_clear_error(conn)) exit_on_error(conn); *p_root = root; return 0; }
/* * pgmpc_playlist * List all songs in given playlist. If not playlist is specified list * songs of current playlist. */ Datum pgmpc_playlist(PG_FUNCTION_ARGS) { TupleDesc tupdesc; Tuplestorestate *tupstore; char *playlist = NULL; bool ret; if (PG_NARGS() == 1 && !PG_ARGISNULL(0)) playlist = text_to_cstring(PG_GETARG_TEXT_PP(0)); /* Initialize function context */ pgmpc_init_setof_single(fcinfo, TEXTOID, "playlist", &tupdesc, &tupstore); /* * Run the command to get all the songs. */ pgmpc_init(); ret = playlist ? mpd_send_list_playlist_meta(mpd_conn, playlist) : mpd_send_list_queue_meta(mpd_conn); if (!ret) pgmpc_print_error(); /* Now get all the songs and send them back to caller */ while (true) { Datum values[1]; bool nulls[1]; struct mpd_song *song = mpd_recv_song(mpd_conn); /* Leave if done */ if (song == NULL) break; /* Assign song name */ nulls[0] = false; values[0] = CStringGetTextDatum(mpd_song_get_uri(song)); /* Save values */ tuplestore_putvalues(tupstore, tupdesc, values, nulls); /* Clean up for the next one */ mpd_song_free(song); } /* We may be in error state, so check for it */ if (mpd_connection_get_error(mpd_conn) != MPD_ERROR_SUCCESS) { const char *message = mpd_connection_get_error_message(mpd_conn); pgmpc_reset(); ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("mpd command failed: %s", message))); } /* Clean up */ pgmpc_reset(); /* clean up and return the tuplestore */ tuplestore_donestoring(tupstore); return (Datum) 0; }
int main(int argc, char ** argv) { struct mpd_connection *conn; conn = mpd_connection_new(NULL, 0, 30000); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) return handle_error(conn); { int i; for(i=0;i<3;i++) { printf("version[%i]: %i\n",i, mpd_connection_get_server_version(conn)[i]); } } if(argc==1) { struct mpd_status * status; struct mpd_song *song; const struct mpd_audio_format *audio_format; mpd_command_list_begin(conn, true); mpd_send_status(conn); mpd_send_current_song(conn); mpd_command_list_end(conn); status = mpd_recv_status(conn); if (status == NULL) return handle_error(conn); printf("volume: %i\n", mpd_status_get_volume(status)); printf("repeat: %i\n", mpd_status_get_repeat(status)); printf("queue version: %u\n", mpd_status_get_queue_version(status)); printf("queue length: %i\n", mpd_status_get_queue_length(status)); if (mpd_status_get_error(status) != NULL) printf("error: %s\n", mpd_status_get_error(status)); if (mpd_status_get_state(status) == MPD_STATE_PLAY || mpd_status_get_state(status) == MPD_STATE_PAUSE) { printf("song: %i\n", mpd_status_get_song_pos(status)); printf("elaspedTime: %i\n",mpd_status_get_elapsed_time(status)); printf("elasped_ms: %u\n", mpd_status_get_elapsed_ms(status)); printf("totalTime: %i\n", mpd_status_get_total_time(status)); printf("bitRate: %i\n", mpd_status_get_kbit_rate(status)); } audio_format = mpd_status_get_audio_format(status); if (audio_format != NULL) { printf("sampleRate: %i\n", audio_format->sample_rate); printf("bits: %i\n", audio_format->bits); printf("channels: %i\n", audio_format->channels); } mpd_status_free(status); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) return handle_error(conn); mpd_response_next(conn); while ((song = mpd_recv_song(conn)) != NULL) { printf("uri: %s\n", mpd_song_get_uri(song)); print_tag(song, MPD_TAG_ARTIST, "artist"); print_tag(song, MPD_TAG_ALBUM, "album"); print_tag(song, MPD_TAG_TITLE, "title"); print_tag(song, MPD_TAG_TRACK, "track"); print_tag(song, MPD_TAG_NAME, "name"); print_tag(song, MPD_TAG_DATE, "date"); if (mpd_song_get_duration(song) > 0) { printf("time: %u\n", mpd_song_get_duration(song)); } printf("pos: %u\n", mpd_song_get_pos(song)); mpd_song_free(song); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if(argc==3 && strcmp(argv[1],"lsinfo")==0) { struct mpd_entity * entity; if (!mpd_send_list_meta(conn, argv[2])) return handle_error(conn); while ((entity = mpd_recv_entity(conn)) != NULL) { const struct mpd_song *song; const struct mpd_directory *dir; const struct mpd_playlist *pl; switch (mpd_entity_get_type(entity)) { case MPD_ENTITY_TYPE_UNKNOWN: break; case MPD_ENTITY_TYPE_SONG: song = mpd_entity_get_song(entity); printf("uri: %s\n", mpd_song_get_uri(song)); print_tag(song, MPD_TAG_ARTIST, "artist"); print_tag(song, MPD_TAG_ALBUM, "album"); print_tag(song, MPD_TAG_TITLE, "title"); print_tag(song, MPD_TAG_TRACK, "track"); break; case MPD_ENTITY_TYPE_DIRECTORY: dir = mpd_entity_get_directory(entity); printf("directory: %s\n", mpd_directory_get_path(dir)); break; case MPD_ENTITY_TYPE_PLAYLIST: pl = mpd_entity_get_playlist(entity); printf("playlist: %s\n", mpd_playlist_get_path(pl)); break; } mpd_entity_free(entity); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if(argc==2 && strcmp(argv[1],"artists")==0) { struct mpd_pair *pair; if (!mpd_search_db_tags(conn, MPD_TAG_ARTIST) || !mpd_search_commit(conn)) return handle_error(conn); while ((pair = mpd_recv_pair_tag(conn, MPD_TAG_ARTIST)) != NULL) { printf("%s\n", pair->value); mpd_return_pair(conn, pair); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "playlists") == 0) { if (!mpd_send_list_playlists(conn)) return handle_error(conn); struct mpd_playlist *playlist; while ((playlist = mpd_recv_playlist(conn)) != NULL) { printf("%s\n", mpd_playlist_get_path(playlist)); mpd_playlist_free(playlist); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "idle") == 0) { enum mpd_idle idle = mpd_run_idle(conn); if (idle == 0 && mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) return handle_error(conn); for (unsigned j = 0;; ++j) { enum mpd_idle i = 1 << j; const char *name = mpd_idle_name(i); if (name == NULL) break; if (idle & i) printf("%s\n", name); } } else if (argc == 3 && strcmp(argv[1], "subscribe") == 0) { /* subscribe to a channel and print all messages */ if (!mpd_run_subscribe(conn, argv[2])) return handle_error(conn); while (mpd_run_idle_mask(conn, MPD_IDLE_MESSAGE) != 0) { if (!mpd_send_read_messages(conn)) return handle_error(conn); struct mpd_message *msg; while ((msg = mpd_recv_message(conn)) != NULL) { printf("%s\n", mpd_message_get_text(msg)); mpd_message_free(msg); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } return handle_error(conn); } else if (argc == 2 && strcmp(argv[1], "channels") == 0) { /* print a list of channels */ if (!mpd_send_channels(conn)) return handle_error(conn); struct mpd_pair *pair; while ((pair = mpd_recv_channel_pair(conn)) != NULL) { printf("%s\n", pair->value); mpd_return_pair(conn, pair); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(conn)) return handle_error(conn); } else if (argc == 4 && strcmp(argv[1], "message") == 0) { /* send a message to a channel */ if (!mpd_run_send_message(conn, argv[2], argv[3])) return handle_error(conn); } mpd_connection_free(conn); return 0; }
/*** main ***/ int main(int argc, char ** argv) { char * album = NULL, * artist = NULL, * icon = NULL, * notifystr = NULL, * title = NULL; GError * error = NULL; unsigned short int errcount = 0, state = MPD_STATE_UNKNOWN; const char * mpd_host = MPD_HOST, * music_dir = NULL, * uri = NULL;; unsigned mpd_port = MPD_PORT, mpd_timeout = MPD_TIMEOUT; struct mpd_song * song = NULL; unsigned int i; program = argv[0]; music_dir = getenv("XDG_MUSIC_DIR"); /* get the verbose status */ while ((i = getopt_long(argc, argv, optstring, options_long, NULL)) != -1) { switch (i) { case 'v': verbose++; break; } } /* reinitialize getopt() by resetting optind to 0 */ optind = 0; /* say hello */ if (verbose > 0) printf("%s: %s v%s (compiled: " __DATE__ ", " __TIME__ ")\n", program, PROGNAME, VERSION); /* get command line options */ while ((i = getopt_long(argc, argv, optstring, options_long, NULL)) != -1) { switch (i) { case 'h': fprintf(stderr, "usage: %s [-h] [-H HOST] [-p PORT] [-m MUSIC-DIR] [-v]\n", program); return EXIT_SUCCESS; case 'p': mpd_port = atoi(optarg); if (verbose > 0) printf("%s: using port %d\n", program, mpd_port); break; case 'm': music_dir = optarg; if (verbose > 0) printf("%s: using music-dir %s\n", program, music_dir); break; case 'H': mpd_host = optarg; if (verbose > 0) printf("%s: using host %s\n", program, mpd_host); break; } } /* disable artwork stuff if we are connected to a foreign host */ if (mpd_host != NULL) music_dir = NULL; /* change directory to music base directory */ if (music_dir != NULL) { if (chdir(music_dir) == -1) { fprintf(stderr, "%s: Can not change directory to '%s'.\n", program, music_dir); music_dir = NULL; } } /* libav */ av_register_all(); conn = mpd_connection_new(mpd_host, mpd_port, mpd_timeout); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { fprintf(stderr,"%s: %s\n", program, mpd_connection_get_error_message(conn)); mpd_connection_free(conn); exit(EXIT_FAILURE); } if(notify_init(PROGNAME) == FALSE) { fprintf(stderr, "%s: Can't create notify.\n", program); exit(EXIT_FAILURE); } notification = # if NOTIFY_CHECK_VERSION(0, 7, 0) notify_notification_new(TEXT_TOPIC, TEXT_NONE, ICON_SOUND); # else notify_notification_new(TEXT_TOPIC, TEXT_NONE, ICON_SOUND, NULL); # endif notify_notification_set_category(notification, PROGNAME); notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL); signal(SIGHUP, received_signal); signal(SIGINT, received_signal); signal(SIGTERM, received_signal); signal(SIGUSR1, received_signal); while(doexit == 0 && mpd_run_idle_mask(conn, MPD_IDLE_PLAYER)) { mpd_command_list_begin(conn, true); mpd_send_status(conn); mpd_send_current_song(conn); mpd_command_list_end(conn); state = mpd_status_get_state(mpd_recv_status(conn)); if (state == MPD_STATE_PLAY) { mpd_response_next(conn); song = mpd_recv_song(conn); uri = mpd_song_get_uri(song); if (music_dir != NULL && uri != NULL) icon = get_icon(music_dir, uri); if (verbose > 0 && icon != NULL) printf("%s: found icon: %s\n", program, icon); if ((title = g_markup_escape_text(mpd_song_get_tag(song, MPD_TAG_TITLE, 0), -1)) == NULL) title = strdup(TEXT_UNKNOWN); if ((artist = g_markup_escape_text(mpd_song_get_tag(song, MPD_TAG_ARTIST, 0), -1)) == NULL) artist = strdup(TEXT_UNKNOWN); if ((album = g_markup_escape_text(mpd_song_get_tag(song, MPD_TAG_ALBUM, 0), -1)) == NULL) album = strdup(TEXT_UNKNOWN); notifystr = malloc(sizeof(TEXT_PLAY) + strlen(title) + strlen(artist) + strlen(album)); sprintf(notifystr, TEXT_PLAY, title, artist, album); free(title); free(artist); free(album); mpd_song_free(song); } else if (state == MPD_STATE_PAUSE) notifystr = TEXT_PAUSE; else if (state == MPD_STATE_STOP) notifystr = TEXT_STOP; else notifystr = TEXT_UNKNOWN; if (verbose > 0) printf("%s: %s\n", program, notifystr); notify_notification_update(notification, TEXT_TOPIC, notifystr, icon ? icon : ICON_SOUND); notify_notification_set_timeout(notification, NOTIFICATION_TIMEOUT); while(notify_notification_show(notification, &error) == FALSE) { if (errcount > 1) { fprintf(stderr, "%s: Looks like we can not reconnect to notification daemon... Exiting.\n", program); exit(EXIT_FAILURE); } else { g_printerr("%s: Error \"%s\" while trying to show notification. Trying to reconnect.\n", program, error->message); errcount++; g_error_free(error); error = NULL; notify_uninit(); usleep(500 * 1000); if(notify_init(PROGNAME) == FALSE) { fprintf(stderr, "%s: Can't create notify.\n", program); exit(EXIT_FAILURE); } } } errcount = 0; if (state == MPD_STATE_PLAY) free(notifystr); if (icon != NULL) { free(icon); icon = NULL; } mpd_response_finish(conn); } if (verbose > 0) printf("Exiting...\n"); mpd_connection_free(conn); g_object_unref(G_OBJECT(notification)); notify_uninit(); return EXIT_SUCCESS; }