diff options
author | Christian Pointner <equinox@spreadspace.org> | 2015-10-12 00:29:45 +0200 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2015-10-12 00:29:45 +0200 |
commit | 3503079eae02744f8e361a78fb1ef71a30d03b39 (patch) | |
tree | fc3565574a422a9055f39651a4bdfc4748656d07 | |
parent | reading config dir works now (diff) |
reading of mixer commands works now
-rw-r--r-- | apps/Makefile | 3 | ||||
-rw-r--r-- | apps/dolmetschctl.c | 13 | ||||
-rw-r--r-- | apps/mixer.c | 91 | ||||
-rw-r--r-- | apps/mixer.h | 13 | ||||
-rw-r--r-- | apps/slist.c | 123 | ||||
-rw-r--r-- | apps/slist.h | 46 |
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 |