polybar-dwm/include/modules/mpd.hpp
Patrick Ziegler 26be83f893
module: Implement action router (#2336)
* module: Implement proof of concept action router

Action implementation inside module becomes much cleaner because each
module just registers action names together with a callback (pointer to
member function) and the action router does the rest.

* Make input function final

This forces all modules to use the action router

* modules: Catch exceptions in action handlers

* Use action router for all modules

* Use action_ prefix for function names

The mpd module's 'stop' action overwrote the base module's stop function
which caused difficult to debug behavior.

To prevent this in the future we now prefix each function that is
responsible for an action with 'action_'

* Cleanup

* actions: Throw exception when re-registering action

Action names are unique inside modules. Unfortunately there is no way to
ensure this statically, the next best thing is to crash the module and
let the user know that this is a bug.

* Formatting

* actions: Ignore data for actions without data

This is the same behavior as before.

* action_router: Write tests
2021-01-04 10:25:52 +01:00

120 lines
4.0 KiB
C++

#pragma once
#include <chrono>
#include "adapters/mpd.hpp"
#include "modules/meta/event_module.hpp"
#include "utils/env.hpp"
POLYBAR_NS
using namespace mpd;
namespace modules {
class mpd_module : public event_module<mpd_module> {
public:
explicit mpd_module(const bar_settings&, string);
void teardown();
inline bool connected() const;
void idle();
bool has_event();
bool update();
string get_format() const;
string get_output();
bool build(builder* builder, const string& tag) const;
static constexpr auto TYPE = "internal/mpd";
static constexpr const char* EVENT_PLAY = "play";
static constexpr const char* EVENT_PAUSE = "pause";
static constexpr const char* EVENT_STOP = "stop";
static constexpr const char* EVENT_PREV = "prev";
static constexpr const char* EVENT_NEXT = "next";
static constexpr const char* EVENT_REPEAT = "repeat";
static constexpr const char* EVENT_SINGLE = "single";
static constexpr const char* EVENT_RANDOM = "random";
static constexpr const char* EVENT_CONSUME = "consume";
static constexpr const char* EVENT_SEEK = "seek";
private:
void action_play();
void action_pause();
void action_stop();
void action_prev();
void action_next();
void action_repeat();
void action_single();
void action_random();
void action_consume();
void action_seek(const string& data);
private:
static constexpr const char* FORMAT_ONLINE{"format-online"};
static constexpr const char* FORMAT_PLAYING{"format-playing"};
static constexpr const char* FORMAT_PAUSED{"format-paused"};
static constexpr const char* FORMAT_STOPPED{"format-stopped"};
static constexpr const char* TAG_BAR_PROGRESS{"<bar-progress>"};
static constexpr const char* TAG_TOGGLE{"<toggle>"};
static constexpr const char* TAG_TOGGLE_STOP{"<toggle-stop>"};
static constexpr const char* TAG_LABEL_SONG{"<label-song>"};
static constexpr const char* TAG_LABEL_TIME{"<label-time>"};
static constexpr const char* TAG_ICON_RANDOM{"<icon-random>"};
static constexpr const char* TAG_ICON_REPEAT{"<icon-repeat>"};
/*
* Deprecated
*/
static constexpr const char* TAG_ICON_REPEAT_ONE{"<icon-repeatone>"};
/*
* Replaces icon-repeatone
*
* repeatone is misleading, since it doesn't actually affect the repeating behaviour
*/
static constexpr const char* TAG_ICON_SINGLE{"<icon-single>"};
static constexpr const char* TAG_ICON_CONSUME{"<icon-consume>"};
static constexpr const char* TAG_ICON_PREV{"<icon-prev>"};
static constexpr const char* TAG_ICON_STOP{"<icon-stop>"};
static constexpr const char* TAG_ICON_PLAY{"<icon-play>"};
static constexpr const char* TAG_ICON_PAUSE{"<icon-pause>"};
static constexpr const char* TAG_ICON_NEXT{"<icon-next>"};
static constexpr const char* TAG_ICON_SEEKB{"<icon-seekb>"};
static constexpr const char* TAG_ICON_SEEKF{"<icon-seekf>"};
static constexpr const char* FORMAT_OFFLINE{"format-offline"};
static constexpr const char* TAG_LABEL_OFFLINE{"<label-offline>"};
unique_ptr<mpdconnection> m_mpd;
/*
* Stores the mpdstatus instance for the current connection
* m_status is not initialized if mpd is not connect, you always have to
* make sure that m_status is not NULL before dereferencing it
*/
unique_ptr<mpdstatus> m_status;
string m_host{env_util::get("MPD_HOST", "127.0.0.1")};
string m_pass;
unsigned int m_port{6600U};
chrono::system_clock::time_point m_lastsync{};
float m_synctime{1.0f};
int m_quick_attempts{0};
// This flag is used to let thru a broadcast once every time
// the connection state changes
connection_state m_statebroadcasted{connection_state::NONE};
progressbar_t m_bar_progress;
iconset_t m_icons;
label_t m_label_song;
label_t m_label_time;
label_t m_label_offline;
rgba m_toggle_on_color;
rgba m_toggle_off_color;
};
} // namespace modules
POLYBAR_NS_END