aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.c119
-rw-r--r--src/config.h4
-rw-r--r--src/effect.c90
-rw-r--r--src/effect.h32
-rw-r--r--src/effects/pulse.c91
-rw-r--r--src/effects/scheme.c8
-rw-r--r--src/effects/scheme.h22
-rw-r--r--src/event.c4
-rw-r--r--src/layout.c10
-rw-r--r--src/util.c4
-rw-r--r--src/util.h4
11 files changed, 315 insertions, 73 deletions
diff --git a/src/config.c b/src/config.c
index 84804bc..54d32eb 100644
--- a/src/config.c
+++ b/src/config.c
@@ -10,6 +10,7 @@
#include "util.h"
#include "block.h"
#include "blocks/scheme.h"
+#include "effects/scheme.h"
#define ANY_INI_IMPLEMENT
#include "any_ini.h"
@@ -30,6 +31,11 @@ static const config_entry_t bar_entries[] = {
{ 0 },
};
+static const config_entry_t effect_entries[] = {
+ { "duration", CONFIG_TIME, NULL, offsetof(effect_info_t, duration) },
+ { 0 },
+};
+
static const config_entry_t block_entries[] = {
{ "hidden", CONFIG_BOOL, NULL, offsetof(block_t, hidden) },
{ "color", CONFIG_COLOR, NULL, offsetof(block_t, color) },
@@ -336,11 +342,24 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re
return CONFIG_UNKNOWN;
}
+static config_status_t config_read_effect(const effect_scheme_t *scheme, effect_info_t *info, const char **type,
+ const char *section, const char *key, const char *value)
+{
+ config_status_t status = config_read_entry(effect_entries, info, type, section, key, value);
+ if (status != CONFIG_UNKNOWN)
+ return status;
+
+ return status != CONFIG_UNKNOWN || scheme == NULL || scheme->entries == NULL
+ ? status
+ : config_read_entry(scheme->entries, info->state, type, section, key, value);
+}
+
static config_status_t config_read_block(const block_scheme_t *scheme, block_t *block, const char **type,
const char *section, const char *key, const char *value)
{
config_status_t status = config_read_entry(block_entries, block, type, section, key, value);
- if (status != CONFIG_UNKNOWN) return status;
+ if (status != CONFIG_UNKNOWN)
+ return status;
status = config_read_entry(block->type == BLOCK_GROUP ? block_group_entries : block_text_entries,
block, type, section, key, value);
@@ -383,9 +402,13 @@ void config_read(config_t *config, FILE *file)
int errors = 0;
bool bar_section = false;
+
const block_scheme_t *scheme = NULL;
block_t *block = NULL;
+ const effect_scheme_t *escheme = NULL;
+ effect_info_t *info = NULL;
+
if (section != NULL) {
if (!strncmp(section, "block.", 6)) {
config->blocks = realloc(config->blocks, ++config->n_blocks * sizeof(block_t));
@@ -451,6 +474,68 @@ void config_read(config_t *config, FILE *file)
"i:line", ini.line);
goto skip_pair;
+ } else if (!strncmp(section, "effect.", 7)) {
+ config->infos = realloc(config->infos, ++config->n_infos * sizeof(effect_info_t));
+ assert(config->infos != NULL);
+ info = &config->infos[config->n_infos - 1];
+
+ char *label = strcopy(section + 6);
+ if (label == NULL || *label == '\0') {
+ ++errors;
+ log_value_error("Effect section must have a valid label",
+ "s:section", section,
+ "i:line", ini.line);
+ } else {
+ for (size_t i = 0; i < config->n_infos - 1; i++) {
+ if (!strcmp(label, config->infos[i].label)) {
+ ++errors;
+ log_value_error("Effect section must have a unique label",
+ "s:section", section,
+ "i:line", ini.line);
+ }
+ }
+ }
+
+ if ((key = any_ini_stream_next_key(&ini)) == NULL || strcmp(key, "type")) {
+ ++errors;
+ log_value_error("Effect section must start with a 'type' pair",
+ "s:section", section,
+ "s:wrong_key", key,
+ "i:line", ini.line);
+ goto skip_pair;
+ }
+
+ value = any_ini_stream_next_value(&ini);
+ if (value == NULL) {
+ ++errors;
+ log_value_error("Effect type must be non-empty",
+ "s:section", section,
+ "i:line", ini.line);
+ goto skip_pair;
+ }
+
+ for (int i = 0; effect_schemes[i] != NULL; i++) {
+ if (strcmp(effect_schemes[i]->name, value))
+ continue;
+
+ escheme = effect_schemes[i];
+ memcpy(info, &escheme->info, sizeof(effect_info_t));
+
+ free(info->label);
+ info->label = label;
+
+ if (escheme->size != 0)
+ info->state = calloc(1, escheme->size);
+ goto skip_pair;
+ }
+
+ ++errors;
+ log_value_error("Effect type not supported",
+ "s:section", section,
+ "s:type", value,
+ "i:line", ini.line);
+
+ goto skip_pair;
} else if (!strcmp(section, "bar")) {
bar_section = true;
} else
@@ -466,23 +551,28 @@ void config_read(config_t *config, FILE *file)
"s:value", value,
"i:line", ini.line);
- if (!bar_section && block == NULL)
+ if (!bar_section && block == NULL && info == NULL)
goto skip_pair;
const char *type;
config_status_t status;
- if (bar_section) {
- status = config_read_entry(bar_entries, config, &type, section, key, value);
+ if (info != NULL) {
+ status = config_read_effect(escheme, &config->infos[config->n_infos - 1],
+ &type, section, key, value);
+ } else {
+ if (bar_section) {
+ status = config_read_entry(bar_entries, config, &type, section, key, value);
- // Try the block entries
- if (status == CONFIG_UNKNOWN)
- block = config->blocks;
- }
+ // Try the block entries
+ if (status == CONFIG_UNKNOWN)
+ block = config->blocks;
+ }
- if (block != NULL) {
- status = config_read_block(scheme, &config->blocks[config->n_blocks - 1],
- &type, section, key, value);
+ if (block != NULL) {
+ status = config_read_block(scheme, &config->blocks[config->n_blocks - 1],
+ &type, section, key, value);
+ }
}
switch (status) {
@@ -523,6 +613,13 @@ skip_pair:
errors += !scheme->validate(block, scheme);
}
+ if (info != NULL && escheme != NULL && escheme->validate != NULL) {
+ if (errors != 0)
+ log_trace("Skipped validation for effect '%s'", section);
+ else
+ errors += !escheme->validate(info, escheme);
+ }
+
free(section);
n_errors += errors;
} while ((section = any_ini_stream_next_section(&ini)) != NULL);
diff --git a/src/config.h b/src/config.h
index a7d196f..848cb16 100644
--- a/src/config.h
+++ b/src/config.h
@@ -8,6 +8,8 @@
typedef struct block block_t;
+typedef struct effect_info effect_info_t;
+
typedef enum {
CONFIG_STRING,
CONFIG_INT,
@@ -30,6 +32,8 @@ typedef struct {
typedef struct {
size_t n_blocks;
block_t *blocks;
+ size_t n_infos;
+ effect_info_t *infos;
char *font;
char *monitor;
bool override_redirect;
diff --git a/src/effect.c b/src/effect.c
index 705c42d..9266979 100644
--- a/src/effect.c
+++ b/src/effect.c
@@ -1,53 +1,61 @@
-#include <math.h>
+#include <assert.h>
#include "layout.h"
#include "effect.h"
#include "any_log.h"
-double cubic_bezier(double x, double a, double b, double c, double d)
-{
- const double t = 1 - x;
- return a * (t * t * t) + 3 * b * (t * t * x) + 3 * c * (t * x * x) + d * (x * x * x);
-}
-
-static void effect_pulse_pre(effect_t *effect, layout_t *layout, cairo_t *cr)
-{
- struct timespec now;
- timespec_get(&now, TIME_UTC);
-
- // After half the duration we invert direction
- struct timespec midpoint = timespec_div(effect->duration, 2);
- struct timespec diff = timespec_diff(now, effect->start);
-
- double t = timespec_greater(midpoint, diff)
- ? (double)timespec_to_ms(diff) / timespec_to_ms(midpoint)
- : 1.0 - (double)timespec_to_ms(timespec_diff(diff, midpoint)) / timespec_to_ms(midpoint);
-
- // Make it customizable
- double s = cubic_bezier(t, 0.19, 1.0, 0.22, 1.0);
-
- // Make it a parameter
- const double amplitude = 0.12;
-
- // FIXME: The intent was to scale the animation for long blocks, but it needs more love
- //
- int x_max = amplitude * (layout->height + (layout->width / (double)layout->height) - 1);
- int y_max = amplitude * layout->height;
-
- layout->x_padding = layout->block->x_padding + x_max * s;
- layout->y_padding = layout->block->y_padding + y_max * s;
-}
-effect_t *effect_pulse(struct timespec duration)
+//double cubic_bezier(double x, double a, double b, double c, double d)
+//{
+// const double t = 1 - x;
+// return a * (t * t * t) + 3 * b * (t * t * x) + 3 * c * (t * x * x) + d * (x * x * x);
+//}
+//
+//static void effect_pulse_pre(effect_t *effect, layout_t *layout, cairo_t *cr)
+//{
+// struct timespec now;
+// timespec_get(&now, TIME_UTC);
+//
+// // After half the duration we invert direction
+// struct timespec midpoint = timespec_div(effect->duration, 2);
+// struct timespec diff = timespec_diff(now, effect->start);
+//
+// double t = timespec_greater(midpoint, diff)
+// ? (double)timespec_to_ms(diff) / timespec_to_ms(midpoint)
+// : 1.0 - (double)timespec_to_ms(timespec_diff(diff, midpoint)) / timespec_to_ms(midpoint);
+//
+// // Make it customizable
+// double s = cubic_bezier(t, 0.19, 1.0, 0.22, 1.0);
+//
+// // Make it a parameter
+// const double amplitude = 0.12;
+//
+// // FIXME: The intent was to scale the animation for long blocks, but it needs more love
+// //
+// int x_max = amplitude * (layout->height + (layout->width / (double)layout->height) - 1);
+// int y_max = amplitude * layout->height;
+//
+// layout->x_padding = layout->block->x_padding + x_max * s;
+// layout->y_padding = layout->block->y_padding + y_max * s;
+//}
+//
+//effect_t *effect_pulse(struct timespec duration)
+//{
+// effect_t *effect = calloc(1, sizeof(effect_t));
+// effect->type = EFFECT_PULSE;
+// effect->duration = duration;
+// effect->pre = effect_pulse_pre;
+// return effect;
+//}
+
+void effect_info_free(effect_info_t *info)
{
- effect_t *effect = calloc(1, sizeof(effect_t));
- effect->type = EFFECT_PULSE;
- effect->duration = duration;
- effect->pre = effect_pulse_pre;
- return effect;
+ free(info->state);
+ free(info);
}
void effect_free(effect_t *effect)
{
- free(effect);
+ assert(effect->info->finalize != NULL);
+ effect->info->finalize(effect);
}
diff --git a/src/effect.h b/src/effect.h
index 1bf1a9e..980d339 100644
--- a/src/effect.h
+++ b/src/effect.h
@@ -5,25 +5,41 @@
#include "util.h"
-typedef enum {
- EFFECT_PULSE,
-} effect_type_t;
-
typedef struct effect effect_t;
+typedef struct effect_info effect_info_t;
+
typedef struct layout layout_t;
+// NOTE: Should only allocate the effect and set any extra values
+//
+typedef effect_t *(*effect_allocate_t)(const effect_info_t *info);
+
+// NOTE: Must free any state associated with the effect
+//
+typedef void (*effect_finalize_t)(effect_t *effect);
+
typedef void (*effect_render_t)(effect_t *effect, layout_t *layout, cairo_t *cr);
-struct effect {
- effect_type_t type;
- struct timespec start;
+// NOTE: effect_info's state will be free'd simply
+//
+struct effect_info {
+ char *label;
struct timespec duration;
+ effect_allocate_t allocate;
+ effect_finalize_t finalize;
effect_render_t pre;
effect_render_t post;
+ void *state;
+};
+
+struct effect {
+ effect_info_t *info;
+ struct timespec start;
+ struct effect *next;
};
-effect_t *effect_pulse(struct timespec duration);
+void effect_info_free(effect_info_t *info);
void effect_free(effect_t *effect);
diff --git a/src/effects/pulse.c b/src/effects/pulse.c
new file mode 100644
index 0000000..c2a324a
--- /dev/null
+++ b/src/effects/pulse.c
@@ -0,0 +1,91 @@
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "scheme.h"
+
+#include "../any_log.h"
+
+typedef struct {
+ effect_t effect;
+ double amplitude;
+} effect_pulse_t;
+
+double cubic_bezier(double x, double a, double b, double c, double d)
+{
+ const double t = 1 - x;
+ return a * (t * t * t) + 3 * b * (t * t * x) + 3 * c * (t * x * x) + d * (x * x * x);
+}
+
+static void effect_pulse_pre(effect_t *effect, layout_t *layout, cairo_t *cr)
+{
+ struct timespec now;
+ timespec_get(&now, TIME_UTC);
+
+ // After half the duration we invert direction
+ struct timespec midpoint = timespec_div(effect->info->duration, 2);
+ struct timespec diff = timespec_diff(now, effect->start);
+
+ double t = timespec_greater(midpoint, diff)
+ ? (double)timespec_to_ms(diff) / timespec_to_ms(midpoint)
+ : 1.0 - (double)timespec_to_ms(timespec_diff(diff, midpoint)) / timespec_to_ms(midpoint);
+
+ // Make it customizable
+ double s = cubic_bezier(t, 0.19, 1.0, 0.22, 1.0);
+
+ const double amplitude = ((effect_pulse_t *)effect)->amplitude;
+
+ // FIXME: The intent was to scale the animation for long blocks, but it needs more love
+ //
+ int x_max = amplitude * (layout->height + (layout->width / (double)layout->height) - 1);
+ int y_max = amplitude * layout->height;
+
+ layout->x_padding = layout->block->x_padding + x_max * s;
+ layout->y_padding = layout->block->y_padding + y_max * s;
+}
+
+static effect_t *effect_pulse_allocate(const effect_info_t *info)
+{
+ effect_pulse_t *effect = calloc(1, sizeof(effect_pulse_t));
+ assert(effect != NULL);
+ effect->amplitude = *(unsigned int *)info->state / 100.0;
+ return (effect_t *)effect;
+}
+
+static void effect_pulse_finalize(effect_t *effect)
+{
+ free(effect);
+}
+
+static bool effect_pulse_validate(effect_info_t *info, const effect_scheme_t *scheme)
+{
+ unsigned int amplitude = *(unsigned int *)info->state;
+ if (amplitude > 100) {
+ log_error("Effect '%s' pulse amplitude must not exceed 100", info->label);
+ return false;
+ }
+
+ return true;
+}
+
+static const config_entry_t effect_pulse_entries[] = {
+ { "amplitude", CONFIG_UINT, NULL, 0 },
+ { 0 },
+};
+
+const effect_scheme_t effect_pulse_scheme = {
+ .name = "pulse",
+ .info = {
+ .duration = {
+ .tv_sec = 0,
+ .tv_nsec = 200000000,
+ },
+ .allocate = effect_pulse_allocate,
+ .finalize = effect_pulse_finalize,
+ .pre = effect_pulse_pre,
+ },
+ .size = sizeof(unsigned int),
+ .entries = effect_pulse_entries,
+ .validate = effect_pulse_validate,
+};
diff --git a/src/effects/scheme.c b/src/effects/scheme.c
new file mode 100644
index 0000000..0d70dec
--- /dev/null
+++ b/src/effects/scheme.c
@@ -0,0 +1,8 @@
+#include "scheme.h"
+
+extern const effect_scheme_t effect_pulse_scheme;
+
+const effect_scheme_t *effect_schemes[] = {
+ &effect_pulse_scheme,
+ NULL
+};
diff --git a/src/effects/scheme.h b/src/effects/scheme.h
new file mode 100644
index 0000000..6026b12
--- /dev/null
+++ b/src/effects/scheme.h
@@ -0,0 +1,22 @@
+#ifndef COMET_EFFECTS_SCHEME_H
+#define COMET_EFFECTS_SCHEME_H
+
+#include "../effect.h"
+#include "../config.h"
+#include "../layout.h"
+
+typedef struct effect_scheme effect_scheme_t;
+
+typedef bool (*effect_validate_t)(effect_info_t *info, const effect_scheme_t *scheme);
+
+struct effect_scheme {
+ const char *name;
+ effect_info_t info;
+ size_t size;
+ const config_entry_t *entries;
+ effect_validate_t validate;
+};
+
+extern const effect_scheme_t *effect_schemes[];
+
+#endif
diff --git a/src/event.c b/src/event.c
index 5d315a3..5792a34 100644
--- a/src/event.c
+++ b/src/event.c
@@ -32,10 +32,6 @@ static bool event_click(layout_t *layout, event_t event)
return true;
}
- if (layout->block->effect == NULL) {
- layout->block->effect = effect_pulse(timespec_from_ms(200));
- }
-
log_value_debug("Block was clicked",
"s:type", even_type_to_string(event.type),
"i:x", event.x,
diff --git a/src/layout.c b/src/layout.c
index 3ebbcce..ae476b4 100644
--- a/src/layout.c
+++ b/src/layout.c
@@ -81,13 +81,13 @@ void layout_render(layout_t *layout, cairo_t *cr)
if (timespec_zero(effect->start))
effect->start = now;
- else if (timespec_greater(now, timespec_add(effect->start, effect->duration)))
+ else if (timespec_greater(now, timespec_add(effect->start, effect->info->duration)))
layout->block->effect = NULL;
}
// Pre-processing effects
- if (effect != NULL && effect->pre != NULL) {
- effect->pre(effect, layout, cr);
+ if (effect != NULL && effect->info->pre != NULL) {
+ effect->info->pre(effect, layout, cr);
}
double degree = M_PI / 180.0;
@@ -136,8 +136,8 @@ void layout_render(layout_t *layout, cairo_t *cr)
}
// Post-processing effects
- if (effect != NULL && effect->post != NULL) {
- effect->post(effect, layout, cr);
+ if (effect != NULL && effect->info->post != NULL) {
+ effect->info->post(effect, layout, cr);
}
if (layout->block->effect == NULL && effect != NULL)
diff --git a/src/util.c b/src/util.c
index 301222a..669e031 100644
--- a/src/util.c
+++ b/src/util.c
@@ -28,7 +28,7 @@ void color_print(FILE *stream, color_t *color)
fprintf(stream, "#%02x%02x%02x%02x", r, g, b, a);
}
-struct timespec timespec_from_ms(long ms)
+const struct timespec timespec_from_ms(long ms)
{
struct timespec ts = {
.tv_sec = ms / 1000,
@@ -37,7 +37,7 @@ struct timespec timespec_from_ms(long ms)
return ts;
}
-long timespec_to_ms(struct timespec ts)
+const long timespec_to_ms(struct timespec ts)
{
return (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000ul);
}
diff --git a/src/util.h b/src/util.h
index 0e28006..30acf34 100644
--- a/src/util.h
+++ b/src/util.h
@@ -29,9 +29,9 @@ char *color_to_string(color_t *color);
void color_print(FILE *stream, color_t *color);
-struct timespec timespec_from_ms(long ms);
+const struct timespec timespec_from_ms(long ms);
-long timespec_to_ms(struct timespec ts);
+const long timespec_to_ms(struct timespec ts);
struct timespec timespec_diff(struct timespec a, struct timespec b);