diff options
Diffstat (limited to 'apps/mixer.c')
-rw-r--r-- | apps/mixer.c | 284 |
1 files changed, 0 insertions, 284 deletions
diff --git a/apps/mixer.c b/apps/mixer.c deleted file mode 100644 index 54df1b4..0000000 --- a/apps/mixer.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 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 <stdio.h> -#include <string.h> -#include <error.h> -#include <poll.h> -#include <assert.h> -#include <sys/types.h> -#include <dirent.h> - -#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 void free_task_entry(void* ptr) -{ - task_t* t = ptr; - assert(t); - free(t->buf_); - free(t); -} - -static int mixer_read_config_file(mixer_t* x, 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(&(x->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)[0]), &((*cmd)[1]), &((*cmd)[2])) != 3) { - continue; - } - assert(slist_add(&(lang->cmds_), cmd)); - } - - fclose(conf); - return 0; -} - -static int mixer_read_config(mixer_t* x) -{ - char path[1024]; - int ret = snprintf(path, sizeof(path), "%s/%s", ETCDIR, x->name_); - assert(ret < sizeof(path)); - - DIR* d = opendir(path); - if(d == NULL) { - error(0, errno, "MIXER: cannot open config directory '%s'", path); - return -1; - } - - struct dirent* entry; - while((entry = readdir(d))) { - if(entry->d_type == DT_REG) { - if((ret = mixer_read_config_file(x, dirfd(d), entry->d_name))) - break; - } - } - - if(closedir(d) < 0) { - error(0, errno, "MIXER: cannot closeconfig directory '%s'", path); - return -1; - } - - return ret; -} - -int mixer_init(mixer_t* x, const char* name, const char* device) -{ - assert(x != NULL); - - x->name_ = name; - x->output_ = NULL; - slist_init(&(x->langs_), free_lang_entry); - slist_init(&(x->tasks_), free_task_entry); - int ret = snd_rawmidi_open(NULL, &(x->output_), device, SND_RAWMIDI_NONBLOCK); - if(ret < 0) { - error(0, 0, "MIXER: cannot open midi port '%s': %s", device, snd_strerror(ret)); - return ret; - } - - return mixer_read_config(x);; -} - -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)[0], (*c)[1], (*c)[2]); - } - } -} - -void mixer_print_langs(mixer_t* x) -{ - assert(x); - - printf("languages:\n"); - if(!slist_length(&(x->langs_))) - printf(" <no languages>\n"); - else { - slist_element_t* tmp; - for(tmp = x->langs_.first_; tmp; tmp = tmp->next_) { - lang_t* l = (lang_t*)(tmp->data_); - printf(" %s:\n", l->name_); - mixer_print_midi_cmds(l->cmds_); - } - } -} - -static u_int8_t* mixer_create_task_buf(slist_t cmds, int len) -{ - u_int8_t* buf = malloc(len); - slist_element_t* tmp; - int i; - for(tmp = cmds.first_, i=0; tmp; tmp = tmp->next_, i+=sizeof(midi_cmd_t)) { - midi_cmd_t* c = (midi_cmd_t*)(tmp->data_); - memcpy(&(buf[i]), (*c), sizeof(midi_cmd_t)); - } - return buf; -} - -int mixer_switch_lang(mixer_t* x, const char* lang, void (*done_cb)(void*), void* done_data) -{ - slist_element_t* tmp; - for(tmp = x->langs_.first_; tmp; tmp = tmp->next_) { - lang_t* l = (lang_t*)(tmp->data_); - if(!strcmp(lang, l->name_)) { - int len = slist_length(&(l->cmds_)); - if(len > 0) { - task_t* task = malloc(sizeof(task_t)); - assert(task); - task->len_ = sizeof(midi_cmd_t) * len; - assert((task->buf_ = mixer_create_task_buf(l->cmds_, task->len_))); - task->write_idx_ = 0; - task->done_cb_ = done_cb; - task->done_data_ = done_data; - assert(slist_add(&(x->tasks_), task)); - } - return 0; - } - } - error(0, 0, "requested language '%s' not found ... ignoring request", lang); - return 0; -} - -void mixer_print_tasks(mixer_t* x) -{ - assert(x); - - printf("tasks:\n"); - if(!slist_length(&(x->tasks_))) - printf(" <no tasks>\n"); - else { - slist_element_t* tmp; - for(tmp = x->tasks_.first_; tmp; tmp = tmp->next_) { - task_t* t = (task_t*)(tmp->data_); - int i; - printf(" buf(%d) = ", t->len_); - for(i = 0; i < t->len_; ++i) { - printf("0x%02X%s", t->buf_[i], (i && !((i+1) % 3)) ? ", " : " "); - } - printf("\n write_idx = %d\n done = %016lX ( %016lX )\n\n", t->write_idx_, (int64_t)(t->done_cb_), (int64_t)(t->done_data_)); - } - } -} - -int mixer_get_poll_fd_count(mixer_t* x) -{ - assert(x); - - return snd_rawmidi_poll_descriptors_count(x->output_); -} - -int mixer_get_poll_fds(mixer_t* x, struct pollfd *pfds, int npfds) -{ - assert(x && pfds && npfds); - - int ret = snd_rawmidi_poll_descriptors(x->output_, pfds, npfds); - if(!slist_length(&(x->tasks_))) { - int i; - for(i = 0; i < ret; ++i) - pfds[i].events = 0; - } - return ret; -} - -int mixer_handle_revents(mixer_t* x, struct pollfd *pfds, int npfds) -{ - assert(x && pfds && npfds); - - int err; - unsigned short revents; - if((err = snd_rawmidi_poll_descriptors_revents(x->output_, pfds, npfds, &revents)) < 0) { - error(0, 0, "MIXER: cannot get poll events: %s", snd_strerror(errno)); - return -1; - } - if(pfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - error(0, 0, "MIXER: got POLLERR, POLLHUP or POLLNVAL"); - return -1; - } - if(!(revents & POLLOUT)) - return 0; - - assert(x->tasks_.first_); - task_t* task = (task_t*)(x->tasks_.first_->data_); - assert(task); - assert(task->buf_); - - int ret = snd_rawmidi_write(x->output_, &(task->buf_[task->write_idx_]), task->len_ - task->write_idx_); - if(ret == -EAGAIN) - return 0; - if(ret < 0) { - error(0, 0, "MIXER: cannot write to midi port: %s", snd_strerror(ret)); - return -1; - } - task->write_idx_ += ret; - if(task->write_idx_ >= task->len_) { - if((err = snd_rawmidi_drain(x->output_)) < 0) { - error(0, 0, "MIXER: cannot drain output: %s", snd_strerror(err)); - return -1; - } - if(task->done_cb_) - task->done_cb_(task->done_data_); - - slist_remove(&(x->tasks_), task); - } - - return 0; -} |