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 {
public:
Factory(Bar &bar, Json::Value config);
IModule &makeModule(std::string name);
IModule *makeModule(std::string name);
private:
Bar &_bar;
Json::Value _config;

View File

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

View File

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

View File

@ -167,24 +167,27 @@ auto waybar::Bar::_setupWidgets() -> void
box1.pack_end(right, true, true);
Factory factory(*this, _config);
if (_config["modules-left"]) {
for (auto name : _config["modules-left"]) {
auto &module = factory.makeModule(name.asString());
left.pack_start(module, false, true, 0);
auto module = factory.makeModule(name.asString());
if (module)
left.pack_start(*module, false, true, 0);
}
}
if (_config["modules-center"]) {
for (auto name : _config["modules-center"]) {
auto &module = factory.makeModule(name.asString());
center.pack_start(module, true, false, 10);
auto module = factory.makeModule(name.asString());
if (module)
center.pack_start(*module, true, false, 10);
}
}
if (_config["modules-right"]) {
std::reverse(_config["modules-right"].begin(), _config["modules-right"].end());
for (auto name : _config["modules-right"]) {
auto &module = factory.makeModule(name.asString());
right.pack_end(module, false, false, 0);
auto module = factory.makeModule(name.asString());
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)
{}
waybar::IModule &waybar::Factory::makeModule(std::string name)
waybar::IModule *waybar::Factory::makeModule(std::string name)
{
if (name == "battery")
return *new waybar::modules::Battery(_config[name]);
if (name == "workspaces")
return *new waybar::modules::Workspaces(_bar);
if (name == "memory")
return *new waybar::modules::Memory(_config[name]);
if (name == "cpu")
return *new waybar::modules::Cpu(_config[name]);
if (name == "clock")
return *new waybar::modules::Clock(_config[name]);
if (name == "network")
return *new waybar::modules::Network(_config[name]);
if (name == "pulseaudio")
return *new waybar::modules::Pulseaudio(_config[name]);
if (!name.compare(0, 7, "custom/") && name.size() > 7)
return *new waybar::modules::Custom(name.substr(7), _config[name]);
throw std::runtime_error("Unknown module: " + name);
try {
if (name == "battery")
return new waybar::modules::Battery(_config[name]);
if (name == "workspaces")
return new waybar::modules::Workspaces(_bar);
if (name == "memory")
return new waybar::modules::Memory(_config[name]);
if (name == "cpu")
return new waybar::modules::Cpu(_config[name]);
if (name == "clock")
return new waybar::modules::Clock(_config[name]);
if (name == "network")
return new waybar::modules::Network(_config[name]);
if (name == "pulseaudio")
return new waybar::modules::Pulseaudio(_config[name]);
if (!name.compare(0, 7, "custom/") && name.size() > 7)
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 {
for (auto &node : fs::directory_iterator(_data_dir)) {
if (fs::is_directory(node) && fs::exists(node / "capacity")
&& fs::exists(node / "status")) {
if (fs::is_directory(node) && fs::exists(node / "capacity"))
_batteries.push_back(node);
}
}
} catch (fs::filesystem_error &e) {
std::cerr << e.what() << std::endl;
throw std::runtime_error(e.what());
}
if (!_batteries.size()) {
std::cerr << "No batteries." << std::endl;
return;
}
if (!_batteries.size())
throw std::runtime_error("No batteries.");
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");
int interval = _config["interval"] ? _config["inveral"].asInt() : 1;
_thread = [this, interval] {
_thread = [this, fd] {
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));
_thread.sleep_for(chrono::seconds(interval));
};
}
auto waybar::modules::Battery::update() -> void
{
try {
int total = 0;
uint16_t total = 0;
bool charging = false;
std::string status;
for (auto &bat : _batteries) {
int capacity;
std::string status;
uint16_t capacity;
std::ifstream(bat / "capacity") >> capacity;
total += capacity;
std::ifstream(bat / "status") >> status;
if (status == "Charging") {
if (status == "Charging")
charging = true;
}
total += capacity;
}
uint16_t capacity = total / _batteries.size();
auto format = _config["format"] ? _config["format"].asString() : "{}%";
auto value = total / _batteries.size();
_label.set_text(fmt::format(format, fmt::arg("value", value),
fmt::arg("icon", _getIcon(value))));
_label.set_tooltip_text(charging ? "Charging" : "Discharging");
_label.set_text(fmt::format(format, fmt::arg("value", capacity),
fmt::arg("icon", _getIcon(capacity))));
_label.set_tooltip_text(status);
if (charging)
_label.get_style_context()->add_class("charging");
else
_label.get_style_context()->remove_class("charging");
if (value < 16 && !charging)
if (capacity < 16 && !charging)
_label.get_style_context()->add_class("warning");
else
_label.get_style_context()->remove_class("warning");
} catch (std::exception &e) {
} catch (const std::exception& e) {
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 "";
auto step = 100 / _config["format-icons"].size();

View File

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

View File

@ -1,8 +1,10 @@
#include "modules/network.hpp"
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");
int interval = _config["interval"] ? _config["inveral"].asInt() : 30;
_thread = [this, interval] {
@ -103,8 +105,6 @@ bool waybar::modules::Network::_associatedOrJoined(struct nlattr** bss)
auto waybar::modules::Network::_getInfo() -> void
{
if (_ifid == 0)
return;
struct nl_sock *sk = nl_socket_alloc();
if (genl_connect(sk) != 0) {
nl_socket_free(sk);

View File

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