mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
Merge branch 'master' into sway-language-module
This commit is contained in:
@ -1,16 +1,23 @@
|
||||
#include "modules/mpd.hpp"
|
||||
#include "modules/mpd/mpd.hpp"
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "modules/mpd/state.hpp"
|
||||
#if defined(MPD_NOINLINE)
|
||||
namespace waybar::modules {
|
||||
#include "modules/mpd/state.inl.hpp"
|
||||
} // namespace waybar::modules
|
||||
#endif
|
||||
|
||||
waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "mpd", id, "{album} - {artist} - {title}", 5),
|
||||
module_name_(id.empty() ? "mpd" : "mpd#" + id),
|
||||
server_(nullptr),
|
||||
port_(config_["port"].isUInt() ? config["port"].asUInt() : 0),
|
||||
password_(config_["password"].empty() ? "" : config_["password"].asString()),
|
||||
timeout_(config_["timeout"].isUInt() ? config_["timeout"].asUInt() * 1'000 : 30'000),
|
||||
connection_(nullptr, &mpd_connection_free),
|
||||
alternate_connection_(nullptr, &mpd_connection_free),
|
||||
status_(nullptr, &mpd_status_free),
|
||||
song_(nullptr, &mpd_song_free) {
|
||||
if (!config_["port"].isNull() && !config_["port"].isUInt()) {
|
||||
@ -28,73 +35,33 @@ waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config)
|
||||
server_ = config["server"].asCString();
|
||||
}
|
||||
|
||||
event_listener().detach();
|
||||
|
||||
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &MPD::handlePlayPause));
|
||||
}
|
||||
|
||||
auto waybar::modules::MPD::update() -> void {
|
||||
std::lock_guard guard(connection_lock_);
|
||||
tryConnect();
|
||||
|
||||
if (connection_ != nullptr) {
|
||||
try {
|
||||
bool wasPlaying = playing();
|
||||
if(!wasPlaying) {
|
||||
// Wait until the periodic_updater has stopped
|
||||
std::lock_guard periodic_guard(periodic_lock_);
|
||||
}
|
||||
fetchState();
|
||||
if (!wasPlaying && playing()) {
|
||||
periodic_updater().detach();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("{}: {}", module_name_, e.what());
|
||||
state_ = MPD_STATE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
setLabel();
|
||||
context_.update();
|
||||
|
||||
// Call parent update
|
||||
ALabel::update();
|
||||
}
|
||||
|
||||
std::thread waybar::modules::MPD::event_listener() {
|
||||
return std::thread([this] {
|
||||
while (true) {
|
||||
try {
|
||||
if (connection_ == nullptr) {
|
||||
// Retry periodically if no connection
|
||||
dp.emit();
|
||||
std::this_thread::sleep_for(interval_);
|
||||
} else {
|
||||
waitForEvent();
|
||||
dp.emit();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
if (strcmp(e.what(), "Connection to MPD closed") == 0) {
|
||||
spdlog::debug("{}: {}", module_name_, e.what());
|
||||
} else {
|
||||
spdlog::warn("{}: {}", module_name_, e.what());
|
||||
}
|
||||
}
|
||||
void waybar::modules::MPD::queryMPD() {
|
||||
if (connection_ != nullptr) {
|
||||
spdlog::debug("{}: fetching state information", module_name_);
|
||||
try {
|
||||
fetchState();
|
||||
spdlog::debug("{}: fetch complete", module_name_);
|
||||
} catch (std::exception const& e) {
|
||||
spdlog::error("{}: {}", module_name_, e.what());
|
||||
state_ = MPD_STATE_UNKNOWN;
|
||||
}
|
||||
});
|
||||
|
||||
dp.emit();
|
||||
}
|
||||
}
|
||||
|
||||
std::thread waybar::modules::MPD::periodic_updater() {
|
||||
return std::thread([this] {
|
||||
std::lock_guard guard(periodic_lock_);
|
||||
while (connection_ != nullptr && playing()) {
|
||||
dp.emit();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
std::string waybar::modules::MPD::getTag(mpd_tag_type type, unsigned idx) {
|
||||
std::string waybar::modules::MPD::getTag(mpd_tag_type type, unsigned idx) const {
|
||||
std::string result =
|
||||
config_["unknown-tag"].isString() ? config_["unknown-tag"].asString() : "N/A";
|
||||
const char* tag = mpd_song_get_tag(song_.get(), type, idx);
|
||||
@ -133,7 +100,7 @@ void waybar::modules::MPD::setLabel() {
|
||||
auto format = format_;
|
||||
|
||||
std::string artist, album_artist, album, title, date;
|
||||
int song_pos, queue_length;
|
||||
int song_pos, queue_length;
|
||||
std::chrono::seconds elapsedTime, totalTime;
|
||||
|
||||
std::string stateIcon = "";
|
||||
@ -149,8 +116,8 @@ void waybar::modules::MPD::setLabel() {
|
||||
label_.get_style_context()->add_class("playing");
|
||||
label_.get_style_context()->remove_class("paused");
|
||||
} else if (paused()) {
|
||||
format =
|
||||
config_["format-paused"].isString() ? config_["format-paused"].asString() : config_["format"].asString();
|
||||
format = config_["format-paused"].isString() ? config_["format-paused"].asString()
|
||||
: config_["format"].asString();
|
||||
label_.get_style_context()->add_class("paused");
|
||||
label_.get_style_context()->remove_class("playing");
|
||||
}
|
||||
@ -216,7 +183,7 @@ void waybar::modules::MPD::setLabel() {
|
||||
}
|
||||
}
|
||||
|
||||
std::string waybar::modules::MPD::getStateIcon() {
|
||||
std::string waybar::modules::MPD::getStateIcon() const {
|
||||
if (!config_["state-icons"].isObject()) {
|
||||
return "";
|
||||
}
|
||||
@ -238,7 +205,7 @@ std::string waybar::modules::MPD::getStateIcon() {
|
||||
}
|
||||
}
|
||||
|
||||
std::string waybar::modules::MPD::getOptionIcon(std::string optionName, bool activated) {
|
||||
std::string waybar::modules::MPD::getOptionIcon(std::string optionName, bool activated) const {
|
||||
if (!config_[optionName + "-icons"].isObject()) {
|
||||
return "";
|
||||
}
|
||||
@ -261,25 +228,30 @@ void waybar::modules::MPD::tryConnect() {
|
||||
}
|
||||
|
||||
connection_ =
|
||||
unique_connection(mpd_connection_new(server_, port_, timeout_), &mpd_connection_free);
|
||||
detail::unique_connection(mpd_connection_new(server_, port_, timeout_), &mpd_connection_free);
|
||||
|
||||
alternate_connection_ =
|
||||
unique_connection(mpd_connection_new(server_, port_, timeout_), &mpd_connection_free);
|
||||
|
||||
if (connection_ == nullptr || alternate_connection_ == nullptr) {
|
||||
if (connection_ == nullptr) {
|
||||
spdlog::error("{}: Failed to connect to MPD", module_name_);
|
||||
connection_.reset();
|
||||
alternate_connection_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
checkErrors(connection_.get());
|
||||
spdlog::debug("{}: Connected to MPD", module_name_);
|
||||
|
||||
if (!password_.empty()) {
|
||||
bool res = mpd_run_password(connection_.get(), password_.c_str());
|
||||
if (!res) {
|
||||
spdlog::error("{}: Wrong MPD password", module_name_);
|
||||
connection_.reset();
|
||||
return;
|
||||
}
|
||||
checkErrors(connection_.get());
|
||||
}
|
||||
} catch (std::runtime_error& e) {
|
||||
spdlog::error("{}: Failed to connect to MPD: {}", module_name_, e.what());
|
||||
connection_.reset();
|
||||
alternate_connection_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,7 +264,6 @@ void waybar::modules::MPD::checkErrors(mpd_connection* conn) {
|
||||
case MPD_ERROR_CLOSED:
|
||||
mpd_connection_clear_error(conn);
|
||||
connection_.reset();
|
||||
alternate_connection_.reset();
|
||||
state_ = MPD_STATE_UNKNOWN;
|
||||
throw std::runtime_error("Connection to MPD closed");
|
||||
default:
|
||||
@ -306,37 +277,20 @@ void waybar::modules::MPD::checkErrors(mpd_connection* conn) {
|
||||
}
|
||||
|
||||
void waybar::modules::MPD::fetchState() {
|
||||
if (connection_ == nullptr) {
|
||||
spdlog::error("{}: Not connected to MPD", module_name_);
|
||||
return;
|
||||
}
|
||||
|
||||
auto conn = connection_.get();
|
||||
status_ = unique_status(mpd_run_status(conn), &mpd_status_free);
|
||||
|
||||
status_ = detail::unique_status(mpd_run_status(conn), &mpd_status_free);
|
||||
checkErrors(conn);
|
||||
|
||||
state_ = mpd_status_get_state(status_.get());
|
||||
checkErrors(conn);
|
||||
|
||||
song_ = unique_song(mpd_run_current_song(conn), &mpd_song_free);
|
||||
checkErrors(conn);
|
||||
}
|
||||
|
||||
void waybar::modules::MPD::waitForEvent() {
|
||||
auto conn = alternate_connection_.get();
|
||||
// Wait for a player (play/pause), option (random, shuffle, etc.), or playlist
|
||||
// change
|
||||
if (!mpd_send_idle_mask(
|
||||
conn, static_cast<mpd_idle>(MPD_IDLE_PLAYER | MPD_IDLE_OPTIONS | MPD_IDLE_QUEUE))) {
|
||||
checkErrors(conn);
|
||||
return;
|
||||
}
|
||||
// alternate_idle_ = true;
|
||||
|
||||
// See issue #277:
|
||||
// https://github.com/Alexays/Waybar/issues/277
|
||||
mpd_recv_idle(conn, /* disable_timeout = */ false);
|
||||
// See issue #281:
|
||||
// https://github.com/Alexays/Waybar/issues/281
|
||||
std::lock_guard guard(connection_lock_);
|
||||
|
||||
checkErrors(conn);
|
||||
mpd_response_finish(conn);
|
||||
|
||||
song_ = detail::unique_song(mpd_run_current_song(conn), &mpd_song_free);
|
||||
checkErrors(conn);
|
||||
}
|
||||
|
||||
@ -346,24 +300,13 @@ bool waybar::modules::MPD::handlePlayPause(GdkEventButton* const& e) {
|
||||
}
|
||||
|
||||
if (e->button == 1) {
|
||||
std::lock_guard guard(connection_lock_);
|
||||
if (stopped()) {
|
||||
mpd_run_play(connection_.get());
|
||||
} else {
|
||||
mpd_run_toggle_pause(connection_.get());
|
||||
}
|
||||
if (state_ == MPD_STATE_PLAY)
|
||||
context_.pause();
|
||||
else
|
||||
context_.play();
|
||||
} else if (e->button == 3) {
|
||||
std::lock_guard guard(connection_lock_);
|
||||
mpd_run_stop(connection_.get());
|
||||
context_.stop();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool waybar::modules::MPD::stopped() {
|
||||
return connection_ == nullptr || state_ == MPD_STATE_UNKNOWN || state_ == MPD_STATE_STOP || status_ == nullptr;
|
||||
}
|
||||
|
||||
bool waybar::modules::MPD::playing() { return connection_ != nullptr && state_ == MPD_STATE_PLAY; }
|
||||
|
||||
bool waybar::modules::MPD::paused() { return connection_ != nullptr && state_ == MPD_STATE_PAUSE; }
|
382
src/modules/mpd/state.cpp
Normal file
382
src/modules/mpd/state.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
#include "modules/mpd/state.hpp"
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "modules/mpd/mpd.hpp"
|
||||
#if defined(MPD_NOINLINE)
|
||||
namespace waybar::modules {
|
||||
#include "modules/mpd/state.inl.hpp"
|
||||
} // namespace waybar::modules
|
||||
#endif
|
||||
|
||||
namespace waybar::modules::detail {
|
||||
|
||||
#define IDLE_RUN_NOIDLE_AND_CMD(...) \
|
||||
if (idle_connection_.connected()) { \
|
||||
idle_connection_.disconnect(); \
|
||||
auto conn = ctx_->connection().get(); \
|
||||
if (!mpd_run_noidle(conn)) { \
|
||||
if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { \
|
||||
spdlog::error("mpd: Idle: failed to unregister for IDLE events"); \
|
||||
ctx_->checkErrors(conn); \
|
||||
} \
|
||||
} \
|
||||
__VA_ARGS__; \
|
||||
}
|
||||
|
||||
void Idle::play() {
|
||||
IDLE_RUN_NOIDLE_AND_CMD(mpd_run_play(conn));
|
||||
|
||||
ctx_->setState(std::make_unique<Playing>(ctx_));
|
||||
}
|
||||
|
||||
void Idle::pause() {
|
||||
IDLE_RUN_NOIDLE_AND_CMD(mpd_run_pause(conn, true));
|
||||
|
||||
ctx_->setState(std::make_unique<Paused>(ctx_));
|
||||
}
|
||||
|
||||
void Idle::stop() {
|
||||
IDLE_RUN_NOIDLE_AND_CMD(mpd_run_stop(conn));
|
||||
|
||||
ctx_->setState(std::make_unique<Stopped>(ctx_));
|
||||
}
|
||||
|
||||
#undef IDLE_RUN_NOIDLE_AND_CMD
|
||||
|
||||
void Idle::update() noexcept {
|
||||
// This is intentionally blank.
|
||||
}
|
||||
|
||||
void Idle::entry() noexcept {
|
||||
auto conn = ctx_->connection().get();
|
||||
assert(conn != nullptr);
|
||||
|
||||
if (!mpd_send_idle_mask(
|
||||
conn, static_cast<mpd_idle>(MPD_IDLE_PLAYER | MPD_IDLE_OPTIONS | MPD_IDLE_QUEUE))) {
|
||||
ctx_->checkErrors(conn);
|
||||
spdlog::error("mpd: Idle: failed to register for IDLE events");
|
||||
} else {
|
||||
spdlog::debug("mpd: Idle: watching FD");
|
||||
sigc::slot<bool, Glib::IOCondition const&> idle_slot = sigc::mem_fun(*this, &Idle::on_io);
|
||||
idle_connection_ =
|
||||
Glib::signal_io().connect(idle_slot,
|
||||
mpd_connection_get_fd(conn),
|
||||
Glib::IO_IN | Glib::IO_PRI | Glib::IO_ERR | Glib::IO_HUP);
|
||||
}
|
||||
}
|
||||
|
||||
void Idle::exit() noexcept {
|
||||
if (idle_connection_.connected()) {
|
||||
idle_connection_.disconnect();
|
||||
spdlog::debug("mpd: Idle: unwatching FD");
|
||||
}
|
||||
}
|
||||
|
||||
bool Idle::on_io(Glib::IOCondition const&) {
|
||||
auto conn = ctx_->connection().get();
|
||||
|
||||
// callback should do this:
|
||||
enum mpd_idle events = mpd_recv_idle(conn, /* ignore_timeout?= */ false);
|
||||
spdlog::debug("mpd: Idle: recv_idle events -> {}", events);
|
||||
|
||||
mpd_response_finish(conn);
|
||||
try {
|
||||
ctx_->checkErrors(conn);
|
||||
} catch (std::exception const& e) {
|
||||
spdlog::warn("mpd: Idle: error: {}", e.what());
|
||||
ctx_->setState(std::make_unique<Disconnected>(ctx_));
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx_->fetchState();
|
||||
mpd_state state = ctx_->state();
|
||||
|
||||
if (state == MPD_STATE_STOP) {
|
||||
ctx_->emit();
|
||||
ctx_->setState(std::make_unique<Stopped>(ctx_));
|
||||
} else if (state == MPD_STATE_PLAY) {
|
||||
ctx_->emit();
|
||||
ctx_->setState(std::make_unique<Playing>(ctx_));
|
||||
} else if (state == MPD_STATE_PAUSE) {
|
||||
ctx_->emit();
|
||||
ctx_->setState(std::make_unique<Paused>(ctx_));
|
||||
} else {
|
||||
ctx_->emit();
|
||||
// self transition
|
||||
ctx_->setState(std::make_unique<Idle>(ctx_));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Playing::entry() noexcept {
|
||||
sigc::slot<bool> timer_slot = sigc::mem_fun(*this, &Playing::on_timer);
|
||||
timer_connection_ = Glib::signal_timeout().connect(timer_slot, /* milliseconds */ 1'000);
|
||||
spdlog::debug("mpd: Playing: enabled 1 second periodic timer.");
|
||||
}
|
||||
|
||||
void Playing::exit() noexcept {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
spdlog::debug("mpd: Playing: disabled 1 second periodic timer.");
|
||||
}
|
||||
}
|
||||
|
||||
bool Playing::on_timer() {
|
||||
// Attempt to connect with MPD.
|
||||
try {
|
||||
ctx_->tryConnect();
|
||||
|
||||
// Success?
|
||||
if (!ctx_->is_connected()) {
|
||||
ctx_->setState(std::make_unique<Disconnected>(ctx_));
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx_->fetchState();
|
||||
|
||||
if (!ctx_->is_playing()) {
|
||||
if (ctx_->is_paused()) {
|
||||
ctx_->setState(std::make_unique<Paused>(ctx_));
|
||||
} else {
|
||||
ctx_->setState(std::make_unique<Stopped>(ctx_));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx_->queryMPD();
|
||||
ctx_->emit();
|
||||
} catch (std::exception const& e) {
|
||||
spdlog::warn("mpd: Playing: error: {}", e.what());
|
||||
ctx_->setState(std::make_unique<Disconnected>(ctx_));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Playing::stop() {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
|
||||
mpd_run_stop(ctx_->connection().get());
|
||||
}
|
||||
|
||||
ctx_->setState(std::make_unique<Stopped>(ctx_));
|
||||
}
|
||||
|
||||
void Playing::pause() {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
|
||||
mpd_run_pause(ctx_->connection().get(), true);
|
||||
}
|
||||
|
||||
ctx_->setState(std::make_unique<Paused>(ctx_));
|
||||
}
|
||||
|
||||
void Playing::update() noexcept { ctx_->do_update(); }
|
||||
|
||||
void Paused::entry() noexcept {
|
||||
sigc::slot<bool> timer_slot = sigc::mem_fun(*this, &Paused::on_timer);
|
||||
timer_connection_ = Glib::signal_timeout().connect(timer_slot, /* milliseconds */ 200);
|
||||
spdlog::debug("mpd: Paused: enabled 200 ms periodic timer.");
|
||||
}
|
||||
|
||||
void Paused::exit() noexcept {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
spdlog::debug("mpd: Paused: disabled 200 ms periodic timer.");
|
||||
}
|
||||
}
|
||||
|
||||
bool Paused::on_timer() {
|
||||
bool rc = true;
|
||||
|
||||
// Attempt to connect with MPD.
|
||||
try {
|
||||
ctx_->tryConnect();
|
||||
|
||||
// Success?
|
||||
if (!ctx_->is_connected()) {
|
||||
ctx_->setState(std::make_unique<Disconnected>(ctx_));
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx_->fetchState();
|
||||
|
||||
ctx_->emit();
|
||||
|
||||
if (ctx_->is_paused()) {
|
||||
ctx_->setState(std::make_unique<Idle>(ctx_));
|
||||
rc = false;
|
||||
} else if (ctx_->is_playing()) {
|
||||
ctx_->setState(std::make_unique<Playing>(ctx_));
|
||||
rc = false;
|
||||
} else if (ctx_->is_stopped()) {
|
||||
ctx_->setState(std::make_unique<Stopped>(ctx_));
|
||||
rc = false;
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
spdlog::warn("mpd: Paused: error: {}", e.what());
|
||||
ctx_->setState(std::make_unique<Disconnected>(ctx_));
|
||||
rc = false;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void Paused::play() {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
|
||||
mpd_run_play(ctx_->connection().get());
|
||||
}
|
||||
|
||||
ctx_->setState(std::make_unique<Playing>(ctx_));
|
||||
}
|
||||
|
||||
void Paused::stop() {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
|
||||
mpd_run_stop(ctx_->connection().get());
|
||||
}
|
||||
|
||||
ctx_->setState(std::make_unique<Stopped>(ctx_));
|
||||
}
|
||||
|
||||
void Paused::update() noexcept { ctx_->do_update(); }
|
||||
|
||||
void Stopped::entry() noexcept {
|
||||
sigc::slot<bool> timer_slot = sigc::mem_fun(*this, &Stopped::on_timer);
|
||||
timer_connection_ = Glib::signal_timeout().connect(timer_slot, /* milliseconds */ 200);
|
||||
spdlog::debug("mpd: Stopped: enabled 200 ms periodic timer.");
|
||||
}
|
||||
|
||||
void Stopped::exit() noexcept {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
spdlog::debug("mpd: Stopped: disabled 200 ms periodic timer.");
|
||||
}
|
||||
}
|
||||
|
||||
bool Stopped::on_timer() {
|
||||
bool rc = true;
|
||||
|
||||
// Attempt to connect with MPD.
|
||||
try {
|
||||
ctx_->tryConnect();
|
||||
|
||||
// Success?
|
||||
if (!ctx_->is_connected()) {
|
||||
ctx_->setState(std::make_unique<Disconnected>(ctx_));
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx_->fetchState();
|
||||
|
||||
ctx_->emit();
|
||||
|
||||
if (ctx_->is_stopped()) {
|
||||
ctx_->setState(std::make_unique<Idle>(ctx_));
|
||||
rc = false;
|
||||
} else if (ctx_->is_playing()) {
|
||||
ctx_->setState(std::make_unique<Playing>(ctx_));
|
||||
rc = false;
|
||||
} else if (ctx_->is_paused()) {
|
||||
ctx_->setState(std::make_unique<Paused>(ctx_));
|
||||
rc = false;
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
spdlog::warn("mpd: Stopped: error: {}", e.what());
|
||||
ctx_->setState(std::make_unique<Disconnected>(ctx_));
|
||||
rc = false;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void Stopped::play() {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
|
||||
mpd_run_play(ctx_->connection().get());
|
||||
}
|
||||
|
||||
ctx_->setState(std::make_unique<Playing>(ctx_));
|
||||
}
|
||||
|
||||
void Stopped::pause() {
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
|
||||
mpd_run_pause(ctx_->connection().get(), true);
|
||||
}
|
||||
|
||||
ctx_->setState(std::make_unique<Paused>(ctx_));
|
||||
}
|
||||
|
||||
void Stopped::update() noexcept { ctx_->do_update(); }
|
||||
|
||||
void Disconnected::arm_timer(int interval) noexcept {
|
||||
// unregister timer, if present
|
||||
disarm_timer();
|
||||
|
||||
// register timer
|
||||
sigc::slot<bool> timer_slot = sigc::mem_fun(*this, &Disconnected::on_timer);
|
||||
timer_connection_ =
|
||||
Glib::signal_timeout().connect(timer_slot, interval);
|
||||
spdlog::debug("mpd: Disconnected: enabled interval timer.");
|
||||
}
|
||||
|
||||
void Disconnected::disarm_timer() noexcept {
|
||||
// unregister timer, if present
|
||||
if (timer_connection_.connected()) {
|
||||
timer_connection_.disconnect();
|
||||
spdlog::debug("mpd: Disconnected: disabled interval timer.");
|
||||
}
|
||||
}
|
||||
|
||||
void Disconnected::entry() noexcept {
|
||||
arm_timer(1'000);
|
||||
}
|
||||
|
||||
void Disconnected::exit() noexcept {
|
||||
disarm_timer();
|
||||
}
|
||||
|
||||
bool Disconnected::on_timer() {
|
||||
// Attempt to connect with MPD.
|
||||
try {
|
||||
ctx_->tryConnect();
|
||||
|
||||
// Success?
|
||||
if (ctx_->is_connected()) {
|
||||
ctx_->fetchState();
|
||||
ctx_->emit();
|
||||
|
||||
if (ctx_->is_playing()) {
|
||||
ctx_->setState(std::make_unique<Playing>(ctx_));
|
||||
} else if (ctx_->is_paused()) {
|
||||
ctx_->setState(std::make_unique<Paused>(ctx_));
|
||||
} else {
|
||||
ctx_->setState(std::make_unique<Stopped>(ctx_));
|
||||
}
|
||||
|
||||
return false; // do not rearm timer
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
spdlog::warn("mpd: Disconnected: error: {}", e.what());
|
||||
}
|
||||
|
||||
arm_timer(ctx_->interval() * 1'000);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Disconnected::update() noexcept { ctx_->do_update(); }
|
||||
|
||||
} // namespace waybar::modules::detail
|
Reference in New Issue
Block a user