Files
vbx/src/audio/config.c
T

244 lines
8.9 KiB
C

#include "audio/types.h"
#include "common/utils.h"
#include <errno.h>
#include <json-c/json.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
SoundPack g_sound_pack = {0};
SoundPack g_mouse_sound_pack = {0};
float g_volume = 1.0f;
float g_mouse_volume = 1.0f;
int g_verbose = 0;
int g_mute = 0;
int g_keyboard_mute = 0;
int g_mouse_mute = 0;
static void get_full_path(char *buffer, size_t buffer_size,
const char *base_dir, const char *filename) {
if (!filename || !base_dir) {
buffer[0] = '\0';
return;
}
if (filename[0] == '/') {
safe_strncpy(buffer, filename, buffer_size);
} else {
if (!safe_snprintf(buffer, buffer_size, "%s/%s", base_dir, filename)) {
buffer[0] = '\0';
}
}
}
int load_sound_config(const char *config_path) {
FILE *file = fopen(config_path, "r");
if (!file) {
safe_fprintf(stderr, "Error: Cannot open config file: %s\n", config_path);
perror("fopen");
return -1;
}
char config_path_copy[1024];
safe_strncpy(config_path_copy, config_path, sizeof(config_path_copy));
char *config_dir = dirname(config_path_copy);
fseek(file, 0, SEEK_END);
long size = ftell(file);
if (size < 0) {
fclose(file);
safe_fprintf(stderr, "Error: ftell failed while reading %s\n", config_path);
return -1;
}
errno = 0;
rewind(file);
if (errno != 0) {
fclose(file);
safe_fprintf(stderr, "Error: rewind failed while reading %s\n", config_path);
return -1;
}
char *json_string = malloc((size_t)size + 1);
if (!json_string) {
fclose(file);
safe_fprintf(stderr, "Error: Memory allocation failed\n");
return -1;
}
fread(json_string, 1, size, file);
json_string[size] = '\0';
fclose(file);
json_object *root = json_tokener_parse(json_string);
free(json_string);
if (!root) {
safe_fprintf(stderr, "Error: Invalid JSON in config file\n");
return -1;
}
const char *key_type = "single";
json_object *obj;
if (json_object_object_get_ex(root, "key_define_type", &obj))
key_type = json_object_get_string(obj);
g_sound_pack.is_multi = strcmp(key_type, "multi") == 0;
if (g_verbose) {
printf("Config loaded: Using %s mode\n",
g_sound_pack.is_multi ? "multi" : "single");
}
if (g_sound_pack.is_multi) {
g_sound_pack.num_generic_press_files = 0;
if (json_object_object_get_ex(root, "sound", &obj)) {
const char *pattern = json_object_get_string(obj);
if (g_verbose)
printf("Sound pattern: %s\n", pattern);
if (strstr(pattern, "%d") || strstr(pattern, "{")) {
for (int i = 0; i <= 4; i++) {
char temp_filename[256];
if (strstr(pattern, "{")) {
char temp_pattern[256];
safe_strncpy(temp_pattern, pattern, sizeof(temp_pattern));
char *brace_start = strstr(temp_pattern, "{");
char *brace_end = strstr(temp_pattern, "}");
if (brace_start && brace_end) {
*brace_start = '%';
*(brace_start + 1) = 'd';
safe_memmove(brace_start + 2, brace_end + 1,
strlen(brace_end + 1) + 1);
}
safe_snprintf_wrapper(temp_filename, sizeof(temp_filename), temp_pattern, i);
} else {
safe_snprintf_wrapper(temp_filename, sizeof(temp_filename), pattern, i);
}
get_full_path(g_sound_pack.generic_press_files[i],
sizeof(g_sound_pack.generic_press_files[i]), config_dir,
temp_filename);
if (access(g_sound_pack.generic_press_files[i], R_OK) == 0) {
g_sound_pack.num_generic_press_files = i + 1;
} else {
if (g_verbose)
printf("Generic sound file not found: %s\n",
g_sound_pack.generic_press_files[i]);
break;
}
}
} else {
get_full_path(g_sound_pack.generic_press_files[0],
sizeof(g_sound_pack.generic_press_files[0]), config_dir,
pattern);
if (access(g_sound_pack.generic_press_files[0], R_OK) == 0) {
g_sound_pack.num_generic_press_files = 1;
if (g_verbose)
printf("Found single generic sound file: %s\n",
g_sound_pack.generic_press_files[0]);
}
}
if (g_verbose)
printf("Total generic press sound files: %d\n",
g_sound_pack.num_generic_press_files);
}
if (json_object_object_get_ex(root, "soundup", &obj)) {
char temp_release_file[256];
safe_strncpy(temp_release_file, json_object_get_string(obj),
sizeof(temp_release_file));
get_full_path(g_sound_pack.release_file,
sizeof(g_sound_pack.release_file), config_dir,
temp_release_file);
if (g_verbose)
printf("Release sound file: %s\n", g_sound_pack.release_file);
}
if (json_object_object_get_ex(root, "defines", &obj)) {
json_object_object_foreach(obj, key, val) {
int key_code;
int is_release = 0;
if (strcmp(key, "MouseLeft") == 0) {
key_code = 272;
} else if (strcmp(key, "MouseRight") == 0) {
key_code = 273;
} else if (strcmp(key, "MouseMiddle") == 0) {
key_code = 274;
} else {
char *dash = strstr(key, "-up");
if (dash) {
char key_copy[16];
safe_strncpy(key_copy, key, dash - key + 1);
key_copy[dash - key] = '\0';
key_code = atoi(key_copy);
is_release = 1;
} else {
key_code = atoi(key);
}
}
if (key_code >= 0 && key_code < 512) {
const char *filename_relative = json_object_get_string(val);
char full_filename[1024];
get_full_path(full_filename, sizeof(full_filename), config_dir,
filename_relative);
if (is_release) {
if (g_sound_pack.multi_key_mappings[key_code].release)
free(g_sound_pack.multi_key_mappings[key_code].release);
g_sound_pack.multi_key_mappings[key_code].release =
xstrdup(full_filename);
} else {
if (g_sound_pack.multi_key_mappings[key_code].press)
free(g_sound_pack.multi_key_mappings[key_code].press);
g_sound_pack.multi_key_mappings[key_code].press =
xstrdup(full_filename);
}
}
}
}
} else {
if (json_object_object_get_ex(root, "sound", &obj) ||
json_object_object_get_ex(root, "audio_file", &obj)) {
char temp_sound_file[256];
safe_strncpy(temp_sound_file, json_object_get_string(obj),
sizeof(temp_sound_file));
get_full_path(g_sound_pack.sound_file, sizeof(g_sound_pack.sound_file),
config_dir, temp_sound_file);
if (g_verbose)
printf("Single mode sound file: %s\n", g_sound_pack.sound_file);
}
json_object *defines_obj = NULL;
if (json_object_object_get_ex(root, "defines", &defines_obj) ||
json_object_object_get_ex(root, "definitions", &defines_obj)) {
json_object_object_foreach(defines_obj, key, val) {
int key_code;
if (strcmp(key, "MouseLeft") == 0) {
key_code = 272;
} else if (strcmp(key, "MouseRight") == 0) {
key_code = 273;
} else if (strcmp(key, "MouseMiddle") == 0) {
key_code = 274;
} else {
key_code = atoi(key);
}
if (key_code >= 0 && key_code < 512) {
if (json_object_is_type(val, json_type_array)) {
if (json_object_array_length(val) >= 2) {
g_sound_pack.key_mappings[key_code].start_ms =
json_object_get_int(json_object_array_get_idx(val, 0));
g_sound_pack.key_mappings[key_code].duration_ms =
json_object_get_int(json_object_array_get_idx(val, 1));
}
} else if (json_object_is_type(val, json_type_object)) {
json_object *timing_array;
if (json_object_object_get_ex(val, "timing", &timing_array) &&
json_object_is_type(timing_array, json_type_array) &&
json_object_array_length(timing_array) > 0) {
json_object *first_timing =
json_object_array_get_idx(timing_array, 0);
if (json_object_is_type(first_timing, json_type_array) &&
json_object_array_length(first_timing) >= 2) {
g_sound_pack.key_mappings[key_code].start_ms =
json_object_get_int(
json_object_array_get_idx(first_timing, 0));
g_sound_pack.key_mappings[key_code].duration_ms =
json_object_get_int(
json_object_array_get_idx(first_timing, 1));
}
}
}
}
}
}
}
json_object_put(root);
return 0;
}