summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2015-10-12 06:54:55 +0200
committerChristian Pointner <equinox@spreadspace.org>2015-10-12 06:54:55 +0200
commit24714dcba8a4b4717251f320570653e1cebf029a (patch)
treec23e643005b951e0c714e045312099cc34879a9d /apps
parentadded command line parser (diff)
moved apps to server
Diffstat (limited to 'apps')
-rw-r--r--apps/Makefile94
-rwxr-xr-xapps/configure163
-rw-r--r--apps/dolmetschctl.c220
-rw-r--r--apps/midi.c237
-rw-r--r--apps/midi.h55
-rw-r--r--apps/mixer.c284
-rw-r--r--apps/mixer.h61
-rw-r--r--apps/osc.c162
-rw-r--r--apps/osc.h50
-rw-r--r--apps/slist.c123
-rw-r--r--apps/slist.h46
11 files changed, 0 insertions, 1495 deletions
diff --git a/apps/Makefile b/apps/Makefile
deleted file mode 100644
index ff1bd06..0000000
--- a/apps/Makefile
+++ /dev/null
@@ -1,94 +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/>.
-##
-
-ifneq ($(MAKECMDGOALS),distclean)
-include include.mk
-endif
-
-EXECUTABLE := dolmetschctl
-
-C_OBJS := osc.o \
- midi.o \
- slist.o \
- mixer.o \
- dolmetschctl.o
-
-C_SRCS := $(C_OBJS:%.o=%.c)
-
-.PHONY: clean distclean install install-bin install-etc uninstall remove remove-bin remove-etc purge
-
-all: $(EXECUTABLE)
-
-%.d: %.c
- @set -e; rm -f $@; \
- $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
- sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
- rm -f $@.$$$$; echo '(re)building $@'
-
-ifneq ($(MAKECMDGOALS),distclean)
--include $(C_SRCS:%.c=%.d)
-endif
-
-$(EXECUTABLE): $(C_OBJS)
- $(CC) $(C_OBJS) -o $@ $(LDFLAGS)
-
-%.o: %.c
- $(CC) $(CFLAGS) -c $<
-
-strip: $(EXECUTABLE)
- $(STRIP) -s $(EXECUTABLE)
-
-
-distclean: clean
- find . -name *.o -exec rm -f {} \;
- find . -name "*.\~*" -exec rm -rf {} \;
- rm -f include.mk
- rm -f config.h
-
-clean:
- rm -f *.o
- rm -f *.d
- rm -f *.d.*
- rm -f $(EXECUTABLE)
-
-INSTALL_TARGETS := install-bin install-etc
-REMOVE_TARGETS := remove-bin remove-etc
-
-install: all $(INSTALL_TARGETS)
-
-install-bin: $(EXECUTABLE)
- $(INSTALL) -d $(DESTDIR)$(BINDIR)
- $(INSTALL) -m 755 $(EXECUTABLE) $(DESTDIR)$(BINDIR)
-
-install-etc:
-
-uninstall: remove
-
-remove: $(REMOVE_TARGETS)
-
-remove-bin:
- rm -f $(DESTDIR)$(BINDIR)/$(EXECUTABLE)
-
-remove-etc:
-
-purge: remove
- rm -rf $(DESTDIR)$(ETCDIR)/$(EXECUTABLE)/ \ No newline at end of file
diff --git a/apps/configure b/apps/configure
deleted file mode 100755
index 9809caa..0000000
--- a/apps/configure
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/bin/sh
-#
-# 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/>.
-#
-
-TARGET=`uname -s`
-EBUILD_COMPAT=0
-
-USE_CLANG=0
-
-PREFIX='/usr/local'
-BINDIR=''
-ETCDIR=''
-
-print_usage() {
- echo "configure --help print this"
- echo " --target=<TARGET> build target i.e. Linux (default: autodetect)"
- echo " --prefix=<PREFIX> the installation prefix (default: /usr/local)"
- echo " --bindir=<DIR> the path to the bin directory (default: $PREFIX/bin)"
- echo " --sysconfdir=<DIR> the path to the system configuration directory (default: $PREFIX/etc"
- echo " --use-clang use clang/llvm as compiler/linker"
-}
-
-for arg
-do
- case $arg in
- --target=*)
- TARGET=${arg#--target=}
- ;;
- --use-clang)
- USE_CLANG=1
- ;;
- --prefix=*)
- PREFIX=${arg#--prefix=}
- ;;
- --bindir=*)
- BINDIR=${arg#--bindir=}
- ;;
- --sysconfdir=*)
- ETCDIR=${arg#--sysconfdir=}
- ;;
- --ebuild-compat)
- EBUILD_COMPAT=1
- ;;
- --help)
- print_usage
- exit 0
- ;;
- *)
- ERRORS="$ERRORS $arg"
- ;;
- esac
-done
-
-if [ -n "$ERRORS" ] && [ $EBUILD_COMPAT -ne 1 ]; then
- for error in $ERRORS; do
- echo "Unknown argument: $error"
- done
-
- print_usage
- exit 1
-fi
-
-if [ $USE_CLANG -eq 0 ]; then
- CFLAGS='-g -Wall -O2'
- LDFLAGS='-g -Wall -O2'
- COMPILER='gcc'
-else
- CFLAGS='-g -O2'
- LDFLAGS='-g -O2'
- COMPILER='clang'
-fi
-
-rm -f config.h
-rm -f include.mk
-case $TARGET in
- Linux)
- LDFLAGS=$LD_FLAGS' -lasound -llo'
- ;;
- *)
- echo "platform not supported"
- exit 1;
- ;;
-esac
-
-if [ -z "$BINDIR" ]; then
- BINDIR=$PREFIX/bin
-fi
-
-if [ -z "$ETCDIR" ]; then
- ETCDIR=$PREFIX/etc
-fi
-
-cat > include.mk <<EOF
-# this file was created automatically
-# do not edit this file directly
-# use ./configure instead
-
-TARGET := $TARGET
-CC := $COMPILER
-CFLAGS := $CFLAGS
-LDFLAGS := $LDFLAGS
-STRIP := strip
-INSTALL := install
-
-prefix := '$PREFIX'
-BINDIR := '$BINDIR'
-ETCDIR := '$ETCDIR'
-EOF
-
-VERSION=`cat ../version`
-if which git >/dev/null; then
- GIT_HASH=`git rev-parse HEAD 2> /dev/null`
- if [ -n "$GIT_HASH" ]; then
- VERSION="$VERSION (git $GIT_HASH)"
- fi
-fi
-
-HOSTNAME=`hostname`
-DATE=`date +"%d.%m.%Y %H:%M:%S %Z"`
-
-cat > config.h <<EOF
-/*
- * dolmetschctl config header
- *
- * this file was created automatically
- * do not edit this file directly
- * use ./configure instead
- */
-
-#ifndef DOLMETSCHCTL_config_h_INCLUDED
-#define DOLMETSCHCTL_config_h_INCLUDED
-
-#define VERSION_STRING_0 "dolmetschctl version $VERSION"
-#define VERSION_STRING_1 "built on $HOSTNAME, $DATE"
-
-#define TARGET "$TARGET"
-#define PREFIX "$PREFIX"
-#define BINDIR "$BINDIR"
-#define ETCDIR "$ETCDIR"
-
-#endif
-EOF
-
-exit 0
diff --git a/apps/dolmetschctl.c b/apps/dolmetschctl.c
deleted file mode 100644
index fd63e99..0000000
--- a/apps/dolmetschctl.c
+++ /dev/null
@@ -1,220 +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 <unistd.h>
-#include <ctype.h>
-#include <error.h>
-
-#include <lo/lo.h>
-#include <alsa/asoundlib.h>
-
-#include "mixer.h"
-#include "midi.h"
-#include "osc.h"
-
-
-void print_version()
-{
- printf("%s\n", VERSION_STRING_0);
-#if defined(__clang__)
- printf("%s, using CLANG %s\n", VERSION_STRING_1, __clang_version__);
-#elif defined(__GNUC__)
- printf("%s, using GCC %d.%d.%d\n", VERSION_STRING_1, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
-#else
- printf("%s\n", VERSION_STRING_1);
-#endif
-
- printf("linked against alsa-lib Version %s\n", snd_asoundlib_version());
- char verstr[32];
- lo_version(verstr, sizeof(verstr), 0, 0, 0, 0, 0, 0, 0);
- printf("linked against liblo Version %s\n", verstr);
-}
-
-void print_usage()
-{
- printf("\ndolmetschctl <options>\n");
- printf(" -h print this and exit\n");
- printf(" -v print version information and exit\n");
- printf(" -x <name> the name of the mixer, dolmetschctl will look for\n");
- printf(" language files inside '%s/<name>/'\n", ETCDIR);
- printf(" -d <dev> the mixer MIDI device name to use, i.e. hw:2,0,0\n");
- printf(" (use `amidi -l` to list all available devices)'\n");
- printf(" -m <dev> the MIDI control device name to use, this can be omitted to\n");
- printf(" only wait for OSC messages'\n");
- printf(" -o <port> the UDP port to listen on for OSC messages, this can be omitted\n");
- printf(" to only use the control MIDI interface'\n");
-}
-
-int main_loop(mixer_t* x, midi_t* m, osc_t* o)
-{
- int ret = 0;
-
- printf("main_loop just started\n");
-
- int mixer_npfds_offset = 0;
- int mixer_npfds = mixer_get_poll_fd_count(x);
- assert(mixer_npfds > 0);
-
- int midi_npfds_offset = mixer_npfds_offset + mixer_npfds;
- int midi_npfds = midi_get_poll_fd_count(m);
- assert(midi_npfds >= 0);
-
- int osc_npfds_offset = midi_npfds_offset + midi_npfds;
- int osc_npfds = osc_get_poll_fd_count(o);
- assert(osc_npfds >= 0);
-
- 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;
- }
-
- printf("main_loop running with %d pollfds...\n", npfds);
- for (;;) {
- 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);
-
- int err = poll(pfds, npfds, 200);
- if(err < 0 && errno != EINTR) {
- error(0, errno, "poll failed");
- break;
- }
- if(err <= 0) {
- // timeout or EINTR
- continue;
- }
-
- ret = mixer_handle_revents(x, &(pfds[mixer_npfds_offset]), mixer_npfds);
- if(ret)
- break;
-
- ret = midi_handle_revents(m, &(pfds[midi_npfds_offset]), midi_npfds, x);
- if(ret)
- break;
-
- ret = osc_handle_revents(o, &(pfds[osc_npfds_offset]), osc_npfds, x);
- if(ret)
- break;
- }
-
- return ret;
-}
-
-int main(int argc, char* argv[])
-{
- int helpflag = 0;
- int versionflag = 0;
- char* mixer_name = NULL;
- char* mixer_dev = NULL;
- char* midi_dev = NULL;
- char* osc_port = NULL;
-
- int c;
- opterr = 0;
- while ((c = getopt (argc, argv, "vhx:d:m:o:")) != -1) {
- switch (c) {
- case 'h':
- helpflag = 1;
- break;
- case 'v':
- versionflag = 1;
- break;
- case 'x':
- mixer_name = optarg;
- break;
- case 'd':
- mixer_dev = optarg;
- break;
- case 'm':
- midi_dev = optarg;
- break;
- case 'o':
- osc_port = optarg;
- break;
- case '?':
- if (optopt == 'x')
- error(0, 0, "Option -%c requires an argument.\n", optopt);
- else if (optopt == 'd')
- error(0, 0, "Option -%c requires an argument.\n", optopt);
- else if (optopt == 'm')
- error(0, 0, "Option -%c requires an argument.\n", optopt);
- else if (optopt == 'o')
- error(0, 0, "Option -%c requires an argument.\n", optopt);
- else if (isprint (optopt))
- error(0, 0, "Unknown option `-%c'.\n", optopt);
- else
- error(0, 0, "Unknown option character `\\x%x'.\n", optopt);
- return -1;
- default:
- return -1;
- }
- }
-
- if(helpflag) {
- print_usage();
- return 0;
- }
-
- if(versionflag) {
- print_version();
- return 0;
- }
-
- if(!mixer_name){
- error(0, 0, "mixer name must be set");
- print_usage();
- return -1;
- }
-
- if(!mixer_dev){
- error(0, 0, "mixer device name must be set");
- print_usage();
- return -1;
- }
-
- if(!midi_dev && !osc_port) {
- error(0, 0, "either midi or osc (or both) must be specified");
- print_usage();
- return -1;
- }
-
- mixer_t x;
- if(mixer_init(&x, mixer_name, mixer_dev))
- return -1;
-
- midi_t m;
- if(midi_init(&m, midi_dev))
- return -1;
-
- osc_t o;
- if(osc_init(&o, osc_port))
- return -1;
-
- int ret = main_loop(&x, &m, &o);
-
- return ret;
-}
diff --git a/apps/midi.c b/apps/midi.c
deleted file mode 100644
index 6ef5775..0000000
--- a/apps/midi.c
+++ /dev/null
@@ -1,237 +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 <error.h>
-#include <poll.h>
-#include <assert.h>
-
-#include "midi.h"
-
-#define NOTE_EN 0x00
-#define NOTE_DE 0x01
-u_int8_t done_data_en[] = { 0xB0, NOTE_EN, 0x01, 0xB0, NOTE_DE, 0x00 };
-u_int8_t done_data_de[] = { 0xB0, NOTE_EN, 0x00, 0xB0, NOTE_DE, 0x01 };
-
-int midi_init(midi_t* m, const char* device)
-{
- assert(m != NULL);
-
- m->input_ = NULL;
- m->output_ = NULL;
- memset(m->buf_, 0, sizeof(m->buf_));
- m->read_idx_ = 0;
-
- slist_init(&(m->done_data_), free);
-
- if(device) {
- int ret = snd_rawmidi_open(&(m->input_), &(m->output_), device, SND_RAWMIDI_NONBLOCK);
- if(ret < 0) {
- error(0, 0, "MIDI: cannot open port '%s': %s", device, snd_strerror(ret));
- return ret;
- }
- }
-
- return 0;
-}
-
-int midi_get_poll_fd_count(midi_t* m)
-{
- assert(m);
-
- if(!m->input_ || !m->output_)
- return 0;
-
- m->in_pfds_cnt_ = snd_rawmidi_poll_descriptors_count(m->input_);
- assert(m->in_pfds_cnt_ > 0);
- m->out_pfds_cnt_ = snd_rawmidi_poll_descriptors_count(m->output_);
- assert(m->out_pfds_cnt_ > 0);
-
- return (m->in_pfds_cnt_ + m->out_pfds_cnt_);
-}
-
-int midi_get_poll_fds(midi_t* m, struct pollfd *pfds, int npfds)
-{
- assert(m);
-
- if(!m->input_ || !m->output_)
- return 0;
-
- snd_rawmidi_poll_descriptors(m->input_, pfds, m->in_pfds_cnt_);
- snd_rawmidi_poll_descriptors(m->output_, &(pfds[m->in_pfds_cnt_]), npfds - m->in_pfds_cnt_);
-
- int pending_data = 0;
- if(m->done_data_.first_) {
- midi_done_data_t* d = (midi_done_data_t*)(m->done_data_.first_->data_);
- if(d->active_)
- pending_data = 1;
- }
- if(!pending_data) {
- int i;
- for(i = m->in_pfds_cnt_; i < npfds; ++i)
- pfds[i].events = 0;
- }
- return (m->in_pfds_cnt_ + m->out_pfds_cnt_);
-}
-
-void midi_lang_switch_done(void* data)
-{
- assert(data);
- midi_done_data_t* d = data;
- d->active_ = 1;
-}
-
-static int midi_enqueue_lang_switch(midi_t* m, mixer_t* x, const char* lang, const u_int8_t* buf, int len)
-{
- midi_done_data_t* done_data = malloc(sizeof(midi_done_data_t));
- assert(done_data);
- done_data->self_ = m;
- done_data->active_ = 0;
- done_data->buf_ = buf;
- done_data->len_ = len;
- done_data->write_idx_ = 0;
- assert(slist_add(&(m->done_data_), done_data));
-
- return mixer_switch_lang(x, lang, &midi_lang_switch_done, done_data);
-}
-
-static int midi_handle_note_on(midi_t* m, mixer_t* x)
-{
- int ret = 0;
- switch(m->buf_[1]) {
- case NOTE_EN: ret = midi_enqueue_lang_switch(m, x, "en", done_data_en, sizeof(done_data_en)); break;
- case NOTE_DE: ret = midi_enqueue_lang_switch(m, x, "de", done_data_de, sizeof(done_data_de)); break;
- default: printf("ignoring unknown note\n"); break;
- }
- return ret;
-}
-
-static int midi_handle_note_off(midi_t* m, mixer_t* x)
-{
- return 0;
-}
-
-static int midi_handle_message(midi_t* m, mixer_t* x)
-{
- /* int i; */
- /* printf("MIDI: "); */
- /* for (i = 0; i < sizeof(m->buf_); ++i) */
- /* printf("%02X%c", m->buf_[i], (i >= (sizeof(m->buf_)-1)) ? '\n' : ' '); */
-
- int ret = 0;
- switch(m->buf_[0]) {
- case 0x90: ret = midi_handle_note_on(m, x); break;
- case 0x80: ret = midi_handle_note_off(m, x); break;
- default: printf("ignoring unknown midi command\n"); break;
- }
-
- return ret;
-}
-
-static int midi_handle_in_revents(midi_t* m, struct pollfd *pfds, int npfds, mixer_t* x)
-{
- int err;
- unsigned short revents;
- if((err = snd_rawmidi_poll_descriptors_revents(m->input_, pfds, npfds, &revents)) < 0) {
- error(0, 0, "MIDI: cannot get poll events: %s", snd_strerror(errno));
- return -1;
- }
- if(pfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
- error(0, 0, "MIDI: got POLLERR, POLLHUP or POLLNVAL");
- return -1;
- }
- if(!(revents & POLLIN))
- return 0;
-
- int ret = snd_rawmidi_read(m->input_, &(m->buf_[m->read_idx_]), sizeof(m->buf_) - m->read_idx_);
- if(ret == -EAGAIN)
- return 0;
- if(ret < 0) {
- error(0, 0, "MIDI: cannot read from midi port: %s", snd_strerror(ret));
- return -1;
- }
- m->read_idx_ += ret;
- if(m->read_idx_ >= sizeof(m->buf_)) {
- ret = midi_handle_message(m, x);
- memset(m->buf_, 0, sizeof(m->buf_));
- m->read_idx_ = 0;
- return ret;
- }
-
- return ret;
-}
-
-static int midi_handle_out_revents(midi_t* m, struct pollfd *pfds, int npfds)
-{
- int err;
- unsigned short revents;
- if((err = snd_rawmidi_poll_descriptors_revents(m->output_, pfds, npfds, &revents)) < 0) {
- error(0, 0, "MIDI: cannot get poll events: %s", snd_strerror(errno));
- return -1;
- }
- if(pfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
- error(0, 0, "MIDI: got POLLERR, POLLHUP or POLLNVAL");
- return -1;
- }
- if(!(revents & POLLOUT))
- return 0;
-
- assert(m->done_data_.first_);
- midi_done_data_t* done_data = (midi_done_data_t*)(m->done_data_.first_->data_);
- assert(done_data);
- assert(done_data->active_);
- assert(done_data->buf_);
-
- int ret = snd_rawmidi_write(m->output_, &(done_data->buf_[done_data->write_idx_]), done_data->len_ - done_data->write_idx_);
- if(ret == -EAGAIN)
- return 0;
- if(ret < 0) {
- error(0, 0, "MIDI: cannot write to port: %s", snd_strerror(ret));
- return -1;
- }
- done_data->write_idx_ += ret;
- if(done_data->write_idx_ >= done_data->len_) {
- if((err = snd_rawmidi_drain(m->output_)) < 0) {
- error(0, 0, "MIDI: cannot drain output: %s", snd_strerror(err));
- return -1;
- }
- slist_remove(&(m->done_data_), done_data);
- }
-
- return 0;
-}
-
-int midi_handle_revents(midi_t* m, struct pollfd *pfds, int npfds, mixer_t* x)
-{
- assert(m);
-
- if(!m->input_ || !m->output_)
- return 0;
-
- int ret = midi_handle_in_revents(m, pfds, m->in_pfds_cnt_, x);
- if(ret)
- return ret;
-
- return midi_handle_out_revents(m, &(pfds[m->in_pfds_cnt_]), m->out_pfds_cnt_);
-}
diff --git a/apps/midi.h b/apps/midi.h
deleted file mode 100644
index 537c356..0000000
--- a/apps/midi.h
+++ /dev/null
@@ -1,55 +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/>.
- */
-
-#ifndef DOLMETSCHCTL_midi_h_INCLUDED
-#define DOLMETSCHCTL_midi_h_INCLUDED
-
-#include <alsa/asoundlib.h>
-#include <poll.h>
-
-#include "slist.h"
-#include "mixer.h"
-
-typedef struct {
- snd_rawmidi_t* input_;
- int in_pfds_cnt_;
- snd_rawmidi_t* output_;
- int out_pfds_cnt_;
- u_int8_t buf_[3];
- int read_idx_;
- slist_t done_data_;
-} midi_t;
-
-typedef struct {
- midi_t* self_;
- int active_;
- const u_int8_t* buf_;
- int len_;
- int write_idx_;
-} midi_done_data_t;
-
-int midi_init(midi_t* m, const char* device);
-int midi_get_poll_fd_count(midi_t* m);
-int midi_get_poll_fds(midi_t* m, struct pollfd *pfds, int npfds);
-int midi_handle_revents(midi_t* m, struct pollfd *pfds, int npfds, mixer_t* x);
-
-#endif
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;
-}
diff --git a/apps/mixer.h b/apps/mixer.h
deleted file mode 100644
index 5d9c666..0000000
--- a/apps/mixer.h
+++ /dev/null
@@ -1,61 +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/>.
- */
-
-#ifndef DOLMETSCHCTL_mixer_h_INCLUDED
-#define DOLMETSCHCTL_mixer_h_INCLUDED
-
-#include <alsa/asoundlib.h>
-#include <poll.h>
-
-#include "slist.h"
-
-typedef u_int8_t midi_cmd_t[3];
-
-typedef struct {
- char* name_;
- slist_t cmds_;
-} lang_t;
-
-typedef struct {
- u_int8_t* buf_;
- int len_;
- int write_idx_;
- void (*done_cb_)(void*);
- void* done_data_;
-} task_t;
-
-typedef struct {
- const char* name_;
- snd_rawmidi_t* output_;
- slist_t langs_;
- slist_t tasks_;
-} mixer_t;
-
-int mixer_init(mixer_t* x, const char* name, const char* device);
-void mixer_print_langs(mixer_t* x);
-int mixer_switch_lang(mixer_t* x, const char* lang, void (*done_cb)(void*), void* done_data);
-void mixer_print_tasks(mixer_t* x);
-int mixer_get_poll_fd_count(mixer_t* x);
-int mixer_get_poll_fds(mixer_t* x, struct pollfd *pfds, int npfds);
-int mixer_handle_revents(mixer_t* x, struct pollfd *pfds, int npfds);
-
-#endif
diff --git a/apps/osc.c b/apps/osc.c
deleted file mode 100644
index 656d400..0000000
--- a/apps/osc.c
+++ /dev/null
@@ -1,162 +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 <error.h>
-#include <assert.h>
-
-#include "osc.h"
-
-
-static void print_error(int num, const char *msg, const char *path)
-{
- error(0, 0, "liblo server error %d in path %s: %s", num, path, msg);
-}
-
-static int lang_handler(const char *path, const char *types, lo_arg ** argv,
- int argc, lo_message msg, void *user_data)
-{
- if(argc != 1 || !lo_is_string_type((lo_type)types[0]))
- return 1;
-
- lo_address from = lo_message_get_source(msg);
- const char* host = lo_address_get_hostname(from);
- const char* port = lo_address_get_port(from);
- assert(host && port);
-
- osc_t* o = (osc_t*)user_data;
- assert(o);
- osc_done_data_t* done_data = malloc(sizeof(osc_done_data_t));
- assert(done_data);
-
- done_data->self_ = o;
- done_data->state_ = 0;
- assert((done_data->lang_ = strdup(&(argv[0]->s))));
- done_data->addr_ = lo_address_new(host, port);
- assert(done_data->addr_);
- done_data->msg_ = lo_message_new();
- assert(done_data->msg_);
- assert(!lo_message_add(done_data->msg_, "s", done_data->lang_));
-
- assert(slist_add(&(o->done_data_), done_data));
-
- return 0;
-}
-
-void free_osc_done_data(void* ptr)
-{
- osc_done_data_t* done_data = (osc_done_data_t*)ptr;
-
- lo_message_free(done_data->msg_);
- lo_address_free(done_data->addr_);
- free(done_data->lang_);
- free(done_data);
-}
-
-void osc_lang_switch_done(void* data)
-{
- assert(data);
- osc_done_data_t* d = data;
-
- lo_send_message_from(d->addr_, d->self_->server_, "/lang/ack", d->msg_);
- slist_remove(&(d->self_->done_data_), d);
-}
-
-int osc_init(osc_t* o, const char* port)
-{
- assert(o != NULL);
-
- o->server_ = NULL;
- slist_init(&(o->done_data_), free_osc_done_data);
-
- if(!port)
- return 0;
-
- o->server_ = lo_server_new(port, print_error);
- if(!o->server_)
- return -1;
-
- if(!lo_server_add_method(o->server_, "/lang/switch", "s", lang_handler, (void*)o))
- return -1;
-
- return 0;
-}
-
-
-int osc_get_poll_fd_count(osc_t* o)
-{
- assert(o);
-
- if(!o->server_)
- return 0;
-
- return 1;
-}
-
-int osc_get_poll_fds(osc_t* o, struct pollfd *pfds, int npfds)
-{
- assert(o);
-
- if(!o->server_)
- return 0;
-
- pfds[0].fd = lo_server_get_socket_fd(o->server_);
- pfds[0].events = POLLIN;
- pfds[0].revents = 0;
-
- return 0;
-}
-
-int osc_handle_revents(osc_t* o, struct pollfd *pfds, int npfds, mixer_t* x)
-{
- assert(o);
-
- if(!o->server_)
- return 0;
-
- if(pfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
- error(0, 0, "OSC: got POLLERR, POLLHUP or POLLNVAL");
- return -1;
- }
- if(!(pfds[0].revents & POLLIN))
- return 0;
-
- lo_server_recv_noblock(o->server_, 0);
-
- int ret = 0;
- slist_element_t* tmp;
- for(tmp = o->done_data_.first_; tmp; tmp = tmp->next_) {
- osc_done_data_t* d = (osc_done_data_t*)(tmp->data_);
- if(d->state_ == 0) {
- ret = mixer_switch_lang(x, d->lang_, &osc_lang_switch_done, d);
- if(ret)
- break;
-
- d->state_ = 1;
- }
- }
-
-
- return ret;
-}
diff --git a/apps/osc.h b/apps/osc.h
deleted file mode 100644
index 40210b3..0000000
--- a/apps/osc.h
+++ /dev/null
@@ -1,50 +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/>.
- */
-
-#ifndef DOLMETSCHCTL_osc_h_INCLUDED
-#define DOLMETSCHCTL_osc_h_INCLUDED
-
-#include "lo/lo.h"
-#include <poll.h>
-
-#include "slist.h"
-#include "mixer.h"
-
-typedef struct {
- lo_server server_;
- slist_t done_data_;
-} osc_t;
-
-typedef struct {
- osc_t* self_;
- int state_;
- char* lang_;
- lo_address addr_;
- lo_message msg_;
-} osc_done_data_t;
-
-int osc_init(osc_t* o, const char* port);
-int osc_get_poll_fd_count(osc_t* o);
-int osc_get_poll_fds(osc_t* o, struct pollfd *pfds, int npfds);
-int osc_handle_revents(osc_t* o, struct pollfd *pfds, int npfds, mixer_t* x);
-
-#endif
diff --git a/apps/slist.c b/apps/slist.c
deleted file mode 100644
index b10aca7..0000000
--- a/apps/slist.c
+++ /dev/null
@@ -1,123 +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 <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
deleted file mode 100644
index 70a81b5..0000000
--- a/apps/slist.h
+++ /dev/null
@@ -1,46 +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/>.
- */
-
-#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