summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2015-10-12 00:29:45 +0200
committerChristian Pointner <equinox@spreadspace.org>2015-10-12 00:29:45 +0200
commit3503079eae02744f8e361a78fb1ef71a30d03b39 (patch)
treefc3565574a422a9055f39651a4bdfc4748656d07 /apps
parentreading config dir works now (diff)
reading of mixer commands works now
Diffstat (limited to 'apps')
-rw-r--r--apps/Makefile3
-rw-r--r--apps/dolmetschctl.c13
-rw-r--r--apps/mixer.c91
-rw-r--r--apps/mixer.h13
-rw-r--r--apps/slist.c123
-rw-r--r--apps/slist.h46
6 files changed, 277 insertions, 12 deletions
diff --git a/apps/Makefile b/apps/Makefile
index cce8207..ff1bd06 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -28,7 +28,8 @@ EXECUTABLE := dolmetschctl
C_OBJS := osc.o \
midi.o \
- mixer.o \
+ slist.o \
+ mixer.o \
dolmetschctl.o
C_SRCS := $(C_OBJS:%.o=%.c)
diff --git a/apps/dolmetschctl.c b/apps/dolmetschctl.c
index 5365c22..2cffff7 100644
--- a/apps/dolmetschctl.c
+++ b/apps/dolmetschctl.c
@@ -62,13 +62,18 @@ int main_loop(mixer_t* x, midi_t* m, osc_t* o)
int npfds = midi_npfds + osc_npfds + mixer_npfds;
struct pollfd *pfds = alloca(npfds * sizeof(struct pollfd));
-
+ if(!pfds) {
+ error(0, 0, "error while allocating poll fds - stack corrupted??");
+ return -1;
+ }
mixer_get_poll_fds(x, &(pfds[mixer_npfds_offset]), mixer_npfds);
midi_get_poll_fds(m, &(pfds[midi_npfds_offset]), midi_npfds);
osc_get_poll_fds(o, &(pfds[osc_npfds_offset]), osc_npfds);
- printf("main_loop running...\n");
+ mixer_print_langs(x);
+
+ printf("main_loop running with %d pollfds...\n", npfds);
for (;;) {
int err = poll(pfds, npfds, 200);
if(err < 0 && errno != EINTR) {
@@ -99,11 +104,11 @@ int main_loop(mixer_t* x, midi_t* m, osc_t* o)
int main(int argc, char* argv[])
{
mixer_t x;
- if(mixer_init(&x, "qu24", "hw:1,0,0"))
+ if(mixer_init(&x, "qu24", "hw:2,0,0"))
return -1;
midi_t m;
- if(midi_init(&m, "hw:1,0,0"))
+ if(midi_init(&m, "hw:3,0,0"))
return -1;
osc_t o;
diff --git a/apps/mixer.c b/apps/mixer.c
index 4a6d128..4112c6d 100644
--- a/apps/mixer.c
+++ b/apps/mixer.c
@@ -31,6 +31,53 @@
#include "mixer.h"
+static void free_lang_entry(void* ptr)
+{
+ lang_t* l = ptr;
+ assert(l);
+ free(l->name_);
+ slist_clear(&(l->cmds_));
+ free(l);
+}
+
+static int mixer_read_config_file(mixer_t* m, int dirfd, const char* filename)
+{
+ assert(dirfd > 0);
+
+ int fd = openat(dirfd, filename, O_RDONLY);
+ if(fd < 0) {
+ error(0, errno, "erorr open('%s')", filename);
+ return -1;
+ }
+ FILE* conf = fdopen(fd, "r");
+ if(conf == NULL) {
+ error(0, errno, "erorr fdopen('%s')", filename);
+ return -1;
+ }
+
+ lang_t* lang = malloc(sizeof(lang_t));
+ assert(lang);
+ assert((lang->name_ = strdup(filename)));
+ slist_init(&(lang->cmds_), free);
+ assert(slist_add(&(m->langs_), lang));
+
+ char buf[256];
+ while(fgets(buf, sizeof(buf), conf) != NULL) {
+ midi_cmd_t* cmd = malloc(sizeof(midi_cmd_t));
+ if(!cmd) {
+ error(0, ENOMEM, "can't create midi command stucture");
+ break;
+ }
+ if(sscanf(buf, "%02hhx %02hhx %02hhx", &(cmd->code_[0]), &(cmd->code_[1]), &(cmd->code_[2])) != 3) {
+ continue;
+ }
+ assert(slist_add(&(lang->cmds_), cmd));
+ }
+
+ fclose(conf);
+ return 0;
+}
+
static int mixer_read_config(mixer_t* m)
{
char path[1024];
@@ -43,21 +90,20 @@ static int mixer_read_config(mixer_t* m)
return -1;
}
- struct dirent* entry = readdir(d);
- while(entry) {
+ struct dirent* entry;
+ while((entry = readdir(d))) {
if(entry->d_type == DT_REG) {
- printf(" > found config file: '%s'\n", entry->d_name);
+ if((ret = mixer_read_config_file(m, dirfd(d), entry->d_name)))
+ break;
}
- entry = readdir(d);
}
- ret = closedir(d);
- if(ret < 0) {
+ if(closedir(d) < 0) {
error(0, errno, "MIXER: cannot closeconfig directory '%s'", path);
return -1;
}
- return 0;
+ return ret;
}
int mixer_init(mixer_t* m, const char* name, const char* device)
@@ -66,6 +112,7 @@ int mixer_init(mixer_t* m, const char* name, const char* device)
m->name_ = name;
m->output_ = NULL;
+ slist_init(&(m->langs_), free_lang_entry);
int ret = snd_rawmidi_open(NULL, &(m->output_), device, SND_RAWMIDI_NONBLOCK);
if(ret < 0) {
error(0, 0, "MIXER: cannot open midi port '%s': %s", device, snd_strerror(ret));
@@ -75,6 +122,36 @@ int mixer_init(mixer_t* m, const char* name, const char* device)
return mixer_read_config(m);;
}
+static void mixer_print_midi_cmds(slist_t cmds)
+{
+ if(!slist_length(&(cmds)))
+ printf("<no commands>\n");
+ else {
+ slist_element_t* tmp;
+ for(tmp = cmds.first_; tmp; tmp = tmp->next_) {
+ midi_cmd_t* c = (midi_cmd_t*)(tmp->data_);
+ printf(" 0x%02X 0x%02X 0x%02X\n", c->code_[0], c->code_[1], c->code_[2]);
+ }
+ }
+}
+
+void mixer_print_langs(mixer_t* m)
+{
+ assert(m);
+
+ printf("mixer:\n");
+ if(!slist_length(&(m->langs_)))
+ printf(" <no languages>\n");
+ else {
+ slist_element_t* tmp;
+ for(tmp = m->langs_.first_; tmp; tmp = tmp->next_) {
+ lang_t* l = (lang_t*)(tmp->data_);
+ printf(" %s:\n", l->name_);
+ mixer_print_midi_cmds(l->cmds_);
+ }
+ }
+}
+
int mixer_get_poll_fd_count(mixer_t* m)
{
return snd_rawmidi_poll_descriptors_count(m->output_);
diff --git a/apps/mixer.h b/apps/mixer.h
index fdd1197..1e22391 100644
--- a/apps/mixer.h
+++ b/apps/mixer.h
@@ -26,12 +26,25 @@
#include <alsa/asoundlib.h>
#include <poll.h>
+#include "slist.h"
+
+typedef struct {
+ u_int8_t code_[3];
+} midi_cmd_t;
+
+typedef struct {
+ char* name_;
+ slist_t cmds_;
+} lang_t;
+
typedef struct {
const char* name_;
snd_rawmidi_t* output_;
+ slist_t langs_;
} mixer_t;
int mixer_init(mixer_t* m, const char* name, const char* device);
+void mixer_print_langs(mixer_t* m);
int mixer_get_poll_fd_count(mixer_t* m);
int mixer_get_poll_fds(mixer_t* m, struct pollfd *pfds, int npfds);
int mixer_handle_revents(mixer_t* m, struct pollfd *pfds, int npfds);
diff --git a/apps/slist.c b/apps/slist.c
new file mode 100644
index 0000000..b10aca7
--- /dev/null
+++ b/apps/slist.c
@@ -0,0 +1,123 @@
+/*
+ * dolmetschctl
+ *
+ *
+ * Copyright (C) 2015 Christian Pointner <equinox@spreadspace.org>
+ *
+ * This file is part of dolmetschctl.
+ *
+ * dolmetschctl is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * dolmetschctl is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with dolmetschctl. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "slist.h"
+
+slist_element_t* slist_get_last(slist_element_t* first)
+{
+ if(!first)
+ return NULL;
+
+ while(first->next_)
+ first = first->next_;
+
+ return first;
+}
+
+void slist_init(slist_t* lst, void (*delete_element)(void*))
+{
+ assert(lst && delete_element);
+
+ lst->delete_element = delete_element;
+ lst->first_ = NULL;
+}
+
+slist_element_t* slist_add(slist_t* lst, void* data)
+{
+ if(!lst || !data)
+ return NULL;
+
+ slist_element_t* new_element = malloc(sizeof(slist_element_t));
+ if(!new_element)
+ return NULL;
+
+ new_element->data_ = data;
+ new_element->next_ = NULL;
+
+ if(!lst->first_)
+ lst->first_ = new_element;
+ else
+ slist_get_last(lst->first_)->next_ = new_element;
+
+ return new_element;
+}
+
+void slist_remove(slist_t* lst, void* data)
+{
+ if(!lst || !lst->first_ || !data)
+ return;
+
+ slist_element_t* tmp = lst->first_->next_;
+ slist_element_t* prev = lst->first_;
+ if(lst->first_->data_ == data) {
+ lst->first_ = tmp;
+ lst->delete_element(prev->data_);
+ free(prev);
+ }
+ else {
+ while(tmp) {
+ if(tmp->data_ == data) {
+ prev->next_ = tmp->next_;
+ lst->delete_element(tmp->data_);
+ free(tmp);
+ return;
+ }
+ prev = tmp;
+ tmp = tmp->next_;
+ }
+ }
+}
+
+void slist_clear(slist_t* lst)
+{
+ if(!lst || !lst->first_)
+ return;
+
+ do {
+ slist_element_t* deletee = lst->first_;
+ lst->first_ = lst->first_->next_;
+ lst->delete_element(deletee->data_);
+ free(deletee);
+ }
+ while(lst->first_);
+
+ lst->first_ = NULL;
+}
+
+int slist_length(slist_t* lst)
+{
+ if(!lst || !lst->first_)
+ return 0;
+
+ int len = 0;
+ slist_element_t* tmp;
+ for(tmp = lst->first_; tmp; tmp = tmp->next_)
+ len++;
+
+ return len;
+}
diff --git a/apps/slist.h b/apps/slist.h
new file mode 100644
index 0000000..70a81b5
--- /dev/null
+++ b/apps/slist.h
@@ -0,0 +1,46 @@
+/*
+ * dolmetschctl
+ *
+ *
+ * Copyright (C) 2015 Christian Pointner <equinox@spreadspace.org>
+ *
+ * This file is part of dolmetschctl.
+ *
+ * dolmetschctl is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * dolmetschctl is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with dolmetschctl. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DOLMETSCHCTL_slist_h_INCLUDED
+#define DOLMETSCHCTL_slist_h_INCLUDED
+
+struct slist_element_struct {
+ void* data_;
+ struct slist_element_struct* next_;
+};
+typedef struct slist_element_struct slist_element_t;
+
+slist_element_t* slist_get_last(slist_element_t* first);
+
+struct slist_struct {
+ void (*delete_element)(void* element);
+ slist_element_t* first_;
+};
+typedef struct slist_struct slist_t;
+
+void slist_init(slist_t* lst, void (*delete_element)(void*));
+slist_element_t* slist_add(slist_t* lst, void* data);
+void slist_remove(slist_t* lst, void* data);
+void slist_clear(slist_t* lst);
+int slist_length(slist_t* lst);
+
+#endif