From 1b81def621036729cb4302f1f63c2ba3d44fe091 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Sun, 6 Jul 2025 18:50:11 +0200 Subject: [PATCH] part 2 for some reason --- .vscode/.server-controller-port.log | 2 +- CMakeLists.txt | 7 +- src/rds95.c | 107 +++++++++++++++++----------- 3 files changed, 70 insertions(+), 46 deletions(-) diff --git a/.vscode/.server-controller-port.log b/.vscode/.server-controller-port.log index 46f44c9..6487a5a 100644 --- a/.vscode/.server-controller-port.log +++ b/.vscode/.server-controller-port.log @@ -1,5 +1,5 @@ { "port": 13452, - "time": 1745844256741, + "time": 1751819046475, "version": "0.0.3" } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a66b49..ccc93c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,16 @@ cmake_minimum_required(VERSION 3.10) -project(rds95 VERSION 1.4) +project(rds95 VERSION 1.5) add_compile_options(-Wall -Werror -Wextra -pedantic -O2 -std=c18 -march=native -DVERSION=\"${PROJECT_VERSION}\") +file(GLOB INIH_FILES "inih/*.c") +add_library(inih OBJECT ${INIH_FILES}) + file(GLOB SOURCES src/*.c) add_executable(rds95 ${SOURCES}) -target_link_libraries(rds95 PRIVATE m pthread pulse pulse-simple) +target_link_libraries(rds95 PRIVATE m pthread pulse pulse-simple inih) install(TARGETS rds95 DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/src/rds95.c b/src/rds95.c index 6ca2a7b..44f7a88 100644 --- a/src/rds95.c +++ b/src/rds95.c @@ -4,6 +4,7 @@ #include #include #include +#include "../inih/ini.h" #include "rds.h" #include "modulator.h" @@ -12,6 +13,7 @@ #include "ascii_cmd.h" #define RDS_DEVICE "RDS" +#define DEFAULT_CONFIG_PATH "/etc/rds95.conf" #define DEFAULT_STREAMS 2 #define MAX_STREAMS 4 @@ -35,10 +37,6 @@ static void *control_pipe_worker(void* modulator) { pthread_exit(NULL); } -static inline void show_version() { - printf("rds95 (a RDS encoder by radio95) version %s\n", VERSION); -} - static inline void show_help(char *name) { printf( "\n" @@ -55,12 +53,41 @@ static inline void show_help(char *name) { ); } -int main(int argc, char **argv) { - show_version(); +typedef struct +{ + char control_pipe[51]; + char rds_device_name[32]; + uint8_t num_streams; +} RDS95_Config; - char control_pipe[51] = "\0"; - char rds_device_name[32] = RDS_DEVICE; - uint8_t num_streams = DEFAULT_STREAMS; +static int config_handler(void* user, const char* section, const char* name, const char* value) { + RDS95_Config* config = (RDS95_Config*)user; + + #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 + if(MATCH("rds95", "control_pipe")) { + strncpy(config->control_pipe, value, 49); + config->control_pipe[50] = '\0'; + } else if(MATCH("devices", "rds95")) { + strncpy(config->rds_device_name, value, 30); + config->rds_device_name[31] = '\0'; + } else if(MATCH("rds95", "streams")) { + config->num_streams = atoi(value); + if(config->num_streams > MAX_STREAMS || config->num_streams == 0) return 1; + } else { + return 1; + } + return 0; +} + +int main(int argc, char **argv) { + printf("rds95 (a RDS encoder by radio95) version %s\n", VERSION); + + char config_path[64] = DEFAULT_CONFIG_PATH; + RDS95_Config config = { + .control_pipe = "\0", + .rds_device_name = RDS_DEVICE, + .num_streams = DEFAULT_STREAMS + }; pa_simple *rds_device = NULL; pa_sample_spec format; @@ -69,13 +96,11 @@ int main(int argc, char **argv) { pthread_attr_t attr; pthread_t control_pipe_thread; - const char *short_opt = "C:d:s:h"; + const char *short_opt = "c:h"; struct option long_opt[] = { - {"ctl", required_argument, NULL, 'C'}, - {"device", required_argument, NULL, 'd'}, - {"streams", required_argument, NULL, 's'}, + {"config", required_argument, NULL, 'c'}, {"help", no_argument, NULL, 'h'}, { 0, 0, 0, 0 } }; @@ -83,19 +108,9 @@ int main(int argc, char **argv) { int opt; while((opt = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) { switch (opt) { - case 'C': - memcpy(control_pipe, optarg, 50); - break; - case 'd': - memcpy(rds_device_name, optarg, 31); - rds_device_name[31] = '\0'; - break; - case 's': - num_streams = (uint8_t)atoi(optarg); - if (num_streams < 1 || num_streams > MAX_STREAMS) { - fprintf(stderr, "Error: Number of streams must be between 1 and %d\n", MAX_STREAMS); - return 1; - } + case 'c': + memcpy(config_path, optarg, 62); + config_path[63] = '\0'; break; case 'h': show_help(argv[0]); @@ -106,7 +121,13 @@ int main(int argc, char **argv) { } } - printf("Using %d RDS stream(s)\n", num_streams); + int res = ini_parse(config_path, config_handler, &config); + if(res != 0) { + fprintf(stderr, "Error: Could not read ini config, error code as return code.\n"); + return res; + } + + printf("Using %d RDS stream(s)\n", config.num_streams); pthread_attr_init(&attr); @@ -114,18 +135,18 @@ int main(int argc, char **argv) { signal(SIGTERM, stop); format.format = PA_SAMPLE_FLOAT32NE; - format.channels = num_streams; // Use dynamic stream count + format.channels = config.num_streams; // Use dynamic stream count format.rate = RDS_SAMPLE_RATE; buffer.prebuf = 0; - buffer.tlength = NUM_MPX_FRAMES * num_streams; - buffer.maxlength = NUM_MPX_FRAMES * num_streams; + buffer.tlength = NUM_MPX_FRAMES * config.num_streams; + buffer.maxlength = NUM_MPX_FRAMES * config.num_streams; rds_device = pa_simple_new( NULL, "rds95", PA_STREAM_PLAYBACK, - rds_device_name, + config.rds_device_name, "RDS Generator", &format, NULL, @@ -140,38 +161,38 @@ int main(int argc, char **argv) { RDSEncoder rdsEncoder; RDSModulator rdsModulator; init_rds_encoder(&rdsEncoder); - init_rds_modulator(&rdsModulator, &rdsEncoder, num_streams); + init_rds_modulator(&rdsModulator, &rdsEncoder, config.num_streams); - if (control_pipe[0]) { - if (open_control_pipe(control_pipe) == 0) { - fprintf(stderr, "Reading control commands on %s.\n", control_pipe); + if (config.control_pipe[0]) { + if (open_control_pipe(config.control_pipe) == 0) { + fprintf(stderr, "Reading control commands on %s.\n", config.control_pipe); int r = pthread_create(&control_pipe_thread, &attr, control_pipe_worker, (void*)&rdsModulator); if (r < 0) { fprintf(stderr, "Could not create control pipe thread.\n"); - control_pipe[0] = 0; + config.control_pipe[0] = 0; goto exit; } else fprintf(stderr, "Created control pipe thread.\n"); } else { - fprintf(stderr, "Failed to open control pipe: %s.\n", control_pipe); - control_pipe[0] = 0; + fprintf(stderr, "Failed to open control pipe: %s.\n", config.control_pipe); + config.control_pipe[0] = 0; } } int pulse_error; // Dynamically allocate buffer based on stream count - float *rds_buffer = (float*)malloc(NUM_MPX_FRAMES * num_streams * sizeof(float)); + float *rds_buffer = (float*)malloc(NUM_MPX_FRAMES * config.num_streams * sizeof(float)); if (rds_buffer == NULL) { fprintf(stderr, "Error: Could not allocate memory for RDS buffer\n"); goto exit; } while(!stop_rds) { - for (uint16_t i = 0; i < NUM_MPX_FRAMES * num_streams; i++) { - rds_buffer[i] = get_rds_sample(&rdsModulator, i % num_streams); + for (uint16_t i = 0; i < NUM_MPX_FRAMES * config.num_streams; i++) { + rds_buffer[i] = get_rds_sample(&rdsModulator, i % config.num_streams); } - if (pa_simple_write(rds_device, rds_buffer, NUM_MPX_FRAMES * num_streams * sizeof(float), &pulse_error) != 0) { + if (pa_simple_write(rds_device, rds_buffer, NUM_MPX_FRAMES * config.num_streams * sizeof(float), &pulse_error) != 0) { fprintf(stderr, "Error: could not play audio. (%s : %d)\n", pa_strerror(pulse_error), pulse_error); break; } @@ -180,7 +201,7 @@ int main(int argc, char **argv) { free(rds_buffer); exit: - if (control_pipe[0]) { + if (config.control_pipe[0]) { fprintf(stderr, "Waiting for pipe thread to shut down.\n"); pthread_join(control_pipe_thread, NULL); }