184 lines
4.0 KiB
C++
184 lines
4.0 KiB
C++
#ifndef _INTERFACES_MPD_HPP_
|
|
#define _INTERFACES_MPD_HPP_
|
|
|
|
#include <string>
|
|
#include <stdlib.h>
|
|
#include <memory>
|
|
#include <chrono>
|
|
#include <mpd/client.h>
|
|
|
|
#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<mpd_song> 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<struct mpd_status, StatusDeleter> status;
|
|
std::unique_ptr<Song> 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<struct mpd_status, StatusDeleter> 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<mpd_connection, ConnectionDeleter> 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();
|
|
void check_prerequisites();
|
|
void check_prerequisites_commands_list();
|
|
void check_errors();
|
|
|
|
public:
|
|
static std::shared_ptr<Connection> &get();
|
|
|
|
void connect();
|
|
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<Status> get_status();
|
|
std::unique_ptr<Song> 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
|