polybar-dwm/include/interfaces/mpd.hpp
2016-06-29 11:06:44 +02:00

189 lines
4.2 KiB
C++

#pragma once
#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(std::string msg, bool clearable)
: ::Exception(msg + (clearable ? " (clearable)" : " (not clearable)")){}
};
class ClientError : public Exception
{
public:
explicit ClientError(std::string msg, mpd_error code, bool clearable)
: Exception("[mpd::ClientError::"+ std::to_string(code) +"] "+ msg, clearable){}
};
class ServerError : public Exception
{
public:
ServerError(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(){}
explicit 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;
}
};
class Connection;
struct Status
{
struct StatusDeleter
{
void operator()(mpd_status *status) {
mpd_status_free(status);
}
};
explicit 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, std::unique_ptr<Connection>& connection);
void update(int event, Connection *connection);
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;
std::string password;
int port = 6600;
int timeout = 15;
bool mpd_command_list_active = false;
bool mpd_idle = false;
int mpd_fd = -1;
void check_prerequisites();
void check_prerequisites_commands_list();
public:
Connection(std::string host, int port, std::string password)
: host(host), password(password), port(port) {}
void connect();
void disconnect();
bool connected();
// bool retry_connection(int interval = 1);
void idle();
int noidle();
void set_host(std::string host) { this->host = host; }
void set_port(int port) { this->port = port; }
void set_password(std::string password) { this->password = password; }
void set_timeout(int timeout) { this->timeout = timeout; }
std::unique_ptr<Status> get_status(bool update = true);
std::unique_ptr<Status> get_status_safe(bool update = true);
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 set_repeat(bool mode);
void set_random(bool mode);
void set_single(bool mode);
};
struct MpdStatus
{
bool random = false,
repeat = false,
single = false;
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();
}
};
}