config: handle transform opts; make implementation futureproof
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ic67d4485d08114f605a6dc2535224b276a6a6964
This commit is contained in:
parent
1a366d2445
commit
5fd2e5660f
1 changed files with 186 additions and 9 deletions
195
src/config.c
195
src/config.c
|
|
@ -52,11 +52,81 @@ static bool parse_bool(const char *value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse integer value from string
|
// Parse scaling mode from string
|
||||||
|
static chroma_scale_mode_t parse_scale_mode(const char *value) {
|
||||||
|
if (!value)
|
||||||
|
return CHROMA_SCALE_FILL; // default
|
||||||
|
|
||||||
|
if (strcasecmp(value, "fill") == 0) {
|
||||||
|
return CHROMA_SCALE_FILL;
|
||||||
|
} else if (strcasecmp(value, "fit") == 0) {
|
||||||
|
return CHROMA_SCALE_FIT;
|
||||||
|
} else if (strcasecmp(value, "stretch") == 0) {
|
||||||
|
return CHROMA_SCALE_STRETCH;
|
||||||
|
} else if (strcasecmp(value, "center") == 0) {
|
||||||
|
return CHROMA_SCALE_CENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
chroma_log("WARN", "Unknown scaling mode: %s (using fill)", value);
|
||||||
|
return CHROMA_SCALE_FILL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse filter quality from string
|
||||||
|
static chroma_filter_quality_t parse_filter_quality(const char *value) {
|
||||||
|
if (!value)
|
||||||
|
return CHROMA_FILTER_LINEAR; // default
|
||||||
|
|
||||||
|
if (strcasecmp(value, "nearest") == 0) {
|
||||||
|
return CHROMA_FILTER_NEAREST;
|
||||||
|
} else if (strcasecmp(value, "linear") == 0) {
|
||||||
|
return CHROMA_FILTER_LINEAR;
|
||||||
|
} else if (strcasecmp(value, "bilinear") == 0) {
|
||||||
|
return CHROMA_FILTER_BILINEAR;
|
||||||
|
} else if (strcasecmp(value, "trilinear") == 0) {
|
||||||
|
return CHROMA_FILTER_TRILINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
chroma_log("WARN", "Unknown filter quality: %s (using linear)", value);
|
||||||
|
return CHROMA_FILTER_LINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get string representation of scaling mode
|
||||||
|
static const char *scale_mode_to_string(chroma_scale_mode_t mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case CHROMA_SCALE_FILL:
|
||||||
|
return "fill";
|
||||||
|
case CHROMA_SCALE_FIT:
|
||||||
|
return "fit";
|
||||||
|
case CHROMA_SCALE_STRETCH:
|
||||||
|
return "stretch";
|
||||||
|
case CHROMA_SCALE_CENTER:
|
||||||
|
return "center";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get string representation of filter quality
|
||||||
|
static const char *filter_quality_to_string(chroma_filter_quality_t quality) {
|
||||||
|
switch (quality) {
|
||||||
|
case CHROMA_FILTER_NEAREST:
|
||||||
|
return "nearest";
|
||||||
|
case CHROMA_FILTER_LINEAR:
|
||||||
|
return "linear";
|
||||||
|
case CHROMA_FILTER_BILINEAR:
|
||||||
|
return "bilinear";
|
||||||
|
case CHROMA_FILTER_TRILINEAR:
|
||||||
|
return "trilinear";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Output-to-image mapping
|
// Output-to-image mapping
|
||||||
static int add_output_mapping(chroma_config_t *config, const char *output_name,
|
static int add_output_mapping(chroma_config_t *config, const char *output_name,
|
||||||
const char *image_path) {
|
const char *image_path,
|
||||||
|
chroma_scale_mode_t scale_mode,
|
||||||
|
chroma_filter_quality_t filter_quality) {
|
||||||
if (!config || !output_name || !image_path) {
|
if (!config || !output_name || !image_path) {
|
||||||
return CHROMA_ERROR_INIT;
|
return CHROMA_ERROR_INIT;
|
||||||
}
|
}
|
||||||
|
|
@ -87,10 +157,14 @@ static int add_output_mapping(chroma_config_t *config, const char *output_name,
|
||||||
|
|
||||||
strcpy(mapping->output_name, output_name);
|
strcpy(mapping->output_name, output_name);
|
||||||
strcpy(mapping->image_path, image_path);
|
strcpy(mapping->image_path, image_path);
|
||||||
|
mapping->scale_mode = scale_mode;
|
||||||
|
mapping->filter_quality = filter_quality;
|
||||||
|
|
||||||
config->mapping_count++;
|
config->mapping_count++;
|
||||||
|
|
||||||
chroma_log("DEBUG", "Added mapping: %s -> %s", output_name, image_path);
|
chroma_log("DEBUG", "Added mapping: %s -> %s (scale: %s, filter: %s)",
|
||||||
|
output_name, image_path, scale_mode_to_string(scale_mode),
|
||||||
|
filter_quality_to_string(filter_quality));
|
||||||
chroma_log("TRACE", "Output mapping %d: '%s' -> '%s' (path length: %zu)",
|
chroma_log("TRACE", "Output mapping %d: '%s' -> '%s' (path length: %zu)",
|
||||||
config->mapping_count, output_name, image_path, path_len);
|
config->mapping_count, output_name, image_path, path_len);
|
||||||
return CHROMA_OK;
|
return CHROMA_OK;
|
||||||
|
|
@ -106,6 +180,10 @@ static void init_default_config(chroma_config_t *config) {
|
||||||
config->daemon_mode = false;
|
config->daemon_mode = false;
|
||||||
config->mapping_count = 0;
|
config->mapping_count = 0;
|
||||||
|
|
||||||
|
// Set default scaling and filtering
|
||||||
|
config->default_scale_mode = CHROMA_SCALE_FILL;
|
||||||
|
config->default_filter_quality = CHROMA_FILTER_LINEAR;
|
||||||
|
|
||||||
// Set default image path (can be overridden)
|
// Set default image path (can be overridden)
|
||||||
const char *home = getenv("HOME");
|
const char *home = getenv("HOME");
|
||||||
if (home) {
|
if (home) {
|
||||||
|
|
@ -181,6 +259,23 @@ static int parse_config_line(chroma_config_t *config, char *line,
|
||||||
chroma_log("TRACE",
|
chroma_log("TRACE",
|
||||||
"Daemon mode configuration: key='%s', value='%s', parsed=%s",
|
"Daemon mode configuration: key='%s', value='%s', parsed=%s",
|
||||||
key, value, config->daemon_mode ? "true" : "false");
|
key, value, config->daemon_mode ? "true" : "false");
|
||||||
|
} else if (strcasecmp(key, "scale_mode") == 0 ||
|
||||||
|
strcasecmp(key, "default_scale_mode") == 0) {
|
||||||
|
config->default_scale_mode = parse_scale_mode(value);
|
||||||
|
chroma_log("DEBUG", "Set default scale mode: %s",
|
||||||
|
scale_mode_to_string(config->default_scale_mode));
|
||||||
|
chroma_log("TRACE",
|
||||||
|
"Scale mode configuration: key='%s', value='%s', parsed=%s", key,
|
||||||
|
value, scale_mode_to_string(config->default_scale_mode));
|
||||||
|
} else if (strcasecmp(key, "filter_quality") == 0 ||
|
||||||
|
strcasecmp(key, "default_filter_quality") == 0) {
|
||||||
|
config->default_filter_quality = parse_filter_quality(value);
|
||||||
|
chroma_log("DEBUG", "Set default filter quality: %s",
|
||||||
|
filter_quality_to_string(config->default_filter_quality));
|
||||||
|
chroma_log("TRACE",
|
||||||
|
"Filter quality configuration: key='%s', value='%s', parsed=%s",
|
||||||
|
key, value,
|
||||||
|
filter_quality_to_string(config->default_filter_quality));
|
||||||
} else if (strncasecmp(key, "output.", 7) == 0) {
|
} else if (strncasecmp(key, "output.", 7) == 0) {
|
||||||
// Output-specific mapping: e.g., output.DP-1=/path/to/image.jpg
|
// Output-specific mapping: e.g., output.DP-1=/path/to/image.jpg
|
||||||
const char *output_name = key + 7;
|
const char *output_name = key + 7;
|
||||||
|
|
@ -190,6 +285,46 @@ static int parse_config_line(chroma_config_t *config, char *line,
|
||||||
return CHROMA_OK;
|
return CHROMA_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for extended output configuration with properties
|
||||||
|
// Format: output.DP-1.scale = fill
|
||||||
|
// Format: output.DP-1.filter = linear
|
||||||
|
char *dot = strchr(output_name, '.');
|
||||||
|
if (dot) {
|
||||||
|
// This is an output property (scale or filter)
|
||||||
|
*dot = '\0';
|
||||||
|
const char *property = dot + 1;
|
||||||
|
|
||||||
|
// Find existing mapping for this output
|
||||||
|
chroma_config_mapping_t *mapping = NULL;
|
||||||
|
for (int i = 0; i < config->mapping_count; i++) {
|
||||||
|
if (strcmp(config->mappings[i].output_name, output_name) == 0) {
|
||||||
|
mapping = &config->mappings[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mapping) {
|
||||||
|
chroma_log("WARN", "Output %s not found for property %s (line %d)",
|
||||||
|
output_name, property, line_number);
|
||||||
|
return CHROMA_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(property, "scale") == 0) {
|
||||||
|
mapping->scale_mode = parse_scale_mode(value);
|
||||||
|
chroma_log("DEBUG", "Set scale mode for output %s: %s", output_name,
|
||||||
|
scale_mode_to_string(mapping->scale_mode));
|
||||||
|
} else if (strcasecmp(property, "filter") == 0) {
|
||||||
|
mapping->filter_quality = parse_filter_quality(value);
|
||||||
|
chroma_log("DEBUG", "Set filter quality for output %s: %s", output_name,
|
||||||
|
filter_quality_to_string(mapping->filter_quality));
|
||||||
|
} else {
|
||||||
|
chroma_log("WARN", "Unknown output property: %s (line %d)", property,
|
||||||
|
line_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CHROMA_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Expand path before validation and storage
|
// Expand path before validation and storage
|
||||||
char *expanded_path = chroma_expand_path(value);
|
char *expanded_path = chroma_expand_path(value);
|
||||||
const char *path_to_validate = expanded_path ? expanded_path : value;
|
const char *path_to_validate = expanded_path ? expanded_path : value;
|
||||||
|
|
@ -204,8 +339,9 @@ static int parse_config_line(chroma_config_t *config, char *line,
|
||||||
return CHROMA_OK;
|
return CHROMA_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_output_mapping(config, output_name, path_to_validate) !=
|
if (add_output_mapping(config, output_name, path_to_validate,
|
||||||
CHROMA_OK) {
|
config->default_scale_mode,
|
||||||
|
config->default_filter_quality) != CHROMA_OK) {
|
||||||
chroma_log("ERROR", "Failed to add output mapping: %s -> %s", output_name,
|
chroma_log("ERROR", "Failed to add output mapping: %s -> %s", output_name,
|
||||||
path_to_validate);
|
path_to_validate);
|
||||||
if (expanded_path) {
|
if (expanded_path) {
|
||||||
|
|
@ -348,6 +484,37 @@ const char *chroma_config_get_image_for_output(chroma_config_t *config,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get configuration mapping for output, including scale mode and filter
|
||||||
|
// quality
|
||||||
|
int chroma_config_get_mapping_for_output(
|
||||||
|
chroma_config_t *config, const char *output_name,
|
||||||
|
chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality) {
|
||||||
|
if (!config || !output_name || !scale_mode || !filter_quality) {
|
||||||
|
return CHROMA_ERROR_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for specific output mapping
|
||||||
|
for (int i = 0; i < config->mapping_count; i++) {
|
||||||
|
if (strcmp(config->mappings[i].output_name, output_name) == 0) {
|
||||||
|
*scale_mode = config->mappings[i].scale_mode;
|
||||||
|
*filter_quality = config->mappings[i].filter_quality;
|
||||||
|
chroma_log("DEBUG",
|
||||||
|
"Found specific mapping for output %s: scale=%s, filter=%s",
|
||||||
|
output_name, scale_mode_to_string(*scale_mode),
|
||||||
|
filter_quality_to_string(*filter_quality));
|
||||||
|
return CHROMA_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return defaults if no specific mapping found
|
||||||
|
*scale_mode = config->default_scale_mode;
|
||||||
|
*filter_quality = config->default_filter_quality;
|
||||||
|
chroma_log("DEBUG", "Using defaults for output %s: scale=%s, filter=%s",
|
||||||
|
output_name, scale_mode_to_string(*scale_mode),
|
||||||
|
filter_quality_to_string(*filter_quality));
|
||||||
|
return CHROMA_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a sample configuration file
|
// Create a sample configuration file
|
||||||
int chroma_config_create_sample(const char *config_file) {
|
int chroma_config_create_sample(const char *config_file) {
|
||||||
if (!config_file) {
|
if (!config_file) {
|
||||||
|
|
@ -391,14 +558,24 @@ void chroma_config_print(const chroma_config_t *config) {
|
||||||
chroma_log("INFO", "=== Configuration ===");
|
chroma_log("INFO", "=== Configuration ===");
|
||||||
chroma_log("INFO", "Default image: %s", config->default_image);
|
chroma_log("INFO", "Default image: %s", config->default_image);
|
||||||
chroma_log("INFO", "Daemon mode: %s", config->daemon_mode ? "true" : "false");
|
chroma_log("INFO", "Daemon mode: %s", config->daemon_mode ? "true" : "false");
|
||||||
|
chroma_log("INFO", "Default scale mode: %s",
|
||||||
|
scale_mode_to_string(config->default_scale_mode));
|
||||||
|
chroma_log("INFO", "Default filter quality: %s",
|
||||||
|
filter_quality_to_string(config->default_filter_quality));
|
||||||
chroma_log("INFO", "Output mappings: %d", config->mapping_count);
|
chroma_log("INFO", "Output mappings: %d", config->mapping_count);
|
||||||
|
|
||||||
for (int i = 0; i < config->mapping_count; i++) {
|
for (int i = 0; i < config->mapping_count; i++) {
|
||||||
chroma_log("INFO", " %s -> %s", config->mappings[i].output_name,
|
chroma_log("INFO", " %s -> %s (scale: %s, filter: %s)",
|
||||||
config->mappings[i].image_path);
|
|
||||||
chroma_log(
|
|
||||||
"TRACE", " Mapping %d: output='%s', image='%s', path_exists=%s", i,
|
|
||||||
config->mappings[i].output_name, config->mappings[i].image_path,
|
config->mappings[i].output_name, config->mappings[i].image_path,
|
||||||
|
scale_mode_to_string(config->mappings[i].scale_mode),
|
||||||
|
filter_quality_to_string(config->mappings[i].filter_quality));
|
||||||
|
chroma_log(
|
||||||
|
"TRACE",
|
||||||
|
" Mapping %d: output='%s', image='%s', scale='%s', filter='%s', "
|
||||||
|
"path_exists=%s",
|
||||||
|
i, config->mappings[i].output_name, config->mappings[i].image_path,
|
||||||
|
scale_mode_to_string(config->mappings[i].scale_mode),
|
||||||
|
filter_quality_to_string(config->mappings[i].filter_quality),
|
||||||
chroma_path_exists(config->mappings[i].image_path) ? "yes" : "no");
|
chroma_path_exists(config->mappings[i].image_path) ? "yes" : "no");
|
||||||
}
|
}
|
||||||
chroma_log("INFO", "====================");
|
chroma_log("INFO", "====================");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue