2016-06-15 03:32:35 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <mpd/client.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <chrono>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "common.hpp"
|
|
|
|
#include "components/logger.hpp"
|
|
|
|
|
|
|
|
LEMONBUDDY_NS
|
|
|
|
|
|
|
|
namespace mpd {
|
|
|
|
DEFINE_ERROR(mpd_exception);
|
|
|
|
DEFINE_CHILD_ERROR(client_error, mpd_exception);
|
|
|
|
DEFINE_CHILD_ERROR(server_error, mpd_exception);
|
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
void check_connection(mpd_connection* conn);
|
|
|
|
void check_errors(mpd_connection* conn);
|
|
|
|
|
|
|
|
// types details {{{
|
|
|
|
|
|
|
|
enum class connection_state { NONE = 0, CONNECTED, DISCONNECTED };
|
2016-10-29 04:52:48 +00:00
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
enum class mpdstate {
|
|
|
|
UNKNOWN = 1 << 0,
|
|
|
|
STOPPED = 1 << 1,
|
|
|
|
PLAYING = 1 << 2,
|
|
|
|
PAUSED = 1 << 4,
|
|
|
|
};
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
namespace details {
|
|
|
|
struct mpd_connection_deleter {
|
2016-11-02 19:22:45 +00:00
|
|
|
void operator()(mpd_connection* conn);
|
2016-06-15 03:32:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct mpd_status_deleter {
|
2016-11-02 19:22:45 +00:00
|
|
|
void operator()(mpd_status* status);
|
2016-06-15 03:32:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct mpd_song_deleter {
|
2016-11-02 19:22:45 +00:00
|
|
|
void operator()(mpd_song* song);
|
2016-06-15 03:32:35 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
using mpd_connection_t = unique_ptr<mpd_connection, details::mpd_connection_deleter>;
|
|
|
|
using mpd_status_t = unique_ptr<mpd_status, details::mpd_status_deleter>;
|
|
|
|
using mpd_song_t = unique_ptr<mpd_song, details::mpd_song_deleter>;
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
// }}}
|
2016-11-02 19:22:45 +00:00
|
|
|
// class : mpdsong {{{
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
class mpdsong {
|
|
|
|
public:
|
2016-11-02 19:22:45 +00:00
|
|
|
explicit mpdsong(mpd_song_t&& song) : m_song(forward<decltype(song)>(song)) {}
|
|
|
|
|
|
|
|
operator bool();
|
|
|
|
|
|
|
|
string get_artist();
|
|
|
|
string get_album();
|
|
|
|
string get_title();
|
|
|
|
unsigned get_duration();
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
private:
|
2016-11-02 19:22:45 +00:00
|
|
|
mpd_song_t m_song;
|
2016-06-15 03:32:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// }}}
|
2016-11-02 19:22:45 +00:00
|
|
|
// class : mpdconnection {{{
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
class mpdstatus;
|
|
|
|
class mpdconnection {
|
|
|
|
public:
|
2016-10-29 04:52:48 +00:00
|
|
|
explicit mpdconnection(const logger& logger, string host, unsigned int port = 6600,
|
|
|
|
string password = "", unsigned int timeout = 15)
|
|
|
|
: m_log(logger), m_host(host), m_port(port), m_password(password), m_timeout(timeout) {}
|
2016-06-15 03:32:35 +00:00
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
void connect();
|
|
|
|
void disconnect();
|
|
|
|
bool connected();
|
|
|
|
bool retry_connection(int interval = 1);
|
2016-06-15 03:32:35 +00:00
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
int get_fd();
|
|
|
|
void idle();
|
|
|
|
int noidle();
|
|
|
|
|
|
|
|
unique_ptr<mpdstatus> get_status();
|
|
|
|
unique_ptr<mpdstatus> get_status_safe();
|
|
|
|
unique_ptr<mpdsong> get_song();
|
2016-06-15 03:32:35 +00:00
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
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();
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
const logger& m_log;
|
2016-11-02 19:22:45 +00:00
|
|
|
mpd_connection_t m_connection;
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
|
|
|
// }}}
|
2016-11-02 19:22:45 +00:00
|
|
|
// class : mpdstatus {{{
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
class mpdstatus {
|
|
|
|
public:
|
2016-11-02 19:22:45 +00:00
|
|
|
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;
|
2016-11-14 00:21:57 +00:00
|
|
|
int get_queuelen() const;
|
2016-11-02 19:22:45 +00:00
|
|
|
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);
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
private:
|
2016-11-02 19:22:45 +00:00
|
|
|
mpd_status_t m_status;
|
2016-06-15 03:32:35 +00:00
|
|
|
unique_ptr<mpdsong> 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;
|
2016-11-14 00:21:57 +00:00
|
|
|
int m_queuelen;
|
2016-06-15 03:32:35 +00:00
|
|
|
|
|
|
|
unsigned long m_total_time;
|
|
|
|
unsigned long m_elapsed_time;
|
|
|
|
unsigned long m_elapsed_time_ms;
|
|
|
|
};
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
}
|
|
|
|
|
|
|
|
LEMONBUDDY_NS_END
|