mirror of
https://codeberg.org/dnkl/yambar.git
synced 2025-04-24 21:05:40 +02:00
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
|
* YAML parsing error messages being replaced with a generic _“unknown
|
||||||
error”_.
|
error”_.
|
||||||
* Memory leak when a YAML parsing error was encountered.
|
* Memory leak when a YAML parsing error was encountered.
|
||||||
|
* clock: update every second when necessary
|
||||||
|
(https://codeberg.org/dnkl/yambar/issues/12).
|
||||||
|
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
|
@ -4,7 +4,11 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <poll.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 "../bar/bar.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include "../config-verify.h"
|
#include "../config-verify.h"
|
||||||
|
@ -12,6 +16,10 @@
|
||||||
|
|
||||||
struct private {
|
struct private {
|
||||||
struct particle *label;
|
struct particle *label;
|
||||||
|
enum {
|
||||||
|
UPDATE_GRANULARITY_SECONDS,
|
||||||
|
UPDATE_GRANULARITY_MINUTES,
|
||||||
|
} update_granularity;
|
||||||
char *date_format;
|
char *date_format;
|
||||||
char *time_format;
|
char *time_format;
|
||||||
};
|
};
|
||||||
|
@ -55,20 +63,56 @@ content(struct module *mod)
|
||||||
static int
|
static int
|
||||||
run(struct module *mod)
|
run(struct module *mod)
|
||||||
{
|
{
|
||||||
|
const struct private *m = mod->private;
|
||||||
const struct bar *bar = mod->bar;
|
const struct bar *bar = mod->bar;
|
||||||
bar->refresh(bar);
|
bar->refresh(bar);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
time_t now = time(NULL);
|
struct timespec _now;
|
||||||
time_t now_no_secs = now / 60 * 60;
|
clock_gettime(CLOCK_REALTIME, &_now);
|
||||||
assert(now_no_secs % 60 == 0);
|
|
||||||
|
|
||||||
time_t next_min = now_no_secs + 60;
|
const struct timeval now = {
|
||||||
time_t timeout = next_min - now;
|
.tv_sec = _now.tv_sec,
|
||||||
assert(timeout >= 0 && timeout <= 60);
|
.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}};
|
struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}};
|
||||||
poll(fds, 1, timeout * 1000);
|
poll(fds, 1, timeout_ms);
|
||||||
|
|
||||||
if (fds[0].revents & POLLIN)
|
if (fds[0].revents & POLLIN)
|
||||||
break;
|
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->date_format = strdup(date_format);
|
||||||
m->time_format = strdup(time_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();
|
struct module *mod = module_common_new();
|
||||||
mod->private = m;
|
mod->private = m;
|
||||||
mod->run = &run;
|
mod->run = &run;
|
||||||
|
|
Loading…
Add table
Reference in a new issue