int mpd_put_outputs(char *buffer, int names) { struct mpd_output *out; int nout; char *str, *strend; str = buffer; strend = buffer+MAX_SIZE; str += snprintf(str, strend-str, "{\"type\":\"%s\", \"data\":{", names ? "outputnames" : "outputs"); mpd_send_outputs(mpd.conn); nout = 0; while ((out = mpd_recv_output(mpd.conn)) != NULL) { if (nout++) *str++ = ','; if (names) str += snprintf(str, strend - str, " \"%d\":\"%s\"", mpd_output_get_id(out), mpd_output_get_name(out)); else str += snprintf(str, strend-str, " \"%d\":%d", mpd_output_get_id(out), mpd_output_get_enabled(out)); mpd_output_free(out); } if (!mpd_response_finish(mpd.conn)) { fprintf(stderr, "MPD outputs: %s\n", mpd_connection_get_error_message(mpd.conn)); mpd_connection_clear_error(mpd.conn); return 0; } str += snprintf(str, strend-str, " }}"); return str-buffer; }
static gboolean lmc_reconnect(G_GNUC_UNUSED gpointer data) { const unsigned *version; g_mpd = mpd_connection_new(g_host, g_port, 0); if (mpd_connection_get_error(g_mpd) != MPD_ERROR_SUCCESS) { lmc_failure(); return true; } idle_supported = mpd_connection_cmp_server_version(g_mpd, 0, 14, 0) >= 0; version = mpd_connection_get_server_version(g_mpd); char *name = connection_settings_name(g_mpd); g_message("connected to mpd %i.%i.%i at %s\n", version[0], version[1], version[2], name); g_free(name); #if LIBMPDCLIENT_CHECK_VERSION(2,5,0) subscribed = mpd_run_subscribe(g_mpd, "mpdscribble"); if (!subscribed && !mpd_connection_clear_error(g_mpd)) { lmc_failure(); return true; } #endif lmc_schedule_update(); reconnect_source_id = 0; return false; }
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); } } }
static gboolean lmc_idle(G_GNUC_UNUSED GIOChannel *source, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer data) { bool success; enum mpd_idle idle; assert(idle_source_id != 0); assert(g_mpd != NULL); assert(mpd_connection_get_error(g_mpd) == MPD_ERROR_SUCCESS); idle_source_id = 0; idle = mpd_recv_idle(g_mpd, false); success = mpd_response_finish(g_mpd); if (!success && mpd_connection_get_error(g_mpd) == MPD_ERROR_SERVER && mpd_connection_get_server_error(g_mpd) == MPD_SERVER_ERROR_UNKNOWN_CMD && mpd_connection_clear_error(g_mpd)) { /* MPD does not recognize the "idle" command - disable it for this connection */ g_message("MPD does not support the 'idle' command - " "falling back to polling\n"); idle_supported = false; lmc_schedule_update(); return false; } if (!success) { lmc_failure(); lmc_schedule_reconnect(); return false; } #if LIBMPDCLIENT_CHECK_VERSION(2,5,0) if (subscribed && (idle & MPD_IDLE_MESSAGE) != 0 && !lmc_read_messages()) { lmc_failure(); lmc_schedule_reconnect(); return false; } #endif if (idle & MPD_IDLE_PLAYER) /* there was a change: query MPD */ lmc_schedule_update(); else /* nothing interesting: re-enter idle */ lmc_schedule_idle(); return false; }
static void mpd_report_error(void) { const gchar *error = mpd_connection_get_error_message(mpd.conn); g_warning("MPD error: %s", error); irc_say("MPD error: %s", error); if (mpd_connection_clear_error(mpd.conn)) { g_warning("Unable to recover, reconnecting"); mpd_disconnect(); mpd_schedule_reconnect(); } }
static bool check_error(struct mpd_connection *client) { if (mpd_connection_get_error(client) != MPD_ERROR_SUCCESS) { printf("Error: %s (Retry in 1 second...)\n", mpd_connection_get_error_message(client)); if (!mpd_connection_clear_error(client)) { mpd_connection_free(client); sleep(1); return true; } } return (client == NULL); }
bool check_error(struct mpd_connection *con, FILE *logfile, bool exit_on_failure) { if (mpd_connection_get_error(con) != MPD_ERROR_SUCCESS) { if (logfile) fprintf(logfile, "MPD error: %s\n", mpd_connection_get_error_message(con)); if (exit_on_failure || !mpd_connection_clear_error(con)) { mpd_connection_free(con); exit(EXIT_FAILURE); } return true; } return false; }
static bool lmc_read_messages(void) { assert(subscribed); if (!mpd_send_read_messages(g_mpd)) return mpd_connection_clear_error(g_mpd); struct mpd_message *msg; while ((msg = mpd_recv_message(g_mpd)) != NULL) { const char *text = mpd_message_get_text(msg); if (strcmp(text, "love") == 0) love = true; else g_message("Unrecognized client-to-client message: '%s'", text); mpd_message_free(msg); } return mpd_response_finish(g_mpd); }
bool path_prepare(struct mpd_connection *conn) { if (initialized) return true; initialized = true; if (mpd_connection_cmp_server_version(conn, 0, 17, 0) < 0) /* the "config" command was added in MPD 0.17.1 */ return true; if (!mpd_send_command(conn, "config", NULL)) return false; struct mpd_pair *pair = mpd_recv_pair_named(conn, "music_directory"); if (pair != NULL) { music_directory = strdup(pair->value); mpd_return_pair(conn, pair); } return mpd_response_finish(conn) || mpd_connection_clear_error(conn); }
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; }
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; }
/* 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; } } }
/* 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; }
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; }
/* * Clears any error */ void Control::clearerror() { mpd_connection_clear_error(conn->h()); }