Battery event (#18)

This commit is contained in:
Alex 2018-08-13 14:05:13 +02:00 committed by GitHub
parent 01894f18cd
commit a423f7032d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 88 additions and 72 deletions

View File

@ -15,7 +15,7 @@ namespace waybar {
class Factory { class Factory {
public: public:
Factory(Bar &bar, Json::Value config); Factory(Bar &bar, Json::Value config);
IModule &makeModule(std::string name); IModule *makeModule(std::string name);
private: private:
Bar &_bar; Bar &_bar;
Json::Value _config; Json::Value _config;

View File

@ -5,6 +5,7 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <fmt/format.h> #include <fmt/format.h>
#include <sys/inotify.h>
#include "util/chrono.hpp" #include "util/chrono.hpp"
#include "IModule.hpp" #include "IModule.hpp"
@ -18,7 +19,7 @@ namespace waybar::modules {
auto update() -> void; auto update() -> void;
operator Gtk::Widget&(); operator Gtk::Widget&();
private: private:
std::string _getIcon(uint32_t percentage); std::string _getIcon(uint16_t percentage);
static inline const fs::path _data_dir = "/sys/class/power_supply/"; static inline const fs::path _data_dir = "/sys/class/power_supply/";
std::vector<fs::path> _batteries; std::vector<fs::path> _batteries;
util::SleeperThread _thread; util::SleeperThread _thread;

View File

@ -39,7 +39,9 @@ namespace waybar::util {
func(); func();
} while (do_run); } while (do_run);
}} }}
{} {
defined = true;
}
SleeperThread& operator=(std::function<void()> func) SleeperThread& operator=(std::function<void()> func)
{ {
@ -48,6 +50,7 @@ namespace waybar::util {
func(); func();
} while (do_run); } while (do_run);
}); });
defined = true;
return *this; return *this;
} }
@ -72,14 +75,17 @@ namespace waybar::util {
~SleeperThread() ~SleeperThread()
{ {
do_run = false; do_run = false;
condvar.notify_all(); if (defined) {
thread.join(); condvar.notify_all();
thread.join();
}
} }
private: private:
std::thread thread; std::thread thread;
std::condition_variable condvar; std::condition_variable condvar;
std::mutex mutex; std::mutex mutex;
bool defined = false;
bool do_run = true; bool do_run = true;
}; };

View File

@ -167,24 +167,27 @@ auto waybar::Bar::_setupWidgets() -> void
box1.pack_end(right, true, true); box1.pack_end(right, true, true);
Factory factory(*this, _config); Factory factory(*this, _config);
if (_config["modules-left"]) { if (_config["modules-left"]) {
for (auto name : _config["modules-left"]) { for (auto name : _config["modules-left"]) {
auto &module = factory.makeModule(name.asString()); auto module = factory.makeModule(name.asString());
left.pack_start(module, false, true, 0); if (module)
left.pack_start(*module, false, true, 0);
} }
} }
if (_config["modules-center"]) { if (_config["modules-center"]) {
for (auto name : _config["modules-center"]) { for (auto name : _config["modules-center"]) {
auto &module = factory.makeModule(name.asString()); auto module = factory.makeModule(name.asString());
center.pack_start(module, true, false, 10); if (module)
center.pack_start(*module, true, false, 10);
} }
} }
if (_config["modules-right"]) { if (_config["modules-right"]) {
std::reverse(_config["modules-right"].begin(), _config["modules-right"].end()); std::reverse(_config["modules-right"].begin(), _config["modules-right"].end());
for (auto name : _config["modules-right"]) { for (auto name : _config["modules-right"]) {
auto &module = factory.makeModule(name.asString()); auto module = factory.makeModule(name.asString());
right.pack_end(module, false, false, 0); if (module)
right.pack_end(*module, false, false, 0);
} }
} }
} }

View File

@ -4,23 +4,32 @@ waybar::Factory::Factory(Bar &bar, Json::Value config)
: _bar(bar), _config(config) : _bar(bar), _config(config)
{} {}
waybar::IModule &waybar::Factory::makeModule(std::string name) waybar::IModule *waybar::Factory::makeModule(std::string name)
{ {
if (name == "battery") try {
return *new waybar::modules::Battery(_config[name]); if (name == "battery")
if (name == "workspaces") return new waybar::modules::Battery(_config[name]);
return *new waybar::modules::Workspaces(_bar); if (name == "workspaces")
if (name == "memory") return new waybar::modules::Workspaces(_bar);
return *new waybar::modules::Memory(_config[name]); if (name == "memory")
if (name == "cpu") return new waybar::modules::Memory(_config[name]);
return *new waybar::modules::Cpu(_config[name]); if (name == "cpu")
if (name == "clock") return new waybar::modules::Cpu(_config[name]);
return *new waybar::modules::Clock(_config[name]); if (name == "clock")
if (name == "network") return new waybar::modules::Clock(_config[name]);
return *new waybar::modules::Network(_config[name]); if (name == "network")
if (name == "pulseaudio") return new waybar::modules::Network(_config[name]);
return *new waybar::modules::Pulseaudio(_config[name]); if (name == "pulseaudio")
if (!name.compare(0, 7, "custom/") && name.size() > 7) return new waybar::modules::Pulseaudio(_config[name]);
return *new waybar::modules::Custom(name.substr(7), _config[name]); if (!name.compare(0, 7, "custom/") && name.size() > 7)
throw std::runtime_error("Unknown module: " + name); return new waybar::modules::Custom(name.substr(7), _config[name]);
std::cerr << "Unknown module: " + name << std::endl;
} catch (const std::exception& e) {
auto err = fmt::format("Disabling module \"{}\", {}", name, e.what());
std::cerr << err << std::endl;
} catch (...) {
auto err = fmt::format("Disabling module \"{}\", Unknown reason", name);
std::cerr << err << std::endl;
}
return nullptr;
} }

View File

@ -5,62 +5,66 @@ waybar::modules::Battery::Battery(Json::Value config)
{ {
try { try {
for (auto &node : fs::directory_iterator(_data_dir)) { for (auto &node : fs::directory_iterator(_data_dir)) {
if (fs::is_directory(node) && fs::exists(node / "capacity") if (fs::is_directory(node) && fs::exists(node / "capacity"))
&& fs::exists(node / "status")) {
_batteries.push_back(node); _batteries.push_back(node);
}
} }
} catch (fs::filesystem_error &e) { } catch (fs::filesystem_error &e) {
std::cerr << e.what() << std::endl; throw std::runtime_error(e.what());
} }
if (!_batteries.size()) { if (!_batteries.size())
std::cerr << "No batteries." << std::endl; throw std::runtime_error("No batteries.");
return;
}
auto fd = inotify_init();
if (fd == -1)
throw std::runtime_error("Unable to listen batteries.");
for (auto &bat : _batteries)
inotify_add_watch(fd, (bat / "uevent").c_str(), IN_ACCESS);
// Trigger first value
update();
_label.get_style_context()->add_class("battery"); _label.get_style_context()->add_class("battery");
int interval = _config["interval"] ? _config["inveral"].asInt() : 1; _thread = [this, fd] {
_thread = [this, interval] { struct inotify_event event;
int nbytes = read(fd, &event, sizeof(event));
if (nbytes != sizeof(event))
return;
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Battery::update)); Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Battery::update));
_thread.sleep_for(chrono::seconds(interval));
}; };
} }
auto waybar::modules::Battery::update() -> void auto waybar::modules::Battery::update() -> void
{ {
try { try {
int total = 0; uint16_t total = 0;
bool charging = false; bool charging = false;
std::string status;
for (auto &bat : _batteries) { for (auto &bat : _batteries) {
int capacity; uint16_t capacity;
std::string status;
std::ifstream(bat / "capacity") >> capacity; std::ifstream(bat / "capacity") >> capacity;
total += capacity;
std::ifstream(bat / "status") >> status; std::ifstream(bat / "status") >> status;
if (status == "Charging") { if (status == "Charging")
charging = true; charging = true;
} total += capacity;
} }
uint16_t capacity = total / _batteries.size();
auto format = _config["format"] ? _config["format"].asString() : "{}%"; auto format = _config["format"] ? _config["format"].asString() : "{}%";
auto value = total / _batteries.size(); _label.set_text(fmt::format(format, fmt::arg("value", capacity),
_label.set_text(fmt::format(format, fmt::arg("value", value), fmt::arg("icon", _getIcon(capacity))));
fmt::arg("icon", _getIcon(value)))); _label.set_tooltip_text(status);
_label.set_tooltip_text(charging ? "Charging" : "Discharging");
if (charging) if (charging)
_label.get_style_context()->add_class("charging"); _label.get_style_context()->add_class("charging");
else else
_label.get_style_context()->remove_class("charging"); _label.get_style_context()->remove_class("charging");
if (value < 16 && !charging) if (capacity < 16 && !charging)
_label.get_style_context()->add_class("warning"); _label.get_style_context()->add_class("warning");
else else
_label.get_style_context()->remove_class("warning"); _label.get_style_context()->remove_class("warning");
} catch (std::exception &e) { } catch (const std::exception& e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
} }
} }
std::string waybar::modules::Battery::_getIcon(uint32_t percentage) std::string waybar::modules::Battery::_getIcon(uint16_t percentage)
{ {
if (!_config["format-icons"] || !_config["format-icons"].isArray()) return ""; if (!_config["format-icons"] || !_config["format-icons"].isArray()) return "";
auto step = 100 / _config["format-icons"].size(); auto step = 100 / _config["format-icons"].size();

View File

@ -4,10 +4,8 @@
waybar::modules::Custom::Custom(std::string name, Json::Value config) waybar::modules::Custom::Custom(std::string name, Json::Value config)
: _name(name), _config(config) : _name(name), _config(config)
{ {
if (!_config["exec"]) { if (!_config["exec"])
std::cerr << name + " has no exec path." << std::endl; throw std::runtime_error(name + " has no exec path.");
return;
}
int interval = _config["interval"] ? _config["inveral"].asInt() : 30; int interval = _config["interval"] ? _config["inveral"].asInt() : 30;
_thread = [this, interval] { _thread = [this, interval] {
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Custom::update)); Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Custom::update));

View File

@ -1,8 +1,10 @@
#include "modules/network.hpp" #include "modules/network.hpp"
waybar::modules::Network::Network(Json::Value config) waybar::modules::Network::Network(Json::Value config)
: _config(config), _ifid(if_nametoindex(config["interface"].asString().c_str())) : _config(config), _ifid(if_nametoindex(config["interface"].asCString()))
{ {
if (_ifid == 0)
throw std::runtime_error("Can't found network interface");
_label.get_style_context()->add_class("network"); _label.get_style_context()->add_class("network");
int interval = _config["interval"] ? _config["inveral"].asInt() : 30; int interval = _config["interval"] ? _config["inveral"].asInt() : 30;
_thread = [this, interval] { _thread = [this, interval] {
@ -103,8 +105,6 @@ bool waybar::modules::Network::_associatedOrJoined(struct nlattr** bss)
auto waybar::modules::Network::_getInfo() -> void auto waybar::modules::Network::_getInfo() -> void
{ {
if (_ifid == 0)
return;
struct nl_sock *sk = nl_socket_alloc(); struct nl_sock *sk = nl_socket_alloc();
if (genl_connect(sk) != 0) { if (genl_connect(sk) != 0) {
nl_socket_free(sk); nl_socket_free(sk);

View File

@ -5,17 +5,12 @@ waybar::modules::Workspaces::Workspaces(Bar &bar)
: _bar(bar) : _bar(bar)
{ {
_box.get_style_context()->add_class("workspaces"); _box.get_style_context()->add_class("workspaces");
try { std::string socketPath = get_socketpath();
std::string socketPath = get_socketpath(); _ipcSocketfd = ipc_open_socket(socketPath);
_ipcSocketfd = ipc_open_socket(socketPath); _ipcEventSocketfd = ipc_open_socket(socketPath);
_ipcEventSocketfd = ipc_open_socket(socketPath); const char *subscribe = "[ \"workspace\", \"mode\" ]";
const char *subscribe = "[ \"workspace\", \"mode\" ]"; uint32_t len = strlen(subscribe);
uint32_t len = strlen(subscribe); ipc_single_command(_ipcEventSocketfd, IPC_SUBSCRIBE, subscribe, &len);
ipc_single_command(_ipcEventSocketfd, IPC_SUBSCRIBE, subscribe, &len);
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return;
}
_thread = [this] { _thread = [this] {
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Workspaces::update)); Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Workspaces::update));
_thread.sleep_for(chrono::milliseconds(250)); _thread.sleep_for(chrono::milliseconds(250));