fix(battery): Proper handling of charge animation
Closes jaagr/lemonbuddy#3
This commit is contained in:
parent
925469fec1
commit
23b2cc69dd
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include "modules/base.hpp"
|
#include "modules/base.hpp"
|
||||||
#include "drawtypes/animation.hpp"
|
#include "drawtypes/animation.hpp"
|
||||||
@ -13,29 +12,25 @@
|
|||||||
|
|
||||||
namespace modules
|
namespace modules
|
||||||
{
|
{
|
||||||
enum BatteryState
|
|
||||||
{
|
|
||||||
UNKNOWN = 1 << 1,
|
|
||||||
CHARGING = 1 << 2,
|
|
||||||
DISCHARGING = 1 << 4,
|
|
||||||
FULL = 1 << 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
DefineModule(BatteryModule, InotifyModule)
|
DefineModule(BatteryModule, InotifyModule)
|
||||||
{
|
{
|
||||||
const char *FORMAT_CHARGING = "format:charging";
|
public:
|
||||||
const char *FORMAT_DISCHARGING = "format:discharging";
|
static const int STATE_UNKNOWN = 1;
|
||||||
const char *FORMAT_FULL = "format:full";
|
static const int STATE_CHARGING = 2;
|
||||||
|
static const int STATE_DISCHARGING = 3;
|
||||||
|
static const int STATE_FULL = 4;
|
||||||
|
|
||||||
const char *TAG_ANIMATION_CHARGING = "<animation:charging>";
|
protected:
|
||||||
const char *TAG_BAR_CAPACITY = "<bar:capacity>";
|
static constexpr auto FORMAT_CHARGING = "format:charging";
|
||||||
const char *TAG_RAMP_CAPACITY = "<ramp:capacity>";
|
static constexpr auto FORMAT_DISCHARGING = "format:discharging";
|
||||||
const char *TAG_LABEL_CHARGING = "<label:charging>";
|
static constexpr auto FORMAT_FULL = "format:full";
|
||||||
const char *TAG_LABEL_DISCHARGING = "<label:discharging>";
|
|
||||||
const char *TAG_LABEL_FULL = "<label:full>";
|
|
||||||
|
|
||||||
// std::mutex ev_mtx;
|
static constexpr auto TAG_ANIMATION_CHARGING = "<animation:charging>";
|
||||||
// std::condition_variable cv;
|
static constexpr auto TAG_BAR_CAPACITY = "<bar:capacity>";
|
||||||
|
static constexpr auto TAG_RAMP_CAPACITY = "<ramp:capacity>";
|
||||||
|
static constexpr auto TAG_LABEL_CHARGING = "<label:charging>";
|
||||||
|
static constexpr auto TAG_LABEL_DISCHARGING = "<label:discharging>";
|
||||||
|
static constexpr auto TAG_LABEL_FULL = "<label:full>";
|
||||||
|
|
||||||
std::unique_ptr<drawtypes::Animation> animation_charging;
|
std::unique_ptr<drawtypes::Animation> animation_charging;
|
||||||
std::unique_ptr<drawtypes::Ramp> ramp_capacity;
|
std::unique_ptr<drawtypes::Ramp> ramp_capacity;
|
||||||
@ -49,8 +44,7 @@ namespace modules
|
|||||||
|
|
||||||
std::string battery, adapter;
|
std::string battery, adapter;
|
||||||
concurrency::Atomic<int> state;
|
concurrency::Atomic<int> state;
|
||||||
// std::atomic<int> state;
|
concurrency::Atomic<int> percentage;
|
||||||
std::atomic<int> percentage;
|
|
||||||
int full_at;
|
int full_at;
|
||||||
|
|
||||||
void animation_thread_runner();
|
void animation_thread_runner();
|
||||||
|
@ -80,6 +80,12 @@ namespace concurrency
|
|||||||
std::lock_guard<concurrency::SpinLock> lck(this->lock);
|
std::lock_guard<concurrency::SpinLock> lck(this->lock);
|
||||||
return this->value;
|
return this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(T const& b)
|
||||||
|
{
|
||||||
|
std::lock_guard<concurrency::SpinLock> lck(this->lock);
|
||||||
|
return this->value == b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -111,5 +117,11 @@ namespace concurrency
|
|||||||
std::lock_guard<concurrency::SpinLock> lck(this->lock);
|
std::lock_guard<concurrency::SpinLock> lck(this->lock);
|
||||||
return this->value;
|
return this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(T const& b)
|
||||||
|
{
|
||||||
|
std::lock_guard<concurrency::SpinLock> lck(this->lock);
|
||||||
|
return this->value == b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ int main(int argc, char **argv)
|
|||||||
eventloop->wait();
|
eventloop->wait();
|
||||||
|
|
||||||
} catch (Exception &e) {
|
} catch (Exception &e) {
|
||||||
logger->fatal(e.what());
|
logger->error(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
eventloop->stop();
|
eventloop->stop();
|
||||||
|
@ -11,12 +11,20 @@
|
|||||||
|
|
||||||
using namespace modules;
|
using namespace modules;
|
||||||
|
|
||||||
|
const int modules::BatteryModule::STATE_UNKNOWN;
|
||||||
|
const int modules::BatteryModule::STATE_CHARGING;
|
||||||
|
const int modules::BatteryModule::STATE_DISCHARGING;
|
||||||
|
const int modules::BatteryModule::STATE_FULL;
|
||||||
|
|
||||||
BatteryModule::BatteryModule(const std::string& name_) : InotifyModule(name_)
|
BatteryModule::BatteryModule(const std::string& name_) : InotifyModule(name_)
|
||||||
{
|
{
|
||||||
this->battery = config::get<std::string>(name(), "battery", "BAT0");
|
this->battery = config::get<std::string>(name(), "battery", "BAT0");
|
||||||
this->adapter = config::get<std::string>(name(), "adapter", "ADP1");
|
this->adapter = config::get<std::string>(name(), "adapter", "ADP1");
|
||||||
this->full_at = config::get<int>(name(), "full_at", 100);
|
this->full_at = config::get<int>(name(), "full_at", 100);
|
||||||
|
|
||||||
|
this->state = STATE_UNKNOWN;
|
||||||
|
this->percentage = 0;
|
||||||
|
|
||||||
this->formatter->add(FORMAT_CHARGING, TAG_LABEL_CHARGING,
|
this->formatter->add(FORMAT_CHARGING, TAG_LABEL_CHARGING,
|
||||||
{ TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_ANIMATION_CHARGING, TAG_LABEL_CHARGING });
|
{ TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_ANIMATION_CHARGING, TAG_LABEL_CHARGING });
|
||||||
|
|
||||||
@ -45,44 +53,54 @@ BatteryModule::BatteryModule(const std::string& name_) : InotifyModule(name_)
|
|||||||
this->label_full = drawtypes::get_optional_config_label(
|
this->label_full = drawtypes::get_optional_config_label(
|
||||||
name(), get_tag_name(TAG_LABEL_FULL), "%percentage%");
|
name(), get_tag_name(TAG_LABEL_FULL), "%percentage%");
|
||||||
|
|
||||||
this->watch(string::replace(PATH_BATTERY_CAPACITY, "%battery%", this->battery));
|
this->watch(string::replace(PATH_BATTERY_CAPACITY, "%battery%", this->battery), InotifyEvent::ACCESSED);
|
||||||
this->watch(string::replace(PATH_ADAPTER_STATUS, "%adapter%", this->adapter));
|
this->watch(string::replace(PATH_ADAPTER_STATUS, "%adapter%", this->adapter), InotifyEvent::ACCESSED);
|
||||||
|
|
||||||
if (this->animation_charging) {
|
if (this->animation_charging)
|
||||||
this->threads.emplace_back(std::thread(&BatteryModule::animation_thread_runner, this));
|
this->threads.emplace_back(std::thread(&BatteryModule::animation_thread_runner, this));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void BatteryModule::animation_thread_runner()
|
void BatteryModule::animation_thread_runner()
|
||||||
|
{
|
||||||
|
std::this_thread::yield();
|
||||||
|
|
||||||
|
const auto dur = std::chrono::duration<double>(
|
||||||
|
float(this->animation_charging->get_framerate()) / 1000.0f);
|
||||||
|
|
||||||
|
int retries = 5;
|
||||||
|
|
||||||
|
while (retries-- > 0)
|
||||||
{
|
{
|
||||||
while (this->enabled()) {
|
while (this->enabled()) {
|
||||||
// std::unique_lock<std::mutex> lck(this->ev_mtx);
|
std::unique_lock<concurrency::SpinLock> lck(this->broadcast_lock);
|
||||||
|
|
||||||
auto state = this->state();
|
if (retries > 0)
|
||||||
|
retries = 0;
|
||||||
|
|
||||||
if (state & CHARGING && !(state & FULL)) {
|
if (this->state == STATE_CHARGING) {
|
||||||
|
lck.unlock();
|
||||||
this->broadcast();
|
this->broadcast();
|
||||||
// else
|
|
||||||
// this->cv.wait(lck, [&]{ return this->state & CHARGING && ~this->state & FULL; });
|
|
||||||
std::this_thread::sleep_for(std::chrono::duration<double>(
|
|
||||||
float(this->animation_charging->get_framerate()) / 1000));
|
|
||||||
} else {
|
} else {
|
||||||
std::this_thread::sleep_for(1s);
|
log_trace("state != charging");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(dur);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(500ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BatteryModule::on_event(InotifyEvent *event)
|
bool BatteryModule::on_event(InotifyEvent *event)
|
||||||
{
|
{
|
||||||
// std::unique_lock<std::mutex> lck(this->ev_mtx);
|
|
||||||
|
|
||||||
if (event != nullptr)
|
if (event != nullptr)
|
||||||
log_trace(event->filename);
|
log_trace(event->filename);
|
||||||
|
|
||||||
|
int state = STATE_UNKNOWN;
|
||||||
|
|
||||||
auto path_capacity = string::replace(PATH_BATTERY_CAPACITY, "%battery%", this->battery);
|
auto path_capacity = string::replace(PATH_BATTERY_CAPACITY, "%battery%", this->battery);
|
||||||
auto path_status = string::replace(PATH_ADAPTER_STATUS, "%adapter%", this->adapter);
|
auto path_status = string::replace(PATH_ADAPTER_STATUS, "%adapter%", this->adapter);
|
||||||
auto status = io::file::get_contents(path_status);
|
auto status = io::file::get_contents(path_status);
|
||||||
int state = UNKNOWN;
|
|
||||||
|
|
||||||
if (status.empty()) {
|
if (status.empty()) {
|
||||||
log_error("Failed to read "+ path_status);
|
log_error("Failed to read "+ path_status);
|
||||||
@ -96,20 +114,18 @@ bool BatteryModule::on_event(InotifyEvent *event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->percentage = (int) math::cap<float>(std::atof(capacity.c_str()), 0, 100) + 0.5;
|
int percentage = (int) math::cap<float>(std::atof(capacity.c_str()), 0, 100) + 0.5;
|
||||||
|
|
||||||
switch (status[0]) {
|
switch (status[0]) {
|
||||||
case '0': state = DISCHARGING; break;
|
case '0': state = STATE_DISCHARGING; break;
|
||||||
case '1': state = CHARGING; break;
|
case '1': state = STATE_CHARGING; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->state() & CHARGING && this->percentage >= this->full_at)
|
if ((state == STATE_CHARGING) && percentage >= this->full_at)
|
||||||
this->percentage = 100;
|
percentage = 100;
|
||||||
|
|
||||||
if (this->percentage == 100)
|
if (percentage == 100)
|
||||||
state |= FULL;
|
state = STATE_FULL;
|
||||||
|
|
||||||
this->state = state;
|
|
||||||
|
|
||||||
if (!this->label_charging_tokenized)
|
if (!this->label_charging_tokenized)
|
||||||
this->label_charging_tokenized = this->label_charging->clone();
|
this->label_charging_tokenized = this->label_charging->clone();
|
||||||
@ -118,31 +134,28 @@ bool BatteryModule::on_event(InotifyEvent *event)
|
|||||||
if (!this->label_full_tokenized)
|
if (!this->label_full_tokenized)
|
||||||
this->label_full_tokenized = this->label_full->clone();
|
this->label_full_tokenized = this->label_full->clone();
|
||||||
|
|
||||||
auto percentage_str = std::to_string(this->percentage) + "%";
|
|
||||||
|
|
||||||
this->label_charging_tokenized->text = this->label_charging->text;
|
this->label_charging_tokenized->text = this->label_charging->text;
|
||||||
this->label_charging_tokenized->replace_token("%percentage%", percentage_str);
|
this->label_charging_tokenized->replace_token("%percentage%", std::to_string(percentage) + "%");
|
||||||
|
|
||||||
this->label_discharging_tokenized->text = this->label_discharging->text;
|
this->label_discharging_tokenized->text = this->label_discharging->text;
|
||||||
this->label_discharging_tokenized->replace_token("%percentage%", std::to_string(this->percentage) +"%");
|
this->label_discharging_tokenized->replace_token("%percentage%", std::to_string(percentage) + "%");
|
||||||
|
|
||||||
this->label_full_tokenized->text = this->label_full->text;
|
this->label_full_tokenized->text = this->label_full->text;
|
||||||
this->label_full_tokenized->replace_token("%percentage%", percentage_str);
|
this->label_full_tokenized->replace_token("%percentage%", std::to_string(percentage) + "%");
|
||||||
|
|
||||||
// lck.unlock();
|
this->state = state;
|
||||||
//
|
this->percentage = percentage;
|
||||||
// this->cv.notify_all();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BatteryModule::get_format()
|
std::string BatteryModule::get_format()
|
||||||
{
|
{
|
||||||
auto state = this->state();
|
int state = this->state();
|
||||||
|
|
||||||
if (state & FULL)
|
if (state == STATE_FULL)
|
||||||
return FORMAT_FULL;
|
return FORMAT_FULL;
|
||||||
else if (state & CHARGING)
|
else if (state == STATE_CHARGING)
|
||||||
return FORMAT_CHARGING;
|
return FORMAT_CHARGING;
|
||||||
else
|
else
|
||||||
return FORMAT_DISCHARGING;
|
return FORMAT_DISCHARGING;
|
||||||
@ -153,16 +166,9 @@ bool BatteryModule::build(Builder *builder, const std::string& tag)
|
|||||||
if (tag == TAG_ANIMATION_CHARGING)
|
if (tag == TAG_ANIMATION_CHARGING)
|
||||||
builder->node(this->animation_charging);
|
builder->node(this->animation_charging);
|
||||||
else if (tag == TAG_BAR_CAPACITY) {
|
else if (tag == TAG_BAR_CAPACITY) {
|
||||||
builder->node(this->bar_capacity, this->percentage);
|
builder->node(this->bar_capacity, this->percentage());
|
||||||
// builder->node(this->bar_capacity, 10);
|
|
||||||
// builder->space(5);
|
|
||||||
// builder->node(this->bar_capacity, 50);
|
|
||||||
// builder->space(5);
|
|
||||||
// builder->node(this->bar_capacity, 90);
|
|
||||||
// builder->space(5);
|
|
||||||
// builder->node(this->bar_capacity, 100);
|
|
||||||
} else if (tag == TAG_RAMP_CAPACITY)
|
} else if (tag == TAG_RAMP_CAPACITY)
|
||||||
builder->node(this->ramp_capacity, this->percentage);
|
builder->node(this->ramp_capacity, this->percentage());
|
||||||
else if (tag == TAG_LABEL_CHARGING)
|
else if (tag == TAG_LABEL_CHARGING)
|
||||||
builder->node(this->label_charging_tokenized);
|
builder->node(this->label_charging_tokenized);
|
||||||
else if (tag == TAG_LABEL_DISCHARGING)
|
else if (tag == TAG_LABEL_DISCHARGING)
|
||||||
|
Loading…
Reference in New Issue
Block a user