refactor: Drop tokenized labels

Handle placeholder tokens inside each label
instead of cloning into a new instance each time
This commit is contained in:
Michael Carlberg 2016-10-19 01:26:17 +02:00
parent 37e367eb79
commit 68f72d69cc
19 changed files with 185 additions and 209 deletions

View File

@ -154,7 +154,7 @@ class builder {
if (!label || !*label) if (!label || !*label)
return; return;
auto text = label->m_text; auto text = label->get();
if (label->m_maxlen > 0 && text.length() > label->m_maxlen) { if (label->m_maxlen > 0 && text.length() > label->m_maxlen) {
text = text.substr(0, label->m_maxlen) + "..."; text = text.substr(0, label->m_maxlen) + "...";

View File

@ -105,4 +105,7 @@ struct action_block {
#endif #endif
}; };
struct wmsettings_bspwm {
};
LEMONBUDDY_NS_END LEMONBUDDY_NS_END

View File

@ -14,23 +14,21 @@ namespace drawtypes {
class label : public non_copyable_mixin<label> { class label : public non_copyable_mixin<label> {
public: public:
string m_text{""}; string m_foreground;
string m_foreground{""}; string m_background;
string m_background{""}; string m_underline;
string m_underline{""}; string m_overline;
string m_overline{""}; int m_font = 0;
int m_font{0}; int m_padding = 0;
int m_padding{0}; int m_margin = 0;
int m_margin{0}; size_t m_maxlen = 0;
size_t m_maxlen{0}; bool m_ellipsis = true;
bool m_ellipsis{true};
explicit label(string text, int font) : m_text(text), m_font(font) {} explicit label(string text, int font) : m_font(font), m_text(text), m_tokenized(m_text) {}
explicit label(string text, string foreground = "", string background = "", explicit label(string text, string foreground = "", string background = "",
string underline = "", string overline = "", int font = 0, int padding = 0, int margin = 0, string underline = "", string overline = "", int font = 0, int padding = 0, int margin = 0,
size_t maxlen = 0, bool ellipsis = true) size_t maxlen = 0, bool ellipsis = true)
: m_text(text) : m_foreground(foreground)
, m_foreground(foreground)
, m_background(background) , m_background(background)
, m_underline(underline) , m_underline(underline)
, m_overline(overline) , m_overline(overline)
@ -38,7 +36,13 @@ namespace drawtypes {
, m_padding(padding) , m_padding(padding)
, m_margin(margin) , m_margin(margin)
, m_maxlen(maxlen) , m_maxlen(maxlen)
, m_ellipsis(ellipsis) {} , m_ellipsis(ellipsis)
, m_text(text)
, m_tokenized(m_text) {}
string get() const {
return m_tokenized;
}
operator bool() { operator bool() {
return !m_text.empty(); return !m_text.empty();
@ -49,8 +53,12 @@ namespace drawtypes {
m_padding, m_margin, m_maxlen, m_ellipsis)}; m_padding, m_margin, m_maxlen, m_ellipsis)};
} }
void reset_tokens() {
m_tokenized = m_text;
}
void replace_token(string token, string replacement) { void replace_token(string token, string replacement) {
m_text = string_util::replace_all(m_text, token, replacement); m_tokenized = string_util::replace_all(m_tokenized, token, replacement);
} }
void replace_defined_values(label_t label) { void replace_defined_values(label_t label) {
@ -63,6 +71,9 @@ namespace drawtypes {
if (!label->m_overline.empty()) if (!label->m_overline.empty())
m_overline = label->m_overline; m_overline = label->m_overline;
} }
private:
string m_text, m_tokenized;
}; };
inline label_t get_config_label(const config& conf, string section, string name = "label", inline label_t get_config_label(const config& conf, string section, string name = "label",

View File

@ -27,9 +27,6 @@ namespace modules {
if (m_formatter->has(TAG_RAMP)) if (m_formatter->has(TAG_RAMP))
m_ramp = get_config_ramp(m_conf, name(), TAG_RAMP); m_ramp = get_config_ramp(m_conf, name(), TAG_RAMP);
if (m_label)
m_tokenized = m_label->clone();
// Build path to the file where the current/maximum brightness value is located // Build path to the file where the current/maximum brightness value is located
m_path_val = string_util::replace(PATH_BACKLIGHT_VAL, "%card%", card); m_path_val = string_util::replace(PATH_BACKLIGHT_VAL, "%card%", card);
m_path_max = string_util::replace(PATH_BACKLIGHT_MAX, "%card%", card); m_path_max = string_util::replace(PATH_BACKLIGHT_MAX, "%card%", card);
@ -55,22 +52,21 @@ namespace modules {
m_percentage = static_cast<int>(float(m_val) / float(m_max) * 100.0f + 0.5f); m_percentage = static_cast<int>(float(m_val) / float(m_max) * 100.0f + 0.5f);
if (!m_label) if (m_label) {
return true; m_label->reset_tokens();
m_label->replace_token("%percentage%", to_string(m_percentage) + "%");
m_tokenized->m_text = m_label->m_text; }
m_tokenized->replace_token("%percentage%", to_string(m_percentage) + "%");
return true; return true;
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_BAR) if (tag == TAG_BAR)
builder->node(m_progressbar->output(m_percentage)); builder->node(m_progressbar->output(m_percentage));
else if (tag == TAG_RAMP) else if (tag == TAG_RAMP)
builder->node(m_ramp->get_by_percentage(m_percentage)); builder->node(m_ramp->get_by_percentage(m_percentage));
else if (tag == TAG_LABEL) else if (tag == TAG_LABEL)
builder->node(m_tokenized); builder->node(m_label);
else else
return false; return false;
return true; return true;
@ -87,7 +83,6 @@ namespace modules {
ramp_t m_ramp; ramp_t m_ramp;
label_t m_label; label_t m_label;
label_t m_tokenized;
progressbar_t m_progressbar; progressbar_t m_progressbar;
string m_path_val; string m_path_val;

View File

@ -57,16 +57,13 @@ namespace modules {
if (m_formatter->has(TAG_LABEL_CHARGING, FORMAT_CHARGING)) { if (m_formatter->has(TAG_LABEL_CHARGING, FORMAT_CHARGING)) {
m_label_charging = m_label_charging =
get_optional_config_label(m_conf, name(), TAG_LABEL_CHARGING, "%percentage%"); get_optional_config_label(m_conf, name(), TAG_LABEL_CHARGING, "%percentage%");
m_label_charging_tokenized = m_label_charging->clone();
} }
if (m_formatter->has(TAG_LABEL_DISCHARGING, FORMAT_DISCHARGING)) { if (m_formatter->has(TAG_LABEL_DISCHARGING, FORMAT_DISCHARGING)) {
m_label_discharging = m_label_discharging =
get_optional_config_label(m_conf, name(), TAG_LABEL_DISCHARGING, "%percentage%"); get_optional_config_label(m_conf, name(), TAG_LABEL_DISCHARGING, "%percentage%");
m_label_discharging_tokenized = m_label_discharging->clone();
} }
if (m_formatter->has(TAG_LABEL_FULL, FORMAT_FULL)) { if (m_formatter->has(TAG_LABEL_FULL, FORMAT_FULL)) {
m_label_full = get_optional_config_label(m_conf, name(), TAG_LABEL_FULL, "%percentage%"); m_label_full = get_optional_config_label(m_conf, name(), TAG_LABEL_FULL, "%percentage%");
m_label_full_tokenized = m_label_full->clone();
} }
// }}} // }}}
@ -124,17 +121,17 @@ namespace modules {
return false; return false;
} }
if (m_label_charging_tokenized) { if (m_label_charging) {
m_label_charging_tokenized->m_text = m_label_charging->m_text; m_label_charging->reset_tokens();
m_label_charging_tokenized->replace_token("%percentage%", to_string(percentage) + "%"); m_label_charging->replace_token("%percentage%", to_string(percentage) + "%");
} }
if (m_label_discharging_tokenized) { if (m_label_discharging) {
m_label_discharging_tokenized->m_text = m_label_discharging->m_text; m_label_discharging->reset_tokens();
m_label_discharging_tokenized->replace_token("%percentage%", to_string(percentage) + "%"); m_label_discharging->replace_token("%percentage%", to_string(percentage) + "%");
} }
if (m_label_full_tokenized) { if (m_label_full) {
m_label_full_tokenized->m_text = m_label_full->m_text; m_label_full->reset_tokens();
m_label_full_tokenized->replace_token("%percentage%", to_string(percentage) + "%"); m_label_full->replace_token("%percentage%", to_string(percentage) + "%");
} }
m_state = state; m_state = state;
@ -143,7 +140,7 @@ namespace modules {
return true; return true;
} }
string get_format() { string get_format() const {
if (m_state == STATE_FULL) if (m_state == STATE_FULL)
return FORMAT_FULL; return FORMAT_FULL;
else if (m_state == STATE_CHARGING) else if (m_state == STATE_CHARGING)
@ -152,7 +149,7 @@ namespace modules {
return FORMAT_DISCHARGING; return FORMAT_DISCHARGING;
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_ANIMATION_CHARGING) if (tag == TAG_ANIMATION_CHARGING)
builder->node(m_animation_charging->get()); builder->node(m_animation_charging->get());
else if (tag == TAG_BAR_CAPACITY) { else if (tag == TAG_BAR_CAPACITY) {
@ -160,11 +157,11 @@ namespace modules {
} else if (tag == TAG_RAMP_CAPACITY) } else if (tag == TAG_RAMP_CAPACITY)
builder->node(m_ramp_capacity->get_by_percentage(m_percentage)); builder->node(m_ramp_capacity->get_by_percentage(m_percentage));
else if (tag == TAG_LABEL_CHARGING) else if (tag == TAG_LABEL_CHARGING)
builder->node(m_label_charging_tokenized); builder->node(m_label_charging);
else if (tag == TAG_LABEL_DISCHARGING) else if (tag == TAG_LABEL_DISCHARGING)
builder->node(m_label_discharging_tokenized); builder->node(m_label_discharging);
else if (tag == TAG_LABEL_FULL) else if (tag == TAG_LABEL_FULL)
builder->node(m_label_full_tokenized); builder->node(m_label_full);
else else
return false; return false;
return true; return true;
@ -222,11 +219,8 @@ namespace modules {
ramp_t m_ramp_capacity; ramp_t m_ramp_capacity;
progressbar_t m_bar_capacity; progressbar_t m_bar_capacity;
label_t m_label_charging; label_t m_label_charging;
label_t m_label_charging_tokenized;
label_t m_label_discharging; label_t m_label_discharging;
label_t m_label_discharging_tokenized;
label_t m_label_full; label_t m_label_full;
label_t m_label_full_tokenized;
string m_battery; string m_battery;
string m_adapter; string m_adapter;

View File

@ -269,8 +269,9 @@ namespace modules {
if (!monitor_focused) if (!monitor_focused)
label->replace_defined_values(m_statelabels.find(bspwm_flag::WORKSPACE_DIMMED)->second); label->replace_defined_values(m_statelabels.find(bspwm_flag::WORKSPACE_DIMMED)->second);
label->reset_tokens();
label->replace_token("%name%", value); label->replace_token("%name%", value);
label->replace_token("%icon%", icon->m_text); label->replace_token("%icon%", icon->get());
label->replace_token("%index%", to_string(++workspace_n)); label->replace_token("%index%", to_string(++workspace_n));
m_workspaces.emplace_back(make_unique<bspwm_workspace>(workspace_flag, std::move(label))); m_workspaces.emplace_back(make_unique<bspwm_workspace>(workspace_flag, std::move(label)));
@ -286,14 +287,14 @@ namespace modules {
return true; return true;
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag != TAG_LABEL_STATE) if (tag != TAG_LABEL_STATE)
return false; return false;
int workspace_n = 0; int workspace_n = 0;
for (auto&& ws : m_workspaces) { for (auto&& ws : m_workspaces) {
if (!ws.get()->label->m_text.empty()) if (!ws.get()->label->get().empty())
builder->cmd(mousebtn::LEFT, string(EVENT_CLICK) + to_string(++workspace_n)); builder->cmd(mousebtn::LEFT, string(EVENT_CLICK) + to_string(++workspace_n));
builder->node(ws.get()->label); builder->node(ws.get()->label);
@ -302,7 +303,7 @@ namespace modules {
for (auto&& mode : m_modes) builder->node(mode); for (auto&& mode : m_modes) builder->node(mode);
} }
if (!ws.get()->label->m_text.empty()) if (!ws.get()->label->get().empty())
builder->cmd_close(true); builder->cmd_close(true);
} }

View File

@ -21,7 +21,7 @@ namespace modules {
return true; return true;
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_COUNTER) { if (tag == TAG_COUNTER) {
builder->node(to_string(m_counter)); builder->node(to_string(m_counter));
return true; return true;

View File

@ -37,10 +37,8 @@ namespace modules {
m_rampload = get_config_ramp(m_conf, name(), TAG_RAMP_LOAD); m_rampload = get_config_ramp(m_conf, name(), TAG_RAMP_LOAD);
if (m_formatter->has(TAG_RAMP_LOAD_PER_CORE)) if (m_formatter->has(TAG_RAMP_LOAD_PER_CORE))
m_rampload_core = get_config_ramp(m_conf, name(), TAG_RAMP_LOAD_PER_CORE); m_rampload_core = get_config_ramp(m_conf, name(), TAG_RAMP_LOAD_PER_CORE);
if (m_formatter->has(TAG_LABEL)) { if (m_formatter->has(TAG_LABEL))
m_label = get_optional_config_label(m_conf, name(), TAG_LABEL, "%percentage%"); m_label = get_optional_config_label(m_conf, name(), TAG_LABEL, "%percentage%");
m_tokenized = m_label->clone();
}
// warmup // warmup
read_values(); read_values();
@ -67,18 +65,17 @@ namespace modules {
m_total = m_total / static_cast<float>(cores_n); m_total = m_total / static_cast<float>(cores_n);
if (m_tokenized) { if (m_label) {
m_tokenized->m_text = m_label->m_text; m_label->reset_tokens();
m_tokenized->replace_token( m_label->replace_token("%percentage%", to_string(static_cast<int>(m_total + 0.5f)) + "%");
"%percentage%", to_string(static_cast<int>(m_total + 0.5f)) + "%");
} }
return true; return true;
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_LABEL) if (tag == TAG_LABEL)
builder->node(m_tokenized); builder->node(m_label);
else if (tag == TAG_BAR_LOAD) else if (tag == TAG_BAR_LOAD)
builder->node(m_barload->output(m_total)); builder->node(m_barload->output(m_total));
else if (tag == TAG_RAMP_LOAD) else if (tag == TAG_RAMP_LOAD)
@ -127,7 +124,7 @@ namespace modules {
return !m_cputimes.empty(); return !m_cputimes.empty();
} }
float get_load(size_t core) { float get_load(size_t core) const {
if (m_cputimes.empty() || m_cputimes_prev.empty()) if (m_cputimes.empty() || m_cputimes_prev.empty())
return 0; return 0;
else if (core >= m_cputimes.size() || core >= m_cputimes_prev.size()) else if (core >= m_cputimes.size() || core >= m_cputimes_prev.size())
@ -159,7 +156,6 @@ namespace modules {
ramp_t m_rampload; ramp_t m_rampload;
ramp_t m_rampload_core; ramp_t m_rampload_core;
label_t m_label; label_t m_label;
label_t m_tokenized;
vector<cpu_time_t> m_cputimes; vector<cpu_time_t> m_cputimes;
vector<cpu_time_t> m_cputimes_prev; vector<cpu_time_t> m_cputimes_prev;

View File

@ -46,7 +46,7 @@ namespace modules {
return m_builder->flush(); return m_builder->flush();
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_DATE) if (tag == TAG_DATE)
builder->node(m_buffer); builder->node(m_buffer);
return tag == TAG_DATE; return tag == TAG_DATE;

View File

@ -167,9 +167,10 @@ namespace modules {
auto icon = m_icons->get(workspace->name, DEFAULT_WS_ICON); auto icon = m_icons->get(workspace->name, DEFAULT_WS_ICON);
auto label = m_statelabels.find(flag)->second->clone(); auto label = m_statelabels.find(flag)->second->clone();
label->reset_tokens();
label->replace_token("%output%", workspace->output); label->replace_token("%output%", workspace->output);
label->replace_token("%name%", wsname); label->replace_token("%name%", wsname);
label->replace_token("%icon%", icon->m_text); label->replace_token("%icon%", icon->get());
label->replace_token("%index%", to_string(workspace->num)); label->replace_token("%index%", to_string(workspace->num));
m_workspaces.emplace_back( m_workspaces.emplace_back(
make_unique<i3_workspace>(workspace->num, flag, std::move(label))); make_unique<i3_workspace>(workspace->num, flag, std::move(label)));
@ -184,7 +185,7 @@ namespace modules {
// }}} // }}}
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
// Output workspace info {{{ // Output workspace info {{{
if (tag != TAG_LABEL_STATE) if (tag != TAG_LABEL_STATE)

View File

@ -25,11 +25,8 @@ namespace modules {
m_bars[memtype::USED] = get_config_bar(m_bar, m_conf, name(), TAG_BAR_USED); m_bars[memtype::USED] = get_config_bar(m_bar, m_conf, name(), TAG_BAR_USED);
if (m_formatter->has(TAG_BAR_FREE)) if (m_formatter->has(TAG_BAR_FREE))
m_bars[memtype::FREE] = get_config_bar(m_bar, m_conf, name(), TAG_BAR_FREE); m_bars[memtype::FREE] = get_config_bar(m_bar, m_conf, name(), TAG_BAR_FREE);
if (m_formatter->has(TAG_LABEL))
if (m_formatter->has(TAG_LABEL)) {
m_label = get_optional_config_label(m_conf, name(), TAG_LABEL, "%percentage_used%"); m_label = get_optional_config_label(m_conf, name(), TAG_LABEL, "%percentage_used%");
m_tokenized = m_label->clone();
}
} }
bool update() { bool update() {
@ -72,38 +69,36 @@ namespace modules {
m_perc[memtype::USED] = 100 - m_perc[memtype::FREE]; m_perc[memtype::USED] = 100 - m_perc[memtype::FREE];
// replace tokens // replace tokens
if (m_tokenized) { if (m_label) {
m_tokenized->m_text = m_label->m_text; m_label->reset_tokens();
auto replace_unit = [](label_t& label, string token, float value, string unit) { auto replace_unit = [](label_t& label, string token, float value, string unit) {
if (label->m_text.find(token) == string::npos)
return;
auto formatted = string_util::from_stream( auto formatted = string_util::from_stream(
stringstream() << std::setprecision(2) << std::fixed << value << " " << unit); stringstream() << std::setprecision(2) << std::fixed << value << " " << unit);
label->replace_token(token, formatted); label->replace_token(token, formatted);
}; };
replace_unit(m_tokenized, "%gb_used%", (kb_total - kb_avail) / 1024 / 1024, "GB"); replace_unit(m_label, "%gb_used%", (kb_total - kb_avail) / 1024 / 1024, "GB");
replace_unit(m_tokenized, "%gb_free%", kb_avail / 1024 / 1024, "GB"); replace_unit(m_label, "%gb_free%", kb_avail / 1024 / 1024, "GB");
replace_unit(m_tokenized, "%gb_total%", kb_total / 1024 / 1024, "GB"); replace_unit(m_label, "%gb_total%", kb_total / 1024 / 1024, "GB");
replace_unit(m_tokenized, "%mb_used%", (kb_total - kb_avail) / 1024, "MB"); replace_unit(m_label, "%mb_used%", (kb_total - kb_avail) / 1024, "MB");
replace_unit(m_tokenized, "%mb_free%", kb_avail / 1024, "MB"); replace_unit(m_label, "%mb_free%", kb_avail / 1024, "MB");
replace_unit(m_tokenized, "%mb_total%", kb_total / 1024, "MB"); replace_unit(m_label, "%mb_total%", kb_total / 1024, "MB");
m_tokenized->replace_token("%percentage_used%", to_string(m_perc[memtype::USED]) + "%"); m_label->replace_token("%percentage_used%", to_string(m_perc[memtype::USED]) + "%");
m_tokenized->replace_token("%percentage_free%", to_string(m_perc[memtype::FREE]) + "%"); m_label->replace_token("%percentage_free%", to_string(m_perc[memtype::FREE]) + "%");
} }
return true; return true;
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_BAR_USED) { if (tag == TAG_BAR_USED) {
builder->node(m_bars[memtype::USED]->output(m_perc[memtype::USED])); builder->node(m_bars.at(memtype::USED)->output(m_perc.at(memtype::USED)));
} else if (tag == TAG_BAR_FREE) } else if (tag == TAG_BAR_FREE)
builder->node(m_bars[memtype::FREE]->output(m_perc[memtype::FREE])); builder->node(m_bars.at(memtype::FREE)->output(m_perc.at(memtype::FREE)));
else if (tag == TAG_LABEL) else if (tag == TAG_LABEL)
builder->node(m_tokenized); builder->node(m_label);
else else
return false; return false;
return true; return true;
@ -115,7 +110,7 @@ namespace modules {
static constexpr auto TAG_BAR_FREE = "<bar-free>"; static constexpr auto TAG_BAR_FREE = "<bar-free>";
label_t m_label; label_t m_label;
label_t m_tokenized; progressbar_t m_bar_free;
map<memtype, progressbar_t> m_bars; map<memtype, progressbar_t> m_bars;
map<memtype, int> m_perc; map<memtype, int> m_perc;
}; };

View File

@ -58,7 +58,7 @@ namespace modules {
} }
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_LABEL_TOGGLE && m_level == -1) { if (tag == TAG_LABEL_TOGGLE && m_level == -1) {
builder->cmd(mousebtn::LEFT, string(EVENT_MENU_OPEN) + "0"); builder->cmd(mousebtn::LEFT, string(EVENT_MENU_OPEN) + "0");
builder->node(m_labelopen); builder->node(m_labelopen);

View File

@ -287,7 +287,7 @@ namespace modules {
return ""; return "";
} }
auto format_name = CAST_MODULE(Impl)->get_format(); auto format_name = CONST_CAST_MODULE(Impl).get_format();
auto format = m_formatter->get(format_name); auto format = m_formatter->get(format_name);
int i = 0; int i = 0;
@ -299,7 +299,7 @@ namespace modules {
if (tag[0] == '<' && tag[tag.length() - 1] == '>') { if (tag[0] == '<' && tag[tag.length() - 1] == '>') {
if (i > 0) if (i > 0)
m_builder->space(format->spacing); m_builder->space(format->spacing);
if (!(tag_built = CAST_MODULE(Impl)->build(m_builder.get(), tag)) && i > 0) if (!(tag_built = CONST_CAST_MODULE(Impl).build(m_builder.get(), tag)) && i > 0)
m_builder->remove_trailing_space(format->spacing); m_builder->remove_trailing_space(format->spacing);
if (tag_built) if (tag_built)
i++; i++;
@ -361,7 +361,7 @@ namespace modules {
CAST_MODULE(Impl)->broadcast(); CAST_MODULE(Impl)->broadcast();
} }
bool build(builder*, string) { bool build(builder*, string) const {
return true; return true;
} }
}; };
@ -427,17 +427,14 @@ namespace modules {
CAST_MODULE(Impl)->broadcast(); CAST_MODULE(Impl)->broadcast();
while (CONST_CAST_MODULE(Impl).enabled()) { while (CONST_CAST_MODULE(Impl).enabled()) {
CAST_MODULE(Impl)->idle(); std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
{
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
if (!CAST_MODULE(Impl)->has_event())
continue;
if (!CAST_MODULE(Impl)->update())
continue;
if (!CAST_MODULE(Impl)->has_event())
CAST_MODULE(Impl)->idle();
else if (!CAST_MODULE(Impl)->update())
CAST_MODULE(Impl)->idle();
else
CAST_MODULE(Impl)->broadcast(); CAST_MODULE(Impl)->broadcast();
}
} }
} catch (const std::exception& err) { } catch (const std::exception& err) {
this->m_log.err("%s: %s", this->name(), err.what()); this->m_log.err("%s: %s", this->name(), err.what());

View File

@ -57,12 +57,10 @@ namespace modules {
if (m_formatter->has(TAG_LABEL_SONG)) { if (m_formatter->has(TAG_LABEL_SONG)) {
m_label_song = m_label_song =
get_optional_config_label(m_conf, name(), TAG_LABEL_SONG, "%artist% - %title%"); get_optional_config_label(m_conf, name(), TAG_LABEL_SONG, "%artist% - %title%");
m_label_song_tokenized = m_label_song->clone();
} }
if (m_formatter->has(TAG_LABEL_TIME)) { if (m_formatter->has(TAG_LABEL_TIME)) {
m_label_time = m_label_time =
get_optional_config_label(m_conf, name(), TAG_LABEL_TIME, "%elapsed% / %total%"); get_optional_config_label(m_conf, name(), TAG_LABEL_TIME, "%elapsed% / %total%");
m_label_time_tokenized = m_label_time->clone();
} }
if (m_formatter->has(TAG_ICON_RANDOM) || m_formatter->has(TAG_ICON_REPEAT) || if (m_formatter->has(TAG_ICON_RANDOM) || m_formatter->has(TAG_ICON_REPEAT) ||
m_formatter->has(TAG_ICON_REPEAT_ONE)) { m_formatter->has(TAG_ICON_REPEAT_ONE)) {
@ -83,64 +81,58 @@ namespace modules {
m_mpd = make_unique<mpdconnection>(m_log, m_host, m_port, m_pass); m_mpd = make_unique<mpdconnection>(m_log, m_host, m_port, m_pass);
m_mpd->connect(); m_mpd->connect();
m_status = m_mpd->get_status(); m_status = m_mpd->get_status();
} catch (const mpd_exception& e) { } catch (const mpd_exception& err) {
m_log.err("%s: %s", name(), e.what()); m_log.err("%s: %s", name(), err.what());
m_mpd.reset();
} }
} }
void teardown() { inline bool connected() const {
if (m_mpd && m_mpd->connected()) { return m_mpd && m_mpd->connected();
try {
m_mpd->disconnect();
} catch (const mpd_exception& e) {
m_log.trace("%s: %s", name(), e.what());
}
} else {
wakeup();
}
} }
void idle() { void idle() {
if (m_mpd && m_mpd->connected()) if (connected())
sleep(80ms); sleep(80ms);
else { else {
sleep(10s); sleep(2s);
} }
} }
bool has_event() { bool has_event() {
if (!m_mpd->connected()) { if (!m_mpd)
m_connection_state_broadcasted = false; m_mpd = make_unique<mpdconnection>(m_log, m_host, m_port, m_pass);
try { try {
if (!connected())
m_mpd->connect(); m_mpd->connect();
} catch (const mpd_exception& e) { if (m_connection_state_broadcasted)
m_log.trace("%s: %s", name(), e.what()); m_connection_state_broadcasted = false;
} } catch (const mpd_exception& err) {
m_log.trace("%s: %s", name(), err.what());
if (!m_mpd->connected()) { m_mpd.reset();
return false; return !m_connection_state_broadcasted;
}
} }
if (!connected())
return !m_connection_state_broadcasted;
if (!m_status) if (!m_status)
m_status = m_mpd->get_status_safe(); m_status = m_mpd->get_status_safe();
try { try {
m_mpd->idle(); m_mpd->idle();
int idle_flags = 0;
int idle_flags;
if ((idle_flags = m_mpd->noidle()) != 0) { if ((idle_flags = m_mpd->noidle()) != 0) {
m_status->update(idle_flags, m_mpd.get()); m_status->update(idle_flags, m_mpd.get());
return true; return true;
} else if (m_status->match_state(mpdstate::PLAYING)) { } else if (m_status->match_state(mpdstate::PLAYING)) {
m_status->update_timer(); m_status->update_timer();
} }
} catch (const mpd_exception& e) { } catch (const mpd_exception& err) {
m_log.err(e.what()); m_log.err(err.what());
m_mpd->disconnect(); m_mpd.reset();
return true; return !m_connection_state_broadcasted;
} }
if ((m_label_time || m_bar_progress) && m_status->match_state(mpdstate::PLAYING)) { if ((m_label_time || m_bar_progress) && m_status->match_state(mpdstate::PLAYING)) {
@ -156,12 +148,14 @@ namespace modules {
} }
bool update() { bool update() {
if (!m_mpd->connected()) if (m_connection_state_broadcasted) {
return true; if (!connected())
if (!m_status && !(m_status = m_mpd->get_status_safe())) return false;
return true; if (!m_status && !(m_status = m_mpd->get_status_safe()))
return false;
m_connection_state_broadcasted = true; } else {
m_connection_state_broadcasted = true;
}
string artist; string artist;
string album; string album;
@ -170,52 +164,55 @@ namespace modules {
string total_str; string total_str;
try { try {
elapsed_str = m_status->get_formatted_elapsed(); if (m_status) {
total_str = m_status->get_formatted_total(); elapsed_str = m_status->get_formatted_elapsed();
auto song = m_mpd->get_song(); total_str = m_status->get_formatted_total();
if (song && song.get()) {
artist = song->get_artist();
album = song->get_album();
title = song->get_title();
} }
} catch (const mpd_exception& e) { if (m_mpd) {
m_log.err(e.what()); auto song = m_mpd->get_song();
m_mpd->disconnect(); if (song && song.get()) {
return true; artist = song->get_artist();
album = song->get_album();
title = song->get_title();
}
}
} catch (const mpd_exception& err) {
m_log.err(err.what());
m_mpd.reset();
} }
if (m_label_song_tokenized) { if (m_label_song) {
m_label_song_tokenized->m_text = m_label_song->m_text; m_label_song->reset_tokens();
m_label_song_tokenized->replace_token( m_label_song->replace_token(
"%artist%", !artist.empty() ? artist : "untitled artist"); "%artist%", !artist.empty() ? artist : "untitled artist");
m_label_song_tokenized->replace_token("%album%", !album.empty() ? album : "untitled album"); m_label_song->replace_token("%album%", !album.empty() ? album : "untitled album");
m_label_song_tokenized->replace_token("%title%", !title.empty() ? title : "untitled track"); m_label_song->replace_token("%title%", !title.empty() ? title : "untitled track");
} }
if (m_label_time_tokenized) { if (m_label_time) {
m_label_time_tokenized->m_text = m_label_time->m_text; m_label_time->reset_tokens();
m_label_time_tokenized->replace_token("%elapsed%", elapsed_str); m_label_time->replace_token("%elapsed%", elapsed_str);
m_label_time_tokenized->replace_token("%total%", total_str); m_label_time->replace_token("%total%", total_str);
} }
if (m_icons->has("random")) if (m_icons->has("random"))
m_icons->get("random")->m_foreground = m_icons->get("random")->m_foreground =
m_status->random() ? m_toggle_on_color : m_toggle_off_color; m_status && m_status->random() ? m_toggle_on_color : m_toggle_off_color;
if (m_icons->has("repeat")) if (m_icons->has("repeat"))
m_icons->get("repeat")->m_foreground = m_icons->get("repeat")->m_foreground =
m_status->repeat() ? m_toggle_on_color : m_toggle_off_color; m_status && m_status->repeat() ? m_toggle_on_color : m_toggle_off_color;
if (m_icons->has("repeat_one")) if (m_icons->has("repeat_one"))
m_icons->get("repeat_one")->m_foreground = m_icons->get("repeat_one")->m_foreground =
m_status->single() ? m_toggle_on_color : m_toggle_off_color; m_status && m_status->single() ? m_toggle_on_color : m_toggle_off_color;
return true; return true;
} }
string get_format() { string get_format() const {
return m_mpd->connected() ? FORMAT_ONLINE : FORMAT_OFFLINE; return connected() ? FORMAT_ONLINE : FORMAT_OFFLINE;
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
bool is_playing = false; bool is_playing = false;
bool is_paused = false; bool is_paused = false;
bool is_stopped = true; bool is_stopped = true;
@ -239,9 +236,9 @@ namespace modules {
}; };
if (tag == TAG_LABEL_SONG && !is_stopped) if (tag == TAG_LABEL_SONG && !is_stopped)
builder->node(m_label_song_tokenized); builder->node(m_label_song);
else if (tag == TAG_LABEL_TIME && !is_stopped) else if (tag == TAG_LABEL_TIME && !is_stopped)
builder->node(m_label_time_tokenized); builder->node(m_label_time);
else if (tag == TAG_BAR_PROGRESS && !is_stopped) else if (tag == TAG_BAR_PROGRESS && !is_stopped)
builder->node(m_bar_progress->output(elapsed_percentage)); builder->node(m_bar_progress->output(elapsed_percentage));
else if (tag == TAG_LABEL_OFFLINE) else if (tag == TAG_LABEL_OFFLINE)
@ -312,8 +309,9 @@ namespace modules {
mpd->seek(status->get_songid(), status->get_seek_position(percentage)); mpd->seek(status->get_songid(), status->get_seek_position(percentage));
} else } else
return false; return false;
} catch (const mpd_exception& e) { } catch (const mpd_exception& err) {
m_log.err("%s: %s", name(), e.what()); m_log.err("%s: %s", name(), err.what());
m_mpd.reset();
} }
return true; return true;
@ -359,9 +357,7 @@ namespace modules {
progressbar_t m_bar_progress; progressbar_t m_bar_progress;
iconset_t m_icons; iconset_t m_icons;
label_t m_label_song; label_t m_label_song;
label_t m_label_song_tokenized;
label_t m_label_time; label_t m_label_time;
label_t m_label_time_tokenized;
label_t m_label_offline; label_t m_label_offline;
unique_ptr<mpdconnection> m_mpd; unique_ptr<mpdconnection> m_mpd;
@ -383,7 +379,7 @@ namespace modules {
// This flag is used to let thru a broadcast once every time // This flag is used to let thru a broadcast once every time
// the connection state changes // the connection state changes
stateflag m_connection_state_broadcasted{true}; stateflag m_connection_state_broadcasted{false};
}; };
} }

View File

@ -38,13 +38,13 @@ namespace modules {
if (m_formatter->has(TAG_LABEL_CONNECTED, FORMAT_CONNECTED)) { if (m_formatter->has(TAG_LABEL_CONNECTED, FORMAT_CONNECTED)) {
m_label[connection_state::CONNECTED] = m_label[connection_state::CONNECTED] =
get_optional_config_label(m_conf, name(), TAG_LABEL_CONNECTED, "%ifname% %local_ip%"); get_optional_config_label(m_conf, name(), TAG_LABEL_CONNECTED, "%ifname% %local_ip%");
m_tokenized[connection_state::CONNECTED] = m_label[connection_state::CONNECTED]->clone();
} }
// Create elements for format-disconnected // Create elements for format-disconnected
if (m_formatter->has(TAG_LABEL_DISCONNECTED, FORMAT_DISCONNECTED)) { if (m_formatter->has(TAG_LABEL_DISCONNECTED, FORMAT_DISCONNECTED)) {
m_label[connection_state::DISCONNECTED] = m_label[connection_state::DISCONNECTED] =
get_optional_config_label(m_conf, name(), TAG_LABEL_DISCONNECTED, ""); get_optional_config_label(m_conf, name(), TAG_LABEL_DISCONNECTED, "");
m_label[connection_state::DISCONNECTED]->reset_tokens();
m_label[connection_state::DISCONNECTED]->replace_token("%ifname%", m_interface); m_label[connection_state::DISCONNECTED]->replace_token("%ifname%", m_interface);
} }
@ -56,8 +56,6 @@ namespace modules {
if (m_formatter->has(TAG_LABEL_PACKETLOSS, FORMAT_PACKETLOSS)) { if (m_formatter->has(TAG_LABEL_PACKETLOSS, FORMAT_PACKETLOSS)) {
m_label[connection_state::PACKETLOSS] = m_label[connection_state::PACKETLOSS] =
get_optional_config_label(m_conf, name(), TAG_LABEL_PACKETLOSS, ""); get_optional_config_label(m_conf, name(), TAG_LABEL_PACKETLOSS, "");
m_tokenized[connection_state::PACKETLOSS] =
m_label[connection_state::PACKETLOSS]->clone();
} }
if (m_formatter->has(TAG_ANIMATION_PACKETLOSS, FORMAT_PACKETLOSS)) if (m_formatter->has(TAG_ANIMATION_PACKETLOSS, FORMAT_PACKETLOSS))
m_animation_packetloss = get_config_animation(m_conf, name(), TAG_ANIMATION_PACKETLOSS); m_animation_packetloss = get_config_animation(m_conf, name(), TAG_ANIMATION_PACKETLOSS);
@ -112,6 +110,7 @@ namespace modules {
// Update label contents // Update label contents
const auto replace_tokens = [&](label_t& label) { const auto replace_tokens = [&](label_t& label) {
label->reset_tokens();
label->replace_token("%ifname%", m_interface); label->replace_token("%ifname%", m_interface);
label->replace_token("%local_ip%", network->ip()); label->replace_token("%local_ip%", network->ip());
label->replace_token("%upspeed%", upspeed); label->replace_token("%upspeed%", upspeed);
@ -126,22 +125,15 @@ namespace modules {
} }
}; };
if (m_label[connection_state::CONNECTED]) { if (m_label[connection_state::CONNECTED])
m_tokenized[connection_state::CONNECTED]->m_text = replace_tokens(m_label[connection_state::CONNECTED]);
m_label[connection_state::CONNECTED]->m_text; if (m_label[connection_state::PACKETLOSS])
replace_tokens(m_tokenized[connection_state::CONNECTED]); replace_tokens(m_label[connection_state::PACKETLOSS]);
}
if (m_label[connection_state::PACKETLOSS]) {
m_tokenized[connection_state::PACKETLOSS]->m_text =
m_label[connection_state::PACKETLOSS]->m_text;
replace_tokens(m_tokenized[connection_state::PACKETLOSS]);
}
return true; return true;
} }
string get_format() { string get_format() const {
if (!m_connected) if (!m_connected)
return FORMAT_DISCONNECTED; return FORMAT_DISCONNECTED;
else if (m_packetloss && m_ping_nth_update > 0) else if (m_packetloss && m_ping_nth_update > 0)
@ -150,13 +142,13 @@ namespace modules {
return FORMAT_CONNECTED; return FORMAT_CONNECTED;
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_LABEL_CONNECTED) if (tag == TAG_LABEL_CONNECTED)
builder->node(m_tokenized[connection_state::CONNECTED]); builder->node(m_label.at(connection_state::CONNECTED));
else if (tag == TAG_LABEL_DISCONNECTED) else if (tag == TAG_LABEL_DISCONNECTED)
builder->node(m_label[connection_state::DISCONNECTED]); builder->node(m_label.at(connection_state::DISCONNECTED));
else if (tag == TAG_LABEL_PACKETLOSS) else if (tag == TAG_LABEL_PACKETLOSS)
builder->node(m_tokenized[connection_state::PACKETLOSS]); builder->node(m_label.at(connection_state::PACKETLOSS));
else if (tag == TAG_ANIMATION_PACKETLOSS) else if (tag == TAG_ANIMATION_PACKETLOSS)
builder->node(m_animation_packetloss->get()); builder->node(m_animation_packetloss->get());
else if (tag == TAG_RAMP_SIGNAL) else if (tag == TAG_RAMP_SIGNAL)
@ -200,7 +192,6 @@ namespace modules {
ramp_t m_ramp_quality; ramp_t m_ramp_quality;
animation_t m_animation_packetloss; animation_t m_animation_packetloss;
map<connection_state, label_t> m_label; map<connection_state, label_t> m_label;
map<connection_state, label_t> m_tokenized;
stateflag m_connected{false}; stateflag m_connected{false};
stateflag m_packetloss{false}; stateflag m_packetloss{false};

View File

@ -129,7 +129,7 @@ namespace modules {
return m_builder->flush(); return m_builder->flush();
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag != TAG_OUTPUT) if (tag != TAG_OUTPUT)
return false; return false;
builder->node(string_util::replace_all(m_output, "\n", "")); builder->node(string_util::replace_all(m_output, "\n", ""));

View File

@ -19,7 +19,7 @@ namespace modules {
string_util::replace_all(m_formatter->get("content")->value, " ", BUILDER_SPACE_TOKEN); string_util::replace_all(m_formatter->get("content")->value, " ", BUILDER_SPACE_TOKEN);
} }
string get_format() { string get_format() const {
return "content"; return "content";
} }

View File

@ -11,7 +11,7 @@
throw application_error("No built-in support for '" + string{MODULE_TYPE} + "'"); \ throw application_error("No built-in support for '" + string{MODULE_TYPE} + "'"); \
} \ } \
void start() {} \ void start() {} \
bool build(builder*, string) { \ bool build(builder*, string) const { \
return true; \ return true; \
} \ } \
} }

View File

@ -98,11 +98,9 @@ namespace modules {
if (m_formatter->has(TAG_LABEL_VOLUME, FORMAT_VOLUME)) { if (m_formatter->has(TAG_LABEL_VOLUME, FORMAT_VOLUME)) {
m_label_volume = m_label_volume =
get_optional_config_label(m_conf, name(), TAG_LABEL_VOLUME, "%percentage%"); get_optional_config_label(m_conf, name(), TAG_LABEL_VOLUME, "%percentage%");
m_label_volume_tokenized = m_label_volume->clone();
} }
if (m_formatter->has(TAG_LABEL_MUTED, FORMAT_MUTED)) { if (m_formatter->has(TAG_LABEL_MUTED, FORMAT_MUTED)) {
m_label_muted = get_optional_config_label(m_conf, name(), TAG_LABEL_MUTED, "%percentage%"); m_label_muted = get_optional_config_label(m_conf, name(), TAG_LABEL_MUTED, "%percentage%");
m_label_muted_tokenized = m_label_muted->clone();
} }
// }}} // }}}
@ -172,13 +170,13 @@ namespace modules {
// }}} // }}}
// Replace label tokens {{{ // Replace label tokens {{{
if (m_label_volume_tokenized) { if (m_label_volume) {
m_label_volume_tokenized->m_text = m_label_volume->m_text; m_label_volume->reset_tokens();
m_label_volume_tokenized->replace_token("%percentage%", to_string(m_volume) + "%"); m_label_volume->replace_token("%percentage%", to_string(m_volume) + "%");
} }
if (m_label_muted_tokenized) { if (m_label_muted) {
m_label_muted_tokenized->m_text = m_label_muted->m_text; m_label_muted->reset_tokens();
m_label_muted_tokenized->replace_token("%percentage%", to_string(m_volume) + "%"); m_label_muted->replace_token("%percentage%", to_string(m_volume) + "%");
} }
// }}} // }}}
@ -186,7 +184,7 @@ namespace modules {
return true; return true;
} }
string get_format() { string get_format() const {
return m_muted ? FORMAT_MUTED : FORMAT_VOLUME; return m_muted ? FORMAT_MUTED : FORMAT_VOLUME;
} }
@ -202,7 +200,7 @@ namespace modules {
return m_builder->flush(); return m_builder->flush();
} }
bool build(builder* builder, string tag) { bool build(builder* builder, string tag) const {
if (tag == TAG_BAR_VOLUME) if (tag == TAG_BAR_VOLUME)
builder->node(m_bar_volume->output(m_volume)); builder->node(m_bar_volume->output(m_volume));
else if (tag == TAG_RAMP_VOLUME && (!m_headphones || !*m_ramp_headphones)) else if (tag == TAG_RAMP_VOLUME && (!m_headphones || !*m_ramp_headphones))
@ -210,9 +208,9 @@ namespace modules {
else if (tag == TAG_RAMP_VOLUME && m_headphones && *m_ramp_headphones) else if (tag == TAG_RAMP_VOLUME && m_headphones && *m_ramp_headphones)
builder->node(m_ramp_headphones->get_by_percentage(m_volume)); builder->node(m_ramp_headphones->get_by_percentage(m_volume));
else if (tag == TAG_LABEL_VOLUME) else if (tag == TAG_LABEL_VOLUME)
builder->node(m_label_volume_tokenized); builder->node(m_label_volume);
else if (tag == TAG_LABEL_MUTED) else if (tag == TAG_LABEL_MUTED)
builder->node(m_label_muted_tokenized); builder->node(m_label_muted);
else else
return false; return false;
return true; return true;
@ -283,9 +281,7 @@ namespace modules {
ramp_t m_ramp_volume; ramp_t m_ramp_volume;
ramp_t m_ramp_headphones; ramp_t m_ramp_headphones;
label_t m_label_volume; label_t m_label_volume;
label_t m_label_volume_tokenized;
label_t m_label_muted; label_t m_label_muted;
label_t m_label_muted_tokenized;
map<mixer, mixer_t> m_mixers; map<mixer, mixer_t> m_mixers;
map<control, control_t> m_controls; map<control, control_t> m_controls;