From 9921cfd56ceca0cff91c9df018538a04f5776123 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Mon, 15 Dec 2014 13:05:09 +0000 Subject: Sync state with directory & argument parsing --- Makefile | 8 ++ trivmix.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ trivmix.h | 21 +++++ 3 files changed, 325 insertions(+) create mode 100644 Makefile create mode 100644 trivmix.c create mode 100644 trivmix.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..91f8d09 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +.PHONY: all test + +all: trivmix +test: all + valgrind ./trivmix testDir + +trivmix: trivmix.c + gcc -lm -Wall `pkg-config --cflags --libs jack` -o trivmix trivmix.c diff --git a/trivmix.c b/trivmix.c new file mode 100644 index 0000000..720c409 --- /dev/null +++ b/trivmix.c @@ -0,0 +1,296 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "trivmix.h" + +#define PIDFILE "pid" +#define INPUTFILE "input" +#define OUTPUTFILE "output" +#define NAMEFILE "name" +#define GAINFILE "gain" +#define DIRMODE S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH +#define FILEMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH +#define INOTIFYBUFLEN 1024 * (sizeof(struct inotify_event) + 16) +#define NOTIFYMASK IN_MODIFY | IN_CREATE | IN_DELETE | IN_ONESHOT + +mixState state = { .input = NULL, .output = NULL, .name = NULL, .dBGain = -90 }; +char *workdir; +char *inotifyBuffer; +bool changedDir = false; + +void initState() +{ + const char *defaultName = "mixer"; + + state.input = malloc(sizeof(char)); + *(state.input) = '\0'; + state.output = malloc(sizeof(char)); + *(state.output) = '\0'; + state.name = malloc(sizeof(char) * (1 + strlen(defaultName))); + strcpy(state.name, defaultName); +} + +void signalHandler(int signal) +{ + fprintf(stderr, "Received signal: %d\n", signal); + cleanExit(1); +} + +void setupSignalHandler() +{ + signal(SIGABRT, signalHandler); + signal(SIGFPE, SIG_IGN); + signal(SIGILL, SIG_IGN); + signal(SIGINT, signalHandler); + signal(SIGTERM, signalHandler); + signal(SIGSEGV, signalHandler); +} + +void parseArgs(int argc, char *argv[]) +{ + char opt; + + while ((opt = getopt(argc, argv, "g:n:i:o:")) != -1) + { + switch (opt) + { + case 'g': + sscanf(optarg, "%f", &(state.dBGain)); + break; + case 'n': + state.name = realloc(state.name, sizeof(char) * (1 + strlen(optarg))); + strcpy(state.name, optarg); + break; + case 'i': + state.input = realloc(state.input, sizeof(char) * (1 + strlen(optarg))); + strcpy(state.input, optarg); + break; + case 'o': + state.output = realloc(state.output, sizeof(char) * (1 + strlen(optarg))); + strcpy(state.output, optarg); + break; + } + } + + if (optind > argc - 1) + { + fprintf(stderr, "Usage: %s [-g {gain}] [-n {name}] [-i {input}] [-o {output}] {working directory}\n", argv[0]); + cleanExit(2); + } + + workdir = argv[optind++]; +} + +void setWorkdir() +{ + if (!(mkdir(workdir, DIRMODE) == 0 || errno == EEXIST) || chdir(workdir) == -1) + errMsg(1, &errno, "Failed to change to workdir", workdir); + changedDir = true; +} + +void writePid() +{ + FILE *pidFile; + + openSyncFile(&pidFile, PIDFILE, "wx", false); + if (fprintf(pidFile, "%d\n", getpid()) <= 1) + errMsg(1, &errno, "Failed to write to pidfile", PIDFILE); + fclose(pidFile); +} + +void syncState() +{ + readState(); + writeState(); +} + +void readState() +{ + FILE *pidFile; + FILE *inputFile; + FILE *outputFile; + FILE *nameFile; + FILE *gainFile; + int newInt; + char newString[64]; + float newFloat; + int ret; + + if (openSyncFile(&pidFile, PIDFILE, "r", true) == -1) + { + ret = fscanf(pidFile, "%d", &newInt); + fclose(pidFile); + + if (ret == 0 || ret == EOF || newInt != getpid()) + cleanExit(0); + } + else + cleanExit(0); + + if (openSyncFile(&inputFile, INPUTFILE, "r", true) == -1) + { + ret = fscanf(inputFile, "%63s", newString); + fclose(inputFile); + + if (ret != 0 && ret != EOF) + { + // TODO Try to set new jack input here + state.input = realloc(state.input, sizeof(char) * (1 + strlen(newString))); + strcpy(state.input, newString); + } + } + if (openSyncFile(&outputFile, OUTPUTFILE, "r", true) == -1) + { + ret = fscanf(outputFile, "%63s", newString); + fclose(outputFile); + + if (ret != 0 && ret != EOF) + { + // TODO Try to set new jack output here + state.output = realloc(state.output, sizeof(char) * (1 + strlen(newString))); + strcpy(state.output, newString); + } + } + + if (openSyncFile(&gainFile, GAINFILE, "r", true) == -1) + { + ret = fscanf(gainFile, "%f", &newFloat); + fclose(gainFile); + + if (ret != 0 && ret != EOF) + { + if (newFloat < -90) + newFloat = -90; + state.dBGain = newFloat; + } + } +} + +void writeState() +{ + FILE *pidFile; + FILE *inputFile; + FILE *outputFile; + FILE *nameFile; + FILE *gainFile; + int ret; + + openSyncFile(&pidFile, PIDFILE, "w", false); + ret = fprintf(pidFile, "%d\n", getpid()); + if (ret < 1) + errMsg(1, &errno, "Failed to write pidfile", PIDFILE); + fclose(pidFile); + + openSyncFile(&inputFile, INPUTFILE, "w", false); + ret = fprintf(inputFile, "%s\n", state.input); + if (ret < 1) + errMsg(1, &errno, "Failed to write file", INPUTFILE); + fclose(inputFile); + + openSyncFile(&outputFile, OUTPUTFILE, "w", false); + ret = fprintf(outputFile, "%s\n", state.output); + if (ret < 1) + errMsg(1, &errno, "Failed to write file", OUTPUTFILE); + fclose(outputFile); + + openSyncFile(&nameFile, NAMEFILE, "w", false); + ret = fprintf(nameFile, "%s\n", state.name); + if (ret < 1) + errMsg(1, &errno, "Failed to write file", NAMEFILE); + fclose(nameFile); + + openSyncFile(&gainFile, GAINFILE, "w", false); + ret = fprintf(gainFile, "%.2f\n", state.dBGain); + if (ret < 1) + errMsg(1, &errno, "Failed to write file", GAINFILE); + fclose(gainFile); +} + +int openSyncFile(FILE **file, char *fileName, char *fileMode, bool errOK) +{ + int ret = -1; + + if ((*file = fopen(fileName, fileMode)) == NULL) + { + if (errOK == false) + errMsg(1, &errno, "Failed to open file", fileName); + else + { + ret = errno; + } + } + + return ret; +} + +int main(int argc, char *argv[]) +{ + int inotifyFD; + + initState(); + inotifyBuffer = malloc(INOTIFYBUFLEN); + setupSignalHandler(); + + parseArgs(argc, argv); + setWorkdir(); + + writePid(); + writeState(); + + inotifyFD = inotify_init(); + if (inotifyFD < 0) + errMsg(1, NULL, "Failed to setup inotify", NULL); + + do + { + syncState(); + printf("State:\n input = %s\n output = %s\n name = %s\n gain = %.2fdB\n", state.input, state.output, state.name, state.dBGain); + inotify_add_watch(inotifyFD, ".", NOTIFYMASK); + } + while (read(inotifyFD, inotifyBuffer, INOTIFYBUFLEN) >= 0); + + exit(0); +} + +void cleanExit(int r) +{ + if (changedDir == true) + { + if (unlink(PIDFILE) != 0 && errno != ENOENT) + errMsg(-1, &errno, "Failed to delete pidfile", PIDFILE); + } + free(state.input); + free(state.output); + free(state.name); + free(inotifyBuffer); + exit(r); +} + +void errMsg(int r, int *errno, char *head, char *detail) +{ + int err; + bool error = false; + + if (errno != NULL) + { + error = true; + err = *errno; + } + + fprintf(stderr, "%s\n", head); + if (detail != NULL) + fprintf(stderr, " %s\n", detail); + if (error == true) + fprintf(stderr, " (%d) %s\n", err, strerror(err)); + + if (r >= 0) + cleanExit(r); +} diff --git a/trivmix.h b/trivmix.h new file mode 100644 index 0000000..03b5860 --- /dev/null +++ b/trivmix.h @@ -0,0 +1,21 @@ +typedef struct mixState { + char *input; + char *output; + char *name; + float dBGain; +} mixState; + +typedef enum bool { + false, + true +} bool; + +void parseArgs(int argc, char *argv[]); +void setWorkdir(); +void syncState(); +void readState(); +void writeState(); +int openSyncFile(FILE **file, char *fileName, char *fileMode, bool errOK); + +void cleanExit(int r); +void errMsg(int r, int *errno, char *head, char *detail); -- cgit v1.2.3