#ifndef _INTERFACES_MPD_HPP_ #define _INTERFACES_MPD_HPP_ #include #include #include #include #include #include "config.hpp" #include "lemonbuddy.hpp" #include "exception.hpp" #include "utils/math.hpp" namespace mpd { class Exception : public ::Exception { public: Exception(const std::string& msg, bool clearable) : ::Exception(msg + (clearable ? " (clearable)" : " (not clearable)")){} }; class ClientError : public Exception { public: ClientError(const std::string& msg, mpd_error code, bool clearable) : Exception("[mpd::ClientError::"+ std::to_string(code) +"] "+ msg, clearable){} }; class ServerError : public Exception { public: ServerError(const std::string& msg, mpd_server_error code, bool clearable) : Exception("[mpd::ServerError::"+ std::to_string(code) +"] "+ msg, clearable){} }; enum State { UNKNOWN = 1 << 0, STOPPED = 1 << 1, PLAYING = 1 << 2, PAUSED = 1 << 4, }; struct Song { Song(){} Song(mpd_song *song); std::shared_ptr song; std::string get_artist(); std::string get_album(); std::string get_title(); unsigned get_duration(); operator bool() { return this->song.get() != nullptr; } }; struct Status { struct StatusDeleter { void operator()(mpd_status *status) { mpd_status_free(status); } }; Status(mpd_status *status); std::unique_ptr status; std::unique_ptr song; std::chrono::system_clock::time_point updated_at; int state = UNKNOWN; bool random = false, repeat = false, single = false; int song_id; unsigned long total_time; unsigned long elapsed_time; unsigned long elapsed_time_ms; void set(std::unique_ptr status); void update(int event); void update_timer(); unsigned get_total_time(); unsigned get_elapsed_time(); unsigned get_elapsed_percentage(); std::string get_formatted_elapsed(); std::string get_formatted_total(); }; class Connection { struct ConnectionDeleter { void operator()(mpd_connection *connection) { if (connection == nullptr) return; //TRACE("Releasing mpd_connection"); mpd_connection_free(connection); } }; std::unique_ptr connection; std::string host = MPD_HOST; std::string password = MPD_PASSWORD; int port = MPD_PORT; int timeout = 15; bool mpd_command_list_active = false; bool mpd_idle = false; int mpd_fd; void check_connection() throw(ClientError); void check_prerequisites(); void check_prerequisites_commands_list(); void check_errors() throw(ClientError, ServerError); public: static std::shared_ptr &get(); void connect() throw (ClientError); void disconnect(); bool connected(); bool retry_connection(int interval = 1); void idle(); int noidle(); void set_host(const std::string& host) { this->host = host; } void set_port(int port) { this->port = port; } void set_password(const std::string& password) { this->password = password; } void set_timeout(int timeout) { this->timeout = timeout; } std::unique_ptr get_status(); std::unique_ptr get_song(); void play(); void pause(bool state); void toggle(); void stop(); void prev(); void next(); void seek(int percentage); void repeat(bool mode); void random(bool mode); void single(bool mode); }; struct MpdStatus { bool random, repeat, single; std::string artist; std::string album; std::string title; int elapsed_time = 0; int total_time = 0; float get_elapsed_percentage(); std::string get_formatted_elapsed(); std::string get_formatted_total(); operator bool() { return !this->artist.empty() && !this->title.empty(); } }; } #endif