#include "components/builder.hpp" #include "components/logger.hpp" #include "components/config.hpp" POLYBAR_NS namespace modules { // module public {{{ template module::module(const bar_settings bar, string name) : m_bar(bar) , m_log(logger::make()) , m_conf(config::make()) , m_name("module/" + name) , m_builder(make_unique(bar)) , m_formatter(make_unique(m_conf, m_name)) {} template module::~module() noexcept { m_log.trace("%s: Deconstructing", name()); for (auto&& thread_ : m_threads) { if (thread_.joinable()) { thread_.join(); } } } template void module::set_update_cb(callback<>&& cb) { m_update_callback = forward(cb); } template void module::set_stop_cb(callback<>&& cb) { m_stop_callback = forward(cb); } template string module::name() const { return m_name; } template bool module::running() const { return m_enabled.load(std::memory_order_relaxed); } template void module::setup() { m_log.trace("%s: Setup", m_name); try { CAST_MOD(Impl)->setup(); } catch (const std::exception& err) { m_log.err("%s: Setup failed", m_name); halt(err.what()); } } template void module::stop() { if (!running()) { return; } m_log.info("%s: Stopping", name()); m_enabled.store(false, std::memory_order_relaxed); wakeup(); std::lock_guard guard(m_lock); { CAST_MOD(Impl)->teardown(); if (m_mainthread.joinable()) { m_mainthread.join(); } } if (m_stop_callback) { m_stop_callback(); } } template void module::halt(string error_message) { m_log.err("%s: %s", name(), error_message); m_log.warn("Stopping '%s'...", name()); stop(); } template void module::teardown() {} template string module::contents() { return m_cache; } template bool module::handle_event(string cmd) { return CAST_MOD(Impl)->handle_event(cmd); } template bool module::receive_events() const { return false; } // }}} // module protected {{{ template void module::broadcast() { if (!running()) { return; } m_cache = CAST_MOD(Impl)->get_output(); if (m_update_callback) m_update_callback(); else m_log.warn("%s: No handler, ignoring broadcast...", name()); } template void module::idle() { CAST_MOD(Impl)->sleep(25ms); } template void module::sleep(chrono::duration sleep_duration) { std::unique_lock lck(m_sleeplock); m_sleephandler.wait_for(lck, sleep_duration); } template void module::wakeup() { m_log.trace("%s: Release sleep lock", name()); m_sleephandler.notify_all(); } template string module::get_format() const { return DEFAULT_FORMAT; } template string module::get_output() { if (!running()) { m_log.trace("%s: Module is disabled", name()); return ""; } auto format_name = CONST_MOD(Impl).get_format(); auto format = m_formatter->get(format_name); int i = 0; bool tag_built = true; for (auto&& tag : string_util::split(format->value, ' ')) { bool is_blankspace = tag.empty(); if (tag[0] == '<' && tag[tag.length() - 1] == '>') { if (i > 0) m_builder->space(format->spacing); if (!(tag_built = CONST_MOD(Impl).build(m_builder.get(), tag)) && i > 0) m_builder->remove_trailing_space(format->spacing); if (tag_built) i++; } else if (is_blankspace && tag_built) { m_builder->node(" "); } else if (!is_blankspace) { m_builder->node(tag); } } return format->decorate(m_builder.get(), m_builder->flush()); } // }}} } POLYBAR_NS_END