aboutsummaryrefslogtreecommitdiff
path: root/src/config.c
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-09-18 14:49:59 +0200
committerFederico Angelilli <code@fedang.net>2024-09-18 14:49:59 +0200
commit0eceb95c0a4b517d7eb537a464089f011e3804e2 (patch)
tree54e2646d5a7c43b3fec074ebe98d4a33aefde025 /src/config.c
parentbc70dead7fb518f073fecb21a04fa374e9ad6dd0 (diff)
Add effect parsingeffect-conf
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c117
1 files changed, 107 insertions, 10 deletions
diff --git a/src/config.c b/src/config.c
index 84804bc..1b88b06 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"
@@ -43,6 +44,11 @@ static const config_entry_t block_entries[] = {
{ 0 },
};
+static const config_entry_t effect_entries[] = {
+ { "duration", CONFIG_TIME, NULL, offsetof(effect_t, duration) },
+ { 0 },
+};
+
static const config_entry_t block_group_entries[] = {
{ "spacing", CONFIG_UINT, NULL, offsetof(block_t, group.spacing) },
{ "blocks", CONFIG_LIST, NULL, offsetof(block_t, group.children) },
@@ -350,6 +356,17 @@ static config_status_t config_read_block(const block_scheme_t *scheme, block_t *
: config_read_entry(scheme->entries, block->state, type, section, key, value);
}
+static config_status_t config_read_effect(const effect_scheme_t *scheme, effect_t *effect, const char **type,
+ const char *section, const char *key, const char *value)
+{
+ config_status_t status = config_read_entry(effect_entries, effect, 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, effect->state, type, section, key, value);
+}
+
void config_init(config_t *config)
{
const config_t config_default = {
@@ -383,9 +400,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_t *effect = NULL;
+
if (section != NULL) {
if (!strncmp(section, "block.", 6)) {
config->blocks = realloc(config->blocks, ++config->n_blocks * sizeof(block_t));
@@ -451,6 +472,70 @@ void config_read(config_t *config, FILE *file)
"i:line", ini.line);
goto skip_pair;
+ } else if (!strncmp(section, "effect.", 7)) {
+ config->effects = realloc(config->effects, ++config->n_effects * sizeof(effect_t));
+ assert(config->effects != NULL);
+ effect = &config->effects[config->n_effects - 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_effects - 1; i++) {
+ if (!strcmp(label, config->effects[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];
+ effect_copy(effect, &escheme->effect);
+ free(effect->label);
+ effect->label = label;
+
+ if (escheme->size != 0) {
+ effect->state = malloc(escheme->size);
+ memset(effect->state, 0, 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,25 +551,31 @@ 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 && effect == 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 (effect != NULL) {
+ status = config_read_effect(escheme, &config->effects[config->n_effects - 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) {
case CONFIG_SUCCESS:
break;
@@ -522,6 +613,12 @@ skip_pair:
else
errors += !scheme->validate(block, scheme);
}
+ if (effect != NULL && escheme != NULL && escheme->validate != NULL) {
+ if (errors != 0)
+ log_trace("Skipped validation for effect '%s'", section);
+ else
+ errors += !escheme->validate(effect, escheme);
+ }
free(section);
n_errors += errors;