mirror of
https://github.com/radio95-rnt/fm95.git
synced 2026-07-29 15:59:14 +02:00
"proper" ipc protocol
This commit is contained in:
+3
-1
@@ -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
@@ -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);
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user