#pragma once #include #include #include #include "common.hpp" POLYBAR_NS // fwd class logger; namespace chrono = std::chrono; namespace mpd { DEFINE_ERROR(mpd_exception); DEFINE_CHILD_ERROR(client_error, mpd_exception); DEFINE_CHILD_ERROR(server_error, mpd_exception); void check_connection(mpd_connection* conn); void check_errors(mpd_connection* conn); // types details {{{ enum class connection_state { NONE = 0, CONNECTED, DISCONNECTED }; enum class mpdstate { UNKNOWN = 1 << 0, STOPPED = 1 << 1, PLAYING = 1 << 2, PAUSED = 1 << 4, }; namespace details { struct mpd_connection_deleter { void operator()(mpd_connection* conn); }; struct mpd_status_deleter { void operator()(mpd_status* status); }; struct mpd_song_deleter { void operator()(mpd_song* song); }; } using mpd_connection_t = unique_ptr; using mpd_status_t = unique_ptr; using mpd_song_t = unique_ptr; // }}} // class : mpdsong {{{ class mpdsong { public: explicit mpdsong(mpd_song_t&& song) : m_song(forward(song)) {} operator bool(); string get_artist(); string get_album(); string get_title(); unsigned get_duration(); private: mpd_song_t m_song; }; // }}} // class : mpdconnection {{{ class mpdstatus; class mpdconnection { public: explicit mpdconnection( const logger& logger, string host, unsigned int port = 6600, string password = "", unsigned int timeout = 15); void connect(); void disconnect(); bool connected(); bool retry_connection(int interval = 1); int get_fd(); void idle(); int noidle(); unique_ptr get_status(); unique_ptr get_status_safe(); unique_ptr get_song(); void play(); void pause(bool state); void toggle(); void stop(); void prev(); void next(); void seek(int songid, int pos); void set_repeat(bool mode); void set_random(bool mode); void set_single(bool mode); operator mpd_connection_t::element_type*(); protected: void check_prerequisites(); void check_prerequisites_commands_list(); private: const logger& m_log; mpd_connection_t m_connection; bool m_listactive = false; bool m_idle = false; int m_fd = -1; string m_host; unsigned int m_port; string m_password; unsigned int m_timeout; }; // }}} // class : mpdstatus {{{ class mpdstatus { public: explicit mpdstatus(mpdconnection* conn, bool autoupdate = true); void fetch_data(mpdconnection* conn); void update(int event, mpdconnection* connection); void update_timer(); bool random() const; bool repeat() const; bool single() const; bool match_state(mpdstate state) const; int get_songid() const; int get_queuelen() const; unsigned get_total_time() const; unsigned get_elapsed_time() const; unsigned get_elapsed_percentage(); string get_formatted_elapsed(); string get_formatted_total(); int get_seek_position(int percentage); private: mpd_status_t m_status; unique_ptr m_song; mpdstate m_state = mpdstate::UNKNOWN; chrono::system_clock::time_point m_updated_at; bool m_random = false; bool m_repeat = false; bool m_single = false; int m_songid; int m_queuelen; unsigned long m_total_time; unsigned long m_elapsed_time; unsigned long m_elapsed_time_ms; }; // }}} } POLYBAR_NS_END