From a609e6895a96db134697acce266e0cb94488f60b Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Mon, 20 May 2013 08:26:48 +0200 Subject: Centralise jackclient code for reuse among the jack client modules. Implement most of the jackaudio output module (probably broken atm.). --- configure.in | 20 ++-- drumgizmo/audioinputenginedl.cc | 27 +++-- drumgizmo/audioinputenginedl.h | 4 + drumgizmo/audiooutputenginedl.cc | 11 ++ drumgizmo/audiooutputenginedl.h | 4 + drumgizmo/input/jackmidi/Makefile.am | 8 +- drumgizmo/input/jackmidi/jackmidi.cc | 46 ++++--- drumgizmo/jackclient.cc | 2 + drumgizmo/jackclient.h | 6 +- drumgizmo/output/jackaudio/jackaudio.cc | 206 ++++++++++++++++++++++++++++++++ src/drumgizmo.cc | 2 +- 11 files changed, 303 insertions(+), 33 deletions(-) create mode 100644 drumgizmo/output/jackaudio/jackaudio.cc diff --git a/configure.in b/configure.in index c551c84..cb3c99a 100644 --- a/configure.in +++ b/configure.in @@ -14,6 +14,8 @@ AM_PROG_LIBTOOL AM_CONFIG_HEADER(config.h) AC_STDC_HEADERS +need_jack=no + dnl ====================== dnl Init pkg-config dnl ====================== @@ -129,10 +131,7 @@ if test "x$enable_cli" = "xyes"; then [enable_input_jackmidi="yes"]) if test "x$enable_input_jackmidi" = "xyes"; then have_input_jackmidi=yes - dnl ====================== - dnl Check for jack - dnl ====================== - PKG_CHECK_MODULES(JACK, jack >= 0.120.1) + need_jack=yes else AC_MSG_RESULT([*** input jackmidi plugin disabled per user request ***]) have_input_jackmidi=no @@ -178,10 +177,7 @@ if test "x$enable_cli" = "xyes"; then [enable_output_jackaudio="yes"]) if test "x$enable_output_jackaudio" = "xyes"; then have_output_jackaudio=yes - dnl ====================== - dnl Check for jack - dnl ====================== - PKG_CHECK_MODULES(JACK, jack >= 0.120.1) + need_jack=yes else AC_MSG_RESULT([*** output jack plugin disabled per user request ***]) have_output_jackaudio=no @@ -390,6 +386,14 @@ else AC_MSG_RESULT([*** Disabling SSE ***]) fi +if test "x$need_jack" = "xyes" +then + dnl ====================== + dnl Check for jack + dnl ====================== + PKG_CHECK_MODULES(JACK, jack >= 0.120.1) +fi + AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(CXXFLAGS) diff --git a/drumgizmo/audioinputenginedl.cc b/drumgizmo/audioinputenginedl.cc index 799e56f..e7f19c6 100644 --- a/drumgizmo/audioinputenginedl.cc +++ b/drumgizmo/audioinputenginedl.cc @@ -34,8 +34,12 @@ #include #include +#include "jackclient.h" + AudioInputEngineDL::AudioInputEngineDL(std::string name) { + is_jack_plugin = strstr(name.c_str(), "jack"); + std::string plugin = INPUT_PLUGIN_DIR"/lib" + name + ".so"; void *lib = dlopen(plugin.c_str(), RTLD_LAZY); if(!lib) { @@ -60,58 +64,66 @@ AudioInputEngineDL::AudioInputEngineDL(std::string name) i_init = (input_init_func_t) dlsym(lib, "init"); dlsym_error = dlerror(); if(dlsym_error) { - printf("Cannot load symbol destroy: %s\n", dlsym_error); + printf("Cannot load symbol init: %s\n", dlsym_error); return; } i_setparm = (input_setparm_func_t) dlsym(lib, "setparm"); dlsym_error = dlerror(); if(dlsym_error) { - printf("Cannot load symbol destroy: %s\n", dlsym_error); + printf("Cannot load symbol setparm: %s\n", dlsym_error); return; } i_start = (input_start_func_t) dlsym(lib, "start"); dlsym_error = dlerror(); if(dlsym_error) { - printf("Cannot load symbol destroy: %s\n", dlsym_error); + printf("Cannot load symbol start: %s\n", dlsym_error); return; } i_stop = (input_stop_func_t) dlsym(lib, "stop"); dlsym_error = dlerror(); if(dlsym_error) { - printf("Cannot load symbol destroy: %s\n", dlsym_error); + printf("Cannot load symbol stop: %s\n", dlsym_error); return; } i_pre = (input_pre_func_t) dlsym(lib, "pre"); dlsym_error = dlerror(); if(dlsym_error) { - printf("Cannot load symbol destroy: %s\n", dlsym_error); + printf("Cannot load symbol pre: %s\n", dlsym_error); return; } i_run = (input_run_func_t) dlsym(lib, "run"); dlsym_error = dlerror(); if(dlsym_error) { - printf("Cannot load symbol destroy: %s\n", dlsym_error); + printf("Cannot load symbol run: %s\n", dlsym_error); return; } i_post = (input_post_func_t) dlsym(lib, "post"); dlsym_error = dlerror(); if(dlsym_error) { - printf("Cannot load symbol destroy: %s\n", dlsym_error); + printf("Cannot load symbol post: %s\n", dlsym_error); return; } ptr = i_create(); + + if(is_jack_plugin) { + char ptrbuf[32]; + jackclient = init_jack_client(); + sprintf(ptrbuf, "%p", jackclient); + setParm("jack_client", ptrbuf); + } } AudioInputEngineDL::~AudioInputEngineDL() { i_destroy(ptr); + if(is_jack_plugin) close_jack_client(); } bool AudioInputEngineDL::init(Instruments &instruments) @@ -138,6 +150,7 @@ void AudioInputEngineDL::setParm(std::string parm, std::string value) bool AudioInputEngineDL::start() { + if(is_jack_plugin) jackclient->activate(); return i_start(ptr); } diff --git a/drumgizmo/audioinputenginedl.h b/drumgizmo/audioinputenginedl.h index b8829e5..ed1fb27 100644 --- a/drumgizmo/audioinputenginedl.h +++ b/drumgizmo/audioinputenginedl.h @@ -28,6 +28,7 @@ #define __DRUMGIZMO_AUDIOINPUTENGINEDL_H__ #include "audioinputengine.h" +#include "jackclient.h" typedef void* (*input_create_func_t)(void); typedef void (*input_destroy_func_t)(void*); @@ -66,6 +67,9 @@ private: input_pre_func_t i_pre; input_run_func_t i_run; input_post_func_t i_post; + + bool is_jack_plugin; + JackClient *jackclient; }; #endif/*__DRUMGIZMO_AUDIOINPUTENGINEDL_H__*/ diff --git a/drumgizmo/audiooutputenginedl.cc b/drumgizmo/audiooutputenginedl.cc index 411c14b..ad8d815 100644 --- a/drumgizmo/audiooutputenginedl.cc +++ b/drumgizmo/audiooutputenginedl.cc @@ -33,6 +33,8 @@ AudioOutputEngineDL::AudioOutputEngineDL(std::string name) { + is_jack_plugin = strstr(name.c_str(), "jack"); + std::string plugin = OUTPUT_PLUGIN_DIR"/lib" + name + ".so"; void *lib = dlopen(plugin.c_str(), RTLD_LAZY); if(!lib) { @@ -104,11 +106,19 @@ AudioOutputEngineDL::AudioOutputEngineDL(std::string name) } ptr = o_create(); + + if(is_jack_plugin) { + char ptrbuf[32]; + jackclient = init_jack_client(); + sprintf(ptrbuf, "%p", jackclient); + setParm("jack_client", ptrbuf); + } } AudioOutputEngineDL::~AudioOutputEngineDL() { o_destroy(ptr); + if(is_jack_plugin) close_jack_client(); } bool AudioOutputEngineDL::init(Channels channels) @@ -135,6 +145,7 @@ void AudioOutputEngineDL::setParm(std::string parm, std::string value) bool AudioOutputEngineDL::start() { + if(is_jack_plugin) jackclient->activate(); return o_start(ptr); } diff --git a/drumgizmo/audiooutputenginedl.h b/drumgizmo/audiooutputenginedl.h index 7faa78e..4b22131 100644 --- a/drumgizmo/audiooutputenginedl.h +++ b/drumgizmo/audiooutputenginedl.h @@ -34,6 +34,7 @@ #include "channel.h" #include "audiooutputengine.h" +#include "jackclient.h" typedef void* (*output_create_func_t)(void); typedef void (*output_destroy_func_t)(void*); @@ -72,6 +73,9 @@ private: output_pre_func_t o_pre; output_run_func_t o_run; output_post_func_t o_post; + + bool is_jack_plugin; + JackClient *jackclient; }; #endif/*__DRUMGIZMO_AUDIOOUTPUTENGINEDL_H__*/ diff --git a/drumgizmo/input/jackmidi/Makefile.am b/drumgizmo/input/jackmidi/Makefile.am index cd77a74..809ca96 100644 --- a/drumgizmo/input/jackmidi/Makefile.am +++ b/drumgizmo/input/jackmidi/Makefile.am @@ -1,6 +1,10 @@ jackmidisources = \ - jackmidi.cc + jackmidi.cc \ + $(top_srcdir)/src/midimapper.cc \ + $(top_srcdir)/src/midimapparser.cc \ + $(top_srcdir)/src/saxparser.cc \ + $(top_srcdir)/hugin/hugin.c if HAVE_INPUT_JACKMIDI @@ -20,7 +24,7 @@ lib_LTLIBRARIES = $(jackmidiltlibs) libdir = $(INPUT_PLUGIN_DIR) -AM_CPPFLAGS = -I$(top_srcdir)/include +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src -I$(top_srcdir)/hugin libjackmidi_la_LDFLAGS = libjackmidi_la_LIBADD = libjackmidi_la_SOURCES = $(jackmidibuildsources) diff --git a/drumgizmo/input/jackmidi/jackmidi.cc b/drumgizmo/input/jackmidi/jackmidi.cc index 7af257e..52c0bb8 100644 --- a/drumgizmo/input/jackmidi/jackmidi.cc +++ b/drumgizmo/input/jackmidi/jackmidi.cc @@ -30,6 +30,8 @@ #include #include +#include +#include #define NOTE_ON 0x90 @@ -65,12 +67,13 @@ private: event_t *list; size_t listsize; + + std::string midimapfile; + MidiMapper mmap; }; JackMidi::JackMidi() { - jackclient = init_jack_client(); - jackclient->addJackProcess(this); pos = 0; list = (event_t *)malloc(sizeof(event_t) * 1000); @@ -79,8 +82,6 @@ JackMidi::JackMidi() JackMidi::~JackMidi() { - jackclient->removeJackProcess(this); - close_jack_client(); } bool JackMidi::init(int instruments, char *inames[]) @@ -91,17 +92,29 @@ bool JackMidi::init(int instruments, char *inames[]) JackPortIsInput,// | JackPortIsTerminal, 0); + MidiMapParser p(midimapfile); + if(p.parse()) return false; + mmap.midimap = p.midimap; + + for(int i = 0; i < instruments; i++) { + mmap.instrmap[inames[i]] = i; + } + return true; } void JackMidi::setParm(std::string parm, std::string value) { - if(parm == "map") loadMap(value); + if(parm == "map") midimapfile = value; + if(parm == "jack_client") { + sscanf(value.c_str(), "%p", &jackclient); + if(jackclient) jackclient->addJackProcess(this); + } } bool JackMidi::start() { - jackclient->activate(); + // jackclient->activate(); return true; } @@ -124,6 +137,8 @@ event_t *JackMidi::run(size_t pos, size_t len, size_t *nevents) void JackMidi::jack_process(jack_nframes_t nframes) { + printf("i"); fflush(stdout); + void *midibuffer = jack_port_get_buffer(midi_port, nframes); jack_nframes_t midievents = jack_midi_get_event_count(midibuffer); @@ -139,13 +154,17 @@ void JackMidi::jack_process(jack_nframes_t nframes) int velocity = event.buffer[2]; printf("Event key:%d vel:%d\n", key, velocity); - - if(velocity) { - list[listsize].type = TYPE_ONSET; - list[listsize].instrument = key; - list[listsize].velocity = velocity / 127.0; - list[listsize].offset = event.time; - listsize++; + + int i = mmap.lookup(key); + if(i != -1) { + + if(velocity) { + list[listsize].type = TYPE_ONSET; + list[listsize].instrument = i; + list[listsize].velocity = velocity / 127.0; + list[listsize].offset = event.time; + listsize++; + } } } @@ -154,7 +173,6 @@ void JackMidi::jack_process(jack_nframes_t nframes) pos += nframes; } - void JackMidi::post() { } diff --git a/drumgizmo/jackclient.cc b/drumgizmo/jackclient.cc index 4fbafb5..56c9da8 100644 --- a/drumgizmo/jackclient.cc +++ b/drumgizmo/jackclient.cc @@ -47,10 +47,12 @@ JackClient::~JackClient() jack_client_close(jack_client); } +/* void JackClient::addJackProcess(JackProcess *process) { jack_processes.insert(process); } +*/ void JackClient::removeJackProcess(JackProcess *process) { diff --git a/drumgizmo/jackclient.h b/drumgizmo/jackclient.h index 636d4d0..88a733f 100644 --- a/drumgizmo/jackclient.h +++ b/drumgizmo/jackclient.h @@ -40,7 +40,11 @@ public: JackClient(); ~JackClient(); - void addJackProcess(JackProcess *process); + void addJackProcess(JackProcess *process) + { + jack_processes.insert(process); + } + void removeJackProcess(JackProcess *process); void activate(); diff --git a/drumgizmo/output/jackaudio/jackaudio.cc b/drumgizmo/output/jackaudio/jackaudio.cc new file mode 100644 index 0000000..9410915 --- /dev/null +++ b/drumgizmo/output/jackaudio/jackaudio.cc @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * jackaudio.cc + * + * Sat Apr 30 21:11:54 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include + +#include +#include + +#define NOTE_ON 0x90 + +#include "../../jackclient.h" +#include + +class JackAudio : public JackProcess { +public: + JackAudio(); + ~JackAudio(); + bool init(int channels, char *cnames[]); + + void setParm(std::string parm, std::string value); + + bool start(); + void stop(); + + void pre(size_t size); + void run(int channel, sample_t* data, size_t size); + void post(size_t size); + + void jack_process(jack_nframes_t nframes); + +private: + JackClient *jackclient; + jack_port_t *output_port[64]; + size_t nchannels; + sample_t **channels; +}; + +JackAudio::JackAudio() +{ +} + +JackAudio::~JackAudio() +{ +} + +bool JackAudio::init(int nchannels, char *cnames[]) +{ + this->nchannels = nchannels; + channels = (sample_t**)malloc(nchannels * sizeof(sample_t*)); + + for(int i = 0; i < nchannels; i++) { + char buf[32]; + sprintf(buf, "%d", i + 1); + std::string name; + name += buf; + name += "-"; + name += cnames[i]; + output_port[i] = jack_port_register(jackclient->jack_client, + name.c_str(), + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, 0); + channels[i] = (sample_t*)malloc(2048 * sizeof(sample_t)); + } + return true; +} + +void JackAudio::setParm(std::string parm, std::string value) +{ + if(parm == "jack_client") { + sscanf(value.c_str(), "%p", &jackclient); + if(jackclient) jackclient->addJackProcess(this); + } +} + +bool JackAudio::start() +{ + return true; +} + +void JackAudio::stop() +{ +} + +void JackAudio::pre(size_t size) +{ +} + +void JackAudio::run(int channel, sample_t* data, size_t size) +{ + // Copy engine data to ringbuffer. + for(int i = 0; i < size; i++) { + channels[channel][i] = data[i]; + } +} + +void JackAudio::post(size_t size) +{ +} + +void JackAudio::jack_process(jack_nframes_t nframes) +{ + printf("o"); fflush(stdout); + for(int c = 0; c < nchannels; c++) { + jack_default_audio_sample_t *out = + (jack_default_audio_sample_t *) jack_port_get_buffer(output_port[c], + nframes); + for(int i = 0; i < nframes; i++) { + out[i] = channels[c][i]; + } + } +} + +extern "C" { + void *create() + { + return new JackAudio(); + } + + void destroy(void *h) + { + JackAudio *jack = (JackAudio*)h; + delete jack; + } + + bool init(void *h, int cs, char *cnames[]) + { + JackAudio *jack = (JackAudio*)h; + return jack->init(cs, cnames); + } + + void setparm(void *h, const char *parm, const char *value) + { + JackAudio *jack = (JackAudio*)h; + jack->setParm(parm, value); + } + + bool start(void *h) + { + JackAudio *jack = (JackAudio*)h; + return jack->start(); + } + + void stop(void *h) + { + JackAudio *jack = (JackAudio*)h; + jack->stop(); + } + + void pre(void *h, size_t s) + { + JackAudio *jack = (JackAudio*)h; + jack->pre(s); + } + + void run(void *h, int ch, sample_t *data, size_t size) + { + JackAudio *jack = (JackAudio*)h; + jack->run(ch, data, size); + } + + void post(void *h, size_t s) + { + JackAudio *jack = (JackAudio*)h; + jack->post(s); + } +} + +#ifdef TEST_AUDIOINPUTENGINEJACKAUDIO +//Additional dependency files +//deps: +//Required cflags (autoconf vars may be used) +//cflags: +//Required link options (autoconf vars may be used) +//libs: +#include "test.h" + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). + +TEST_END; + +#endif/*TEST_AUDIOINPUTENGINEJACKAUDIO*/ diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index e0be30b..cb77fd4 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -389,7 +389,7 @@ void DrumGizmo::run() oe->start(); size_t pos = 0; - size_t nsamples = 512; + size_t nsamples = 2048; sample_t samples[nsamples]; while(run(pos, samples, nsamples) == true) { -- cgit v1.2.3