forked from external/yambar
Merge branch 'clock-seconds-granularity' into master
This commit is contained in:
commit
bd29bf765b
2 changed files with 78 additions and 7 deletions
|
@ -18,6 +18,8 @@
|
|||
* YAML parsing error messages being replaced with a generic _“unknown
|
||||
error”_.
|
||||
* Memory leak when a YAML parsing error was encountered.
|
||||
* clock: update every second when necessary
|
||||
(https://codeberg.org/dnkl/yambar/issues/12).
|
||||
|
||||
|
||||
### Security
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define LOG_MODULE "clock"
|
||||
#define LOG_ENABLE_DBG 0
|
||||
#include "../log.h"
|
||||
#include "../bar/bar.h"
|
||||
#include "../config.h"
|
||||
#include "../config-verify.h"
|
||||
|
@ -12,6 +16,10 @@
|
|||
|
||||
struct private {
|
||||
struct particle *label;
|
||||
enum {
|
||||
UPDATE_GRANULARITY_SECONDS,
|
||||
UPDATE_GRANULARITY_MINUTES,
|
||||
} update_granularity;
|
||||
char *date_format;
|
||||
char *time_format;
|
||||
};
|
||||
|
@ -55,20 +63,56 @@ content(struct module *mod)
|
|||
static int
|
||||
run(struct module *mod)
|
||||
{
|
||||
const struct private *m = mod->private;
|
||||
const struct bar *bar = mod->bar;
|
||||
bar->refresh(bar);
|
||||
|
||||
while (true) {
|
||||
time_t now = time(NULL);
|
||||
time_t now_no_secs = now / 60 * 60;
|
||||
assert(now_no_secs % 60 == 0);
|
||||
struct timespec _now;
|
||||
clock_gettime(CLOCK_REALTIME, &_now);
|
||||
|
||||
time_t next_min = now_no_secs + 60;
|
||||
time_t timeout = next_min - now;
|
||||
assert(timeout >= 0 && timeout <= 60);
|
||||
const struct timeval now = {
|
||||
.tv_sec = _now.tv_sec,
|
||||
.tv_usec = _now.tv_nsec / 1000,
|
||||
};
|
||||
|
||||
int timeout_ms;
|
||||
|
||||
switch (m->update_granularity) {
|
||||
case UPDATE_GRANULARITY_SECONDS: {
|
||||
const struct timeval next_second = {
|
||||
.tv_sec = now.tv_sec + 1,
|
||||
.tv_usec = 0};
|
||||
|
||||
struct timeval _timeout;
|
||||
timersub(&next_second, &now, &_timeout);
|
||||
|
||||
assert(_timeout.tv_sec == 0 ||
|
||||
(_timeout.tv_sec == 1 && _timeout.tv_usec == 0));
|
||||
timeout_ms = _timeout.tv_usec / 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
case UPDATE_GRANULARITY_MINUTES: {
|
||||
const struct timeval next_minute = {
|
||||
.tv_sec = now.tv_sec / 60 * 60 + 60,
|
||||
.tv_usec = 0,
|
||||
};
|
||||
|
||||
struct timeval _timeout;
|
||||
timersub(&next_minute, &now, &_timeout);
|
||||
timeout_ms = _timeout.tv_sec * 1000 + _timeout.tv_usec / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add 1ms to account for rounding errors */
|
||||
timeout_ms++;
|
||||
|
||||
LOG_DBG("now: %lds %ldµs -> timeout: %dms",
|
||||
now.tv_sec, now.tv_usec, timeout_ms);
|
||||
|
||||
struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}};
|
||||
poll(fds, 1, timeout * 1000);
|
||||
poll(fds, 1, timeout_ms);
|
||||
|
||||
if (fds[0].revents & POLLIN)
|
||||
break;
|
||||
|
@ -87,6 +131,31 @@ clock_new(struct particle *label, const char *date_format, const char *time_form
|
|||
m->date_format = strdup(date_format);
|
||||
m->time_format = strdup(time_format);
|
||||
|
||||
static const char *const seconds_formatters[] = {
|
||||
"%c",
|
||||
"%s",
|
||||
"%S",
|
||||
"%T",
|
||||
"%r",
|
||||
"%X",
|
||||
};
|
||||
|
||||
m->update_granularity = UPDATE_GRANULARITY_MINUTES;
|
||||
|
||||
for (size_t i = 0;
|
||||
i < sizeof(seconds_formatters) / sizeof(seconds_formatters[0]);
|
||||
i++)
|
||||
{
|
||||
if (strstr(time_format, seconds_formatters[i]) != NULL) {
|
||||
m->update_granularity = UPDATE_GRANULARITY_SECONDS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DBG("using %s update granularity",
|
||||
(m->update_granularity == UPDATE_GRANULARITY_MINUTES
|
||||
? "minutes" : "seconds"));
|
||||
|
||||
struct module *mod = module_common_new();
|
||||
mod->private = m;
|
||||
mod->run = &run;
|
||||
|
|
Loading…
Add table
Reference in a new issue