/* 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; } } }
bool mpd_run_previous(struct mpd_connection *connection) { return mpd_run_check(connection) && mpd_send_previous(connection) && mpd_response_finish(connection); }