"proper" ipc protocol

This commit is contained in:
2026-05-03 18:33:19 +02:00
parent 44098f9b18
commit 39738773ed
5 changed files with 94 additions and 37 deletions
+3 -1
View File
@@ -31,7 +31,7 @@ void init_bs412(BS412Compressor* comp, uint32_t mpx_deviation, float target_powe
#endif #endif
} }
float bs412_compress(BS412Compressor* comp, float audio, float sample_mpx) { float bs412_compress(BS412Compressor* comp, float audio, float sample_mpx, float* mpx_power) {
float combined = audio + sample_mpx; float combined = audio + sample_mpx;
float output_sample = (audio * comp->gain) + sample_mpx; float output_sample = (audio * comp->gain) + sample_mpx;
@@ -66,6 +66,8 @@ float bs412_compress(BS412Compressor* comp, float audio, float sample_mpx) {
comp->sample_counter++; comp->sample_counter++;
if(mpx_power != NULL) *mpx_power = deviation_to_dbr(avg_power);
if(comp->can_compress) return output_sample; if(comp->can_compress) return output_sample;
return combined; return combined;
} }
+1 -1
View File
@@ -32,4 +32,4 @@ typedef struct
float deviation_to_dbr(float deviation); float deviation_to_dbr(float deviation);
void init_bs412(BS412Compressor *comp, uint32_t mpx_deviation, float target_power, float attack, float release, float max_gain, uint32_t sample_rate); void init_bs412(BS412Compressor *comp, uint32_t mpx_deviation, float target_power, float attack, float release, float max_gain, uint32_t sample_rate);
float bs412_compress(BS412Compressor *comp, float audio, float sample_mpx); float bs412_compress(BS412Compressor *comp, float audio, float sample_mpx, float* mpx_power);
+14 -10
View File
@@ -43,14 +43,16 @@ static void *listener_thread(void *arg) {
printf("[ipc] new client fd=%d\n", client_fd); printf("[ipc] new client fd=%d\n", client_fd);
int *fd_ptr = malloc(sizeof(int)); ipc_client_arg_t *carg = malloc(sizeof(ipc_client_arg_t));
if (!fd_ptr) { close(client_fd); continue; } if (!carg) { close(client_fd); continue; }
*fd_ptr = client_fd; carg->client_fd = client_fd;
carg->user_data = ctx->user_data;
pthread_t tid; pthread_t tid;
if (pthread_create(&tid, NULL, ctx->handler, fd_ptr) != 0) { if (pthread_create(&tid, NULL,
(void *(*)(void *))ctx->handler, carg) != 0) {
perror("ipc: pthread_create"); perror("ipc: pthread_create");
free(fd_ptr); free(carg);
close(client_fd); close(client_fd);
continue; continue;
} }
@@ -61,10 +63,13 @@ static void *listener_thread(void *arg) {
return NULL; return NULL;
} }
int create_ipc(ipc_ctx_t *ctx, ipc_client_fn handler, const char* socket_path) { int create_ipc(ipc_ctx_t *ctx, ipc_client_fn handler,
ctx->handler = handler; const char *socket_path, void *user_data)
ctx->running = 1; {
ctx->server_fd = make_server_socket(socket_path); ctx->handler = handler;
ctx->user_data = user_data;
ctx->running = 1;
ctx->server_fd = make_server_socket(socket_path);
ctx->socket_path = strdup(socket_path); ctx->socket_path = strdup(socket_path);
if (ctx->server_fd < 0) return -1; if (ctx->server_fd < 0) return -1;
@@ -76,7 +81,6 @@ int create_ipc(ipc_ctx_t *ctx, ipc_client_fn handler, const char* socket_path) {
return -1; return -1;
} }
/* store tid so destroy_ipc can join it */
ctx->_tid = tid; ctx->_tid = tid;
printf("[ipc] listening on %s\n", socket_path); printf("[ipc] listening on %s\n", socket_path);
+11 -4
View File
@@ -6,17 +6,24 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#define IPC_SOCKET_PATH "/tmp/ipc_demo.sock"
#define IPC_BACKLOG 1 #define IPC_BACKLOG 1
typedef void *(*ipc_client_fn)(void *client_fd_ptr); typedef struct {
int client_fd;
void *user_data;
} ipc_client_arg_t;
typedef void *(*ipc_client_fn)(ipc_client_arg_t *arg);
typedef struct { typedef struct {
int server_fd; int server_fd;
volatile int running; volatile int running;
ipc_client_fn handler; ipc_client_fn handler;
void *user_data;
pthread_t _tid; /* internal — do not touch */ pthread_t _tid; /* internal — do not touch */
char* socket_path; char *socket_path;
} ipc_ctx_t; } ipc_ctx_t;
int create_ipc(ipc_ctx_t *ctx, ipc_client_fn handler, const char* socket_path);
int create_ipc(ipc_ctx_t *ctx, ipc_client_fn handler,
const char *socket_path, void *user_data);
void destroy_ipc(ipc_ctx_t *ctx); void destroy_ipc(ipc_ctx_t *ctx);
+65 -21
View File
@@ -93,6 +93,10 @@ typedef struct {
FM95_DeviceNames* devices; FM95_DeviceNames* devices;
} FM95_SetupContext; } FM95_SetupContext;
typedef struct {
float mpx_power;
} FM95_RunResult;
bool compare_dvs(const FM95_DeviceNames *a, const FM95_DeviceNames *b) { bool compare_dvs(const FM95_DeviceNames *a, const FM95_DeviceNames *b) {
return strcmp(a->input, b->input) == 0 && strcmp(a->output, b->output) == 0 && strcmp(a->mpx, b->mpx) == 0 && strcmp(a->rds, b->rds) == 0; return strcmp(a->input, b->input) == 0 && strcmp(a->output, b->output) == 0 && strcmp(a->mpx, b->mpx) == 0 && strcmp(a->rds, b->rds) == 0;
} }
@@ -143,8 +147,9 @@ void cleanup_audio_runtime(FM95_Runtime *rt, const FM95_Options options) {
free_PulseDevice(&rt->output_device); free_PulseDevice(&rt->output_device);
} }
int run_fm95(const FM95_Config config, FM95_Runtime* runtime) { int run_fm95(const FM95_Config config, FM95_Runtime* runtime, FM95_RunResult* result) {
float output[BUFFER_SIZE]; float output[BUFFER_SIZE];
FM95_RunResult temp_result = {};
int pulse_error; int pulse_error;
@@ -172,9 +177,9 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) {
bool mpx_on = config.options.mpx_on; bool mpx_on = config.options.mpx_on;
bool rds_on = config.options.rds_on; bool rds_on = config.options.rds_on;
float softclip_norm = config.volumes.makeup / tanhf(config.volumes.drive);
while (to_run) { while (to_run) {
float softclip_norm = config.volumes.makeup / tanhf(config.volumes.drive);
if((pulse_error = read_PulseInputDevice(&runtime->input_device, audio_stereo_input, sizeof(audio_stereo_input)))) { // get output from the function and assign it into pulse_error, this comment to avoid confusion if((pulse_error = read_PulseInputDevice(&runtime->input_device, audio_stereo_input, sizeof(audio_stereo_input)))) { // get output from the function and assign it into pulse_error, this comment to avoid confusion
fprintf(stderr, "Error reading from input device: %s\n", pa_strerror(pulse_error)); fprintf(stderr, "Error reading from input device: %s\n", pa_strerror(pulse_error));
to_run = 0; to_run = 0;
@@ -237,11 +242,12 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) {
} }
} }
mpx = bs412_compress(&runtime->bs412, audio, mpx+mpx_in[i]); mpx = bs412_compress(&runtime->bs412, audio, mpx+mpx_in[i], &temp_result.mpx_power);
output[i] = tanhf(mpx)*config.master_volume; // Ensure peak deviation of 75 khz (or the set deviation), assuming we're calibrated correctly output[i] = tanhf(mpx)*config.master_volume; // Ensure peak deviation of 75 khz (or the set deviation), assuming we're calibrated correctly
advance_oscillator(&runtime->osc); advance_oscillator(&runtime->osc);
} }
memcpy(result, &temp_result, sizeof(FM95_RunResult));
if((pulse_error = write_PulseOutputDevice(&runtime->output_device, output, sizeof(output)))) { if((pulse_error = write_PulseOutputDevice(&runtime->output_device, output, sizeof(output)))) {
fprintf(stderr, "Error writing to output device: %s\n", pa_strerror(pulse_error)); fprintf(stderr, "Error writing to output device: %s\n", pa_strerror(pulse_error));
@@ -458,23 +464,56 @@ void init_runtime(FM95_Runtime* runtime, const FM95_Config config) {
} }
#define BUF_SIZE 256 #define BUF_SIZE 256
#define PREFIX "ECHO: "
#define PREFIX_LEN 6
static void *handle_client(void *arg) { typedef struct {
int fd = *(int *)arg; FM95_Runtime* runtime;
FM95_Config* config;
FM95_RunResult* run_result;
} FM95_Data;
static void *handle_client(ipc_client_arg_t *arg) {
int fd = arg->client_fd;
FM95_Data* data = arg->user_data;
free(arg); free(arg);
char buf[BUF_SIZE]; char buf[BUF_SIZE];
char reply = 0;
ssize_t n; ssize_t n;
while ((n = recv(fd, buf, sizeof(buf) - 1, 0)) > 0) { while ((n = recv(fd, buf, sizeof(buf) - 1, 0)) > 0) {
reply = 0;
buf[n] = '\0'; buf[n] = '\0';
printf("[client fd=%d] %s\n", fd, buf); switch (buf[0]) {
case 1:
// Reload
to_run = 0;
to_reload = 1;
break;
case 2:
// Quit
to_run = 0;
to_reload = 0;
break;
case 100:
// Toggle stereo
data->config->stereo ^= 1;
break;
case 101:
// Set makeup
float val;
memcpy(&val, buf + 1, sizeof(float));
data->config->volumes.makeup = val;
break;
case 0xff:
// Fetch data
send(fd, data->run_result, sizeof(FM95_RunResult), 0);
break;
default:
reply = 1; // Unknown command
break;
}
char reply[BUF_SIZE + PREFIX_LEN]; send(fd, &reply, 1, 0);
snprintf(reply, sizeof(reply), PREFIX "%s", buf);
send(fd, reply, strlen(reply), 0);
} }
printf("[client fd=%d] disconnected\n", fd); printf("[client fd=%d] disconnected\n", fd);
@@ -485,14 +524,6 @@ static void *handle_client(void *arg) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
printf("fm95 (an FM Processor by radio95) version 2.5\n"); printf("fm95 (an FM Processor by radio95) version 2.5\n");
ipc_ctx_t ctx;
ipc_ctx_t *pctx = &ctx;
if(create_ipc(pctx, handle_client, "/etc/fm95/ctl.socket") < 0) {
printf("Could not create IPC.\n");
pctx = NULL;
}
FM95_Config config = { FM95_Config config = {
.volumes = { .volumes = {
.pilot = 0.09f, .pilot = 0.09f,
@@ -580,9 +611,22 @@ int main(int argc, char **argv) {
init_runtime(&runtime, config); init_runtime(&runtime, config);
FM95_RunResult runres = {};
FM95_Data fmdata = {
.config = &config,
.runtime = &runtime,
.run_result = &runres
};
ipc_ctx_t ctx;
ipc_ctx_t *pctx = &ctx;
if(create_ipc(pctx, handle_client, "/etc/fm95/ctl.socket", &fmdata) < 0) {
printf("Could not create IPC.\n");
pctx = NULL;
}
int ret; int ret;
while(true) { while(true) {
ret = run_fm95(config, &runtime); ret = run_fm95(config, &runtime, &runres);
if(to_reload) { if(to_reload) {
to_reload = 0; to_reload = 0;
printf("Reloading...\n"); printf("Reloading...\n");