diff options
Diffstat (limited to 'attic/muse2-oom/muse2/muse/dssihost.cpp')
-rw-r--r-- | attic/muse2-oom/muse2/muse/dssihost.cpp | 3059 |
1 files changed, 0 insertions, 3059 deletions
diff --git a/attic/muse2-oom/muse2/muse/dssihost.cpp b/attic/muse2-oom/muse2/muse/dssihost.cpp deleted file mode 100644 index 986abea1..00000000 --- a/attic/muse2-oom/muse2/muse/dssihost.cpp +++ /dev/null @@ -1,3059 +0,0 @@ -//============================================================================= -// MusE -// Linux Music Editor -// $Id: dssihost.cpp,v 1.15.2.16 2009/12/15 03:39:58 terminator356 Exp $ -// -// Copyright (C) 2002-2006 by Werner Schweer and others -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2. -// -// This program 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 this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -//============================================================================= - -#include "config.h" -#ifdef DSSI_SUPPORT - -// Turn on debugging messages -//#define DSSI_DEBUG - -// Support vst state saving/loading with vst chunks. Requires patches to DSSI and DSSI-vst! -//#define DSSI_VST_CHUNK_SUPPORT - -#include <string.h> -#include <signal.h> -#include <dlfcn.h> -#include <stdlib.h> -#include <sys/stat.h> -//#include <dssi.h> -//#include <alsa/asoundlib.h> - -#include <QDir> -#include <QFileInfo> -#include <QMenu> - -#include "dssihost.h" -#include "synth.h" -#include "audio.h" -#include "jackaudio.h" -//#include "../driver/jackaudio.h" // p4.0.2 -#include "midi.h" -#include "midiport.h" -#include "stringparam.h" -#include "plugin.h" -//#include "al/al.h" -//#include "al/xml.h" -#include "xml.h" -#include "song.h" -//#include "midictrl.h" -//#include "ladspaplugin.h" - -#include "app.h" -#include "globals.h" -#include "globaldefs.h" -//#include "al/dsp.h" -#include "gconfig.h" - -/* -static lo_server_thread serverThread; -static char osc_path_tmp[1024]; -static char* url; - -//--------------------------------------------------------- -// oscError -//--------------------------------------------------------- - -static void oscError(int num, const char *msg, const char *path) - { - fprintf(stderr, "MusE: liblo server error %d in path %s: %s\n", - num, path, msg); - } - -//--------------------------------------------------------- -// oscDebugHandler -//--------------------------------------------------------- - -static int oscDebugHandler(const char* path, const char* types, lo_arg** argv, - int argc, void*, void*) - { - printf("MusE: got unhandled OSC message:\n path: <%s>\n", path); - for (int i = 0; i < argc; i++) { - printf(" arg %d '%c' ", i, types[i]); - lo_arg_pp(lo_type(types[i]), argv[i]); - printf("\n"); - } - return 1; - } - -//--------------------------------------------------------- -// oscUpdate -//--------------------------------------------------------- - -int DssiSynthIF::oscUpdate(lo_arg **argv) - { - const char *url = (char *)&argv[0]->s; - - if (uiTarget) - lo_address_free(uiTarget); - char* host = lo_url_get_hostname(url); - char* port = lo_url_get_port(url); - uiTarget = lo_address_new(host, port); - free(host); - free(port); - - if (uiOscPath) - free(uiOscPath); - uiOscPath = lo_url_get_path(url); - int pl = strlen(uiOscPath); - - if (uiOscControlPath) - free(uiOscControlPath); - uiOscControlPath = (char *)malloc(pl + 10); - sprintf(uiOscControlPath, "%s/control", uiOscPath); - - if (uiOscConfigurePath) - free(uiOscConfigurePath); - uiOscConfigurePath = (char *)malloc(pl + 12); - sprintf(uiOscConfigurePath, "%s/configure", uiOscPath); - - if (uiOscProgramPath) - free(uiOscProgramPath); - uiOscProgramPath = (char *)malloc(pl + 10); - sprintf(uiOscProgramPath, "%s/program", uiOscPath); - - if (uiOscShowPath) - free(uiOscShowPath); - uiOscShowPath = (char *)malloc(pl + 10); - sprintf(uiOscShowPath, "%s/show", uiOscPath); - - // At this point a more substantial host might also call - // configure() on the UI to set any state that it had remembered - // for the plugin instance. But we don't remember state for - // plugin instances (see our own configure() implementation in - // osc_configure_handler), and so we have nothing to send except - // the optional project directory. - - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::oscUpdate synth name:%s url:%s uiTarget:%p uiOscPath:%s uiOscConfigurePath:%s museProject:%s\n", synti->name().ascii(), url, uiTarget, uiOscPath, uiOscConfigurePath, museProject.ascii()); - #endif - - //lo_send(uiTarget, uiOscConfigurePath, "ss", - //DSSI_PROJECT_DIRECTORY_KEY, song->projectPath().toAscii().data()); - lo_send(uiTarget, uiOscConfigurePath, "ss", - DSSI_PROJECT_DIRECTORY_KEY, museProject.ascii()); - -#if 0 - // Send current bank/program (-FIX- another race...) - if (instance->pendingProgramChange < 0) { - unsigned long bank = instance->currentBank; - unsigned long program = instance->currentProgram; - instance->uiNeedsProgramUpdate = 0; - if (instance->uiTarget) { - lo_send(instance->uiTarget, instance->ui_osc_program_path, "ii", bank, program); - } - } - - // Send control ports - for (i = 0; i < instance->plugin->controlIns; i++) { - int in = i + instance->firstControlIn; - int port = pluginControlInPortNumbers[in]; - lo_send(instance->uiTarget, instance->ui_osc_control_path, "if", port, - pluginControlIns[in]); - // Avoid overloading the GUI if there are lots and lots of ports - if ((i+1) % 50 == 0) - usleep(300000); - } -#endif - return 0; - } - -//--------------------------------------------------------- -// oscMessageHandler -//--------------------------------------------------------- - -int oscMessageHandler(const char* path, const char* types, lo_arg** argv, - int argc, void* data, void* user_data) - { - const char* p = path; - - #ifdef DSSI_DEBUG - if(argc) - { - printf("oscMessageHandler: path:%s argc:%d\n", path, argc); - for(int i = 0; i < argc; ++i) - { - printf(" "); - lo_arg_pp((lo_type)types[i], argv[i]); - } - printf("\n"); - } - else - { - printf("%s\n", path); - printf("oscMessageHandler: no args, path:%s\n", path); - } - #endif - - if (strncmp(p, "/dssi/", 6)) - return oscDebugHandler(path, types, argv, argc, data, user_data); - - p += 6; - //p = strrchr(p, "/"); - - SynthIList* sl = song->syntis(); - DssiSynthIF* instance = 0; - SynthI* synti = 0; - - #ifdef DSSI_DEBUG - fprintf(stderr, "oscMessageHandler: song->syntis() size:%d\n", sl->size()); - #endif - - for(int retry = 0; retry < 5; ++retry) - { - #ifdef DSSI_DEBUG - fprintf(stderr, "oscMessageHandler: search retry number:%d ...\n", retry); - #endif - - //if(uiOscPath) - // break; - - for(iSynthI si = sl->begin(); si != sl->end(); ++si) - { - #ifdef DSSI_DEBUG - fprintf(stderr, "oscMessageHandler: searching for synth p:%s: checking instances:%s\n", p, (*si)->name().ascii()); - #endif - - //int l = strlen((*si)->name().toAscii().data()); - //if (!strncmp(p, (*si)->name().toAscii().data(), l)) { - //int l = strlen((*si)->name().ascii()); - const char* sub = strstr(p, (*si)->name().ascii()); - - //if(!strncmp(p, (*si)->name().ascii(), l)) - if(sub != NULL) - { - synti = *si; - instance = (DssiSynthIF*)(synti->sif()); - - //p += l; - p = sub + strlen((*si)->name().ascii()); - - break; - } - } - if(instance) - break; - - sleep(1); - } - - if(!instance) - { - fprintf(stderr, "oscMessageHandler: error: no instance\n"); - return oscDebugHandler(path, types, argv, argc, data, user_data); - } - - if (*p != '/' || *(p + 1) == 0) - { - fprintf(stderr, "oscMessageHandler: error: end or no /\n"); - return oscDebugHandler(path, types, argv, argc, data, user_data); - } - - ++p; - - #ifdef DSSI_DEBUG - fprintf(stderr, "oscMessageHandler: method:%s\n", p); - #endif - - if (!strcmp(p, "configure") && argc == 2 && !strcmp(types, "ss")) - return instance->oscConfigure(argv); - else if (!strcmp(p, "control") && argc == 2 && !strcmp(types, "if")) - return instance->oscControl(argv); - else if (!strcmp(p, "midi") && argc == 1 && !strcmp(types, "m")) - return instance->oscMidi(argv); - else if (!strcmp(p, "program") && argc == 2 && !strcmp(types, "ii")) - return instance->oscProgram(argv); - else if (!strcmp(p, "update") && argc == 1 && !strcmp(types, "s")) - return instance->oscUpdate(argv); - else if (!strcmp(p, "exiting") && argc == 0) - return instance->oscExiting(argv); - return oscDebugHandler(path, types, argv, argc, data, user_data); - } -*/ - -//--------------------------------------------------------- -// scanDSSILib -//--------------------------------------------------------- - -static void scanDSSILib(QFileInfo& fi) // ddskrjo removed const for argument - { - //void* handle = dlopen(fi.filePath().toAscii().data(), RTLD_NOW); - void* handle = dlopen(fi.filePath().toLatin1().constData(), RTLD_NOW); - //void* handle = dlopen(fi.absFilePath().toLatin1().constData(), RTLD_NOW); - - if (handle == 0) { - fprintf(stderr, "scanDSSILib: dlopen(%s) failed: %s\n", - //fi.filePath().toAscii().data(), dlerror()); - fi.filePath().toLatin1().constData(), dlerror()); - //fi.absFilePath().toLatin1().constData(), dlerror()); - - return; - } - DSSI_Descriptor_Function dssi = (DSSI_Descriptor_Function)dlsym(handle, "dssi_descriptor"); - - if (!dssi) - { - /* - const char *txt = dlerror(); - if (txt) - { - fprintf(stderr, - "Unable to find dssi_descriptor() function in plugin " - "library file \"%s\": %s.\n" - "Are you sure this is a DSSI plugin file?\n", - //fi.filePath().toAscii().data(), - fi.filePath().ascii(), - //fi.absFilePath().toLatin1().constData(), - - txt); - dlclose(handle); - exit(1); - } - */ - dlclose(handle); - return; - } - else - { - //const DSSI_Descriptor* descr; - for (int i = 0;; ++i) - { - const DSSI_Descriptor* descr; - - // CRAPPY PLUGIN ALERT: - // Out of many plugins, with several, Valgrind says something in here is allocated with new. - descr = dssi(i); - if (descr == 0) - break; - - #ifdef DSSI_DEBUG - fprintf(stderr, "scanDSSILib: name:%s inPlaceBroken:%d\n", descr->LADSPA_Plugin->Name, LADSPA_IS_INPLACE_BROKEN(descr->LADSPA_Plugin->Properties)); - #endif - - // Listing synths only while excluding effect plugins: - // Do the exact opposite of what dssi-vst.cpp does for listing ladspa plugins. - // That way we cover all bases - effect plugins and synths. - // Non-synths will show up in the ladspa effect dialog, while synths will show up here... - // There should be nothing left out... - if(descr->run_synth || - descr->run_synth_adding || - descr->run_multiple_synths || - descr->run_multiple_synths_adding) - - { - const QString label(descr->LADSPA_Plugin->Label); - - // Make sure it doesn't already exist. - std::vector<Synth*>::iterator is; - for(is = synthis.begin(); is != synthis.end(); ++is) - { - Synth* s = *is; - //#ifdef DSSI_DEBUG - // fprintf(stderr, "scanDSSILib: name:%s listname:%s lib:%s listlib:%s\n", - // label.toLatin1().constData(), s->name().toLatin1().constData(), fi.baseName(true).toLatin1().constData(), s->baseName().toLatin1().constData()); - //#endif - - if(s->name() == label && s->baseName() == fi.completeBaseName()) - break; - } - if(is != synthis.end()) - continue; - - DssiSynth* s = new DssiSynth(fi, descr); - - if(debugMsg) - { - fprintf(stderr, "scanDSSILib: name:%s listname:%s lib:%s listlib:%s\n", - label.toLatin1().constData(), s->name().toLatin1().constData(), fi.completeBaseName().toLatin1().constData(), s->baseName().toLatin1().constData()); - int ai = 0, ao = 0, ci = 0, co = 0; - for(unsigned long pt = 0; pt < descr->LADSPA_Plugin->PortCount; ++pt) - { - LADSPA_PortDescriptor pd = descr->LADSPA_Plugin->PortDescriptors[pt]; - if(LADSPA_IS_PORT_INPUT(pd) && LADSPA_IS_PORT_AUDIO(pd)) - ai++; - else - if(LADSPA_IS_PORT_OUTPUT(pd) && LADSPA_IS_PORT_AUDIO(pd)) - ao++; - else - if(LADSPA_IS_PORT_INPUT(pd) && LADSPA_IS_PORT_CONTROL(pd)) - ci++; - else - if(LADSPA_IS_PORT_OUTPUT(pd) && LADSPA_IS_PORT_CONTROL(pd)) - co++; - } - fprintf(stderr, "audio ins:%d outs:%d control ins:%d outs:%d\n", ai, ao, ci, co); - } - - synthis.push_back(s); - } - else - { - // NOTE: Just a test - //QFileInfo ffi(fi); - //plugins.add(&ffi, LADSPA_Descriptor_Function(NULL), descr->LADSPA_Plugin, false); - //plugins.add(&ffi, descr, false); - } - } - } - dlclose(handle); - } - -//--------------------------------------------------------- -// scanVstDir -//--------------------------------------------------------- - -static void scanDSSIDir(QString& s) // ddskrjo removed const for argument -{ - if(debugMsg) - //printf("scan DSSI plugin dir <%s>\n", s.toAscii().data()); - printf("scanDSSIDir: scan DSSI plugin dir <%s>\n", s.toLatin1().constData()); - -#ifdef __APPLE__ - QDir pluginDir(s, QString("*.dylib"), QDir::Unsorted, QDir::Files); -#else - QDir pluginDir(s, QString("*.so"), QDir::Unsorted, QDir::Files); -#endif - if(!pluginDir.exists()) - return; - - //const QFileInfoList list = pluginDir.entryInfoList(); - //for (int i = 0; i < list.size(); ++i) { - //QFileInfo fi = list.at(i); - //scanDSSILib(fi); - //} - - QStringList list = pluginDir.entryList(); - for(int i = 0; i < list.count(); ++i) - { - if(debugMsg) - printf("scanDSSIDir: found %s\n", (s + QString("/") + list[i]).toLatin1().constData()); - - QFileInfo fi(s + QString("/") + list[i]); - scanDSSILib(fi); - } -} - -//--------------------------------------------------------- -// initDSSI -//--------------------------------------------------------- - -void initDSSI() - { - const char* dssiPath = getenv("DSSI_PATH"); - if (dssiPath == 0) - dssiPath = "/usr/local/lib64/dssi:/usr/lib64/dssi:/usr/local/lib/dssi:/usr/lib/dssi"; - - //const char* ladspaPath = getenv("LADSPA_PATH"); - //if (ladspaPath == 0) - // ladspaPath = "/usr/local/lib64/ladspa:/usr/lib64/ladspa:/usr/local/lib/ladspa:/usr/lib/ladspa"; - - const char* p = dssiPath; - //QString pth = QString(dssiPath) + QString(":") + QString(ladspaPath); - //const char* p = pth.toLatin1().constData(); - while (*p != '\0') { - const char* pe = p; - while (*pe != ':' && *pe != '\0') - pe++; - - int n = pe - p; - if (n) { - char* buffer = new char[n + 1]; - strncpy(buffer, p, n); - buffer[n] = '\0'; - QString tmpStr(buffer); - scanDSSIDir(tmpStr); - delete[] buffer; - } - p = pe; - if (*p == ':') - p++; - } - - // Create OSC thread - //serverThread = lo_server_thread_new(0, oscError); - //snprintf(osc_path_tmp, 31, "/dssi"); - //char* tmp = lo_server_thread_get_url(serverThread); - //url = (char *)malloc(strlen(tmp) + strlen(osc_path_tmp)); - //sprintf(url, "%s%s", tmp, osc_path_tmp + 1); - //free(tmp); - //lo_server_thread_add_method(serverThread, 0, 0, oscMessageHandler, 0); - //lo_server_thread_start(serverThread); - } - -//--------------------------------------------------------- -// DssiSynth -// Synth.label = plug.Label -// Synth.descr = plug.Name -// Synth.maker = plug.maker -// Synth.version = nil (no such field in ladspa, maybe try copyright instead) -//--------------------------------------------------------- - -DssiSynth::DssiSynth(QFileInfo& fi, const DSSI_Descriptor* d) : // ddskrjo removed const from QFileInfo - //Synth(fi, label, descr, maker, ver) - Synth(fi, QString(d->LADSPA_Plugin->Label), QString(d->LADSPA_Plugin->Name), QString(d->LADSPA_Plugin->Maker), QString()) -{ - df = 0; - handle = 0; - dssi = 0; - _hasGui = false; - - const LADSPA_Descriptor* descr = d->LADSPA_Plugin; - - _portCount = descr->PortCount; - //_portDescriptors = 0; - //if(_portCount) - // _portDescriptors = new LADSPA_PortDescriptor[_portCount]; - - _inports = 0; - _outports = 0; - _controlInPorts = 0; - _controlOutPorts = 0; - for(unsigned long k = 0; k < _portCount; ++k) - { - LADSPA_PortDescriptor pd = descr->PortDescriptors[k]; - //_portDescriptors[k] = pd; - if(pd & LADSPA_PORT_AUDIO) - { - if(pd & LADSPA_PORT_INPUT) - ++_inports; - else - if(pd & LADSPA_PORT_OUTPUT) - ++_outports; - } - else - if(pd & LADSPA_PORT_CONTROL) - { - if(pd & LADSPA_PORT_INPUT) - ++_controlInPorts; - else - if(pd & LADSPA_PORT_OUTPUT) - ++_controlOutPorts; - } - } - - _inPlaceCapable = !LADSPA_IS_INPLACE_BROKEN(descr->Properties); - - // Blacklist vst plugins in-place configurable for now. - if ((_inports != _outports) || (fi.completeBaseName() == QString("dssi-vst") && !config.vstInPlace)) - _inPlaceCapable = false; -} - -DssiSynth::~DssiSynth() -{ - -} - -//--------------------------------------------------------- -// createSIF -//--------------------------------------------------------- - -SynthIF* DssiSynth::createSIF(SynthI* synti) -{ - if (_instances == 0) - { - //handle = dlopen(info.filePath().toAscii().data(), RTLD_NOW); - handle = dlopen(info.filePath().toLatin1().constData(), RTLD_NOW); - //handle = dlopen(info.absFilePath().toLatin1().constData(), RTLD_NOW); - - if (handle == 0) - { - fprintf(stderr, "DssiSynth::createSIF dlopen(%s) failed: %s\n", - //info.filePath().toAscii().data(), dlerror()); - info.filePath().toLatin1().constData(), dlerror()); - //info.absFilePath().toLatin1().constData(), dlerror()); - - return 0; - } - df = (DSSI_Descriptor_Function)dlsym(handle, "dssi_descriptor"); - - if (!df) { - const char *txt = dlerror(); - fprintf(stderr, - "Unable to find dssi_descriptor() function in plugin " - "library file \"%s\": %s.\n" - "Are you sure this is a DSSI plugin file?\n", - //info.filePath().toAscii().data(), - info.filePath().toLatin1().constData(), - //info.absFilePath().toLatin1().constData(), - - txt ? txt : "?"); - dlclose(handle); - handle = 0; - return 0; - } - for (int i = 0;; ++i) - { - dssi = df(i); - if (dssi == 0) - break; - QString label(dssi->LADSPA_Plugin->Label); - if (label == _name) - break; - } - - if(dssi != 0) - { - _inports = 0; - _outports = 0; - _controlInPorts = 0; - _controlOutPorts = 0; - - pIdx.clear(); - opIdx.clear(); - iIdx.clear(); - oIdx.clear(); - rpIdx.clear(); - iUsedIdx.clear(); - midiCtl2PortMap.clear(); - port2MidiCtlMap.clear(); - //synti->_guiUpdateControls.clear(); - - const LADSPA_Descriptor* descr = dssi->LADSPA_Plugin; - //#ifdef DSSI_DEBUG - // printf("DssiSynth::createSIF ladspa plugin PortCount:%lu\n", d->PortCount); - //#endif - - _portCount = descr->PortCount; - - for (unsigned long k = 0; k < _portCount; ++k) - { - LADSPA_PortDescriptor pd = descr->PortDescriptors[k]; - - #ifdef DSSI_DEBUG - printf("DssiSynth::createSIF ladspa plugin Port:%ld Name:%s descriptor:%x\n", k, descr->PortNames[k], pd); - #endif - - if (LADSPA_IS_PORT_AUDIO(pd)) - { - if (LADSPA_IS_PORT_INPUT(pd)) - { - ++_inports; - iIdx.push_back(k); - iUsedIdx.push_back(false); // Start out with all false. - } - else if (LADSPA_IS_PORT_OUTPUT(pd)) - { - ++_outports; - oIdx.push_back(k); - } - - rpIdx.push_back((unsigned long)-1); - } - else if (LADSPA_IS_PORT_CONTROL(pd)) - { - if (LADSPA_IS_PORT_INPUT(pd)) - { - rpIdx.push_back(_controlInPorts); - ++_controlInPorts; - pIdx.push_back(k); - // Set to false at first. - //synti->_guiUpdateControls.push_back(false); - } - else if (LADSPA_IS_PORT_OUTPUT(pd)) - { - rpIdx.push_back((unsigned long)-1); - ++_controlOutPorts; - opIdx.push_back(k); - } - } - } - - _inPlaceCapable = !LADSPA_IS_INPLACE_BROKEN(descr->Properties); - // Blacklist vst plugins in-place configurable for now. - if((_inports != _outports) || (info.completeBaseName() == QString("dssi-vst") && !config.vstInPlace)) - _inPlaceCapable = false; - } - } - - if (dssi == 0) - { - //fprintf(stderr, "cannot found DSSI synti %s\n", _name.toAscii().data()); - fprintf(stderr, "cannot find DSSI synti %s\n", _name.toLatin1().constData()); - dlclose(handle); - handle = 0; - df = 0; - return 0; - } - - DssiSynthIF* sif = new DssiSynthIF(synti); - ++_instances; - sif->init(this); - - //_plugin->incInstances(1); - - - -// static char oscUrl[1024]; - //snprintf(oscUrl, 1024, "%s/%s", url, synti->name().toAscii().data()); - //snprintf(oscUrl, 1024, "%s/%s", url, synti->name().toLatin1().constData()); -// snprintf(oscUrl, 1024, "%s/%s/%s", url, info.baseName().toLatin1().constData(), synti->name().toLatin1().constData()); - //QString guiPath(info.path() + "/" + info.baseName()); - QString guiPath(info.path() + "/" + info.baseName()); - QDir guiDir(guiPath, "*", QDir::Unsorted, QDir::Files); - _hasGui = guiDir.exists(); - - //sif->initGui(); - - return sif; -} - -//--------------------------------------------------------- -// guiVisible -//--------------------------------------------------------- - -bool DssiSynthIF::guiVisible() const - { - //return _guiVisible; - #ifdef OSC_SUPPORT - return _oscif.oscGuiVisible(); - #endif - return false; - } - -//--------------------------------------------------------- -// showGui -//--------------------------------------------------------- - -void DssiSynthIF::showGui(bool v) - { - #ifdef OSC_SUPPORT - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::showGui(): v:%d visible:%d\n", v, guiVisible()); - #endif - - _oscif.oscShowGui(v); - - #endif // OSC_SUPPORT - - /* - if (v == guiVisible()) - return; - - //if(guiPid == -1) - if((guiQProc == 0) || (!guiQProc->isRunning())) - { - // We need an indicator that update was called - update must have been called to get new path etc... - // If the process is not running this path is invalid, right? - if(uiOscPath) - free(uiOscPath); - uiOscPath = 0; - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::showGui(): No QProcess or process not running. Starting gui...\n"); - #endif - - initGui(); - } - - //for (int i = 0; i < 5; ++i) { - for (int i = 0; i < 10; ++i) { // Give it a wee bit more time? - if (uiOscPath) - break; - sleep(1); - } - if (uiOscPath == 0) { - printf("DssiSynthIF::showGui(): no uiOscPath. Error: Timeout - synth gui did not start within 10 seconds.\n"); - return; - } - - char uiOscGuiPath[strlen(uiOscPath)+6]; - sprintf(uiOscGuiPath, "%s/%s", uiOscPath, v ? "show" : "hide"); - #ifdef DSSI_DEBUG - printf("DssiSynthIF::showGui(): Sending show/hide uiOscGuiPath:%s\n", uiOscGuiPath); - #endif - - lo_send(uiTarget, uiOscGuiPath, ""); - _guiVisible = v; - */ - } - -//--------------------------------------------------------- -// receiveEvent -//--------------------------------------------------------- - -//MidiEvent DssiSynthIF::receiveEvent() -// { -// return MidiEvent(); -// } -MidiPlayEvent DssiSynthIF::receiveEvent() - { - return MidiPlayEvent(); - } - -//--------------------------------------------------------- -// init -//--------------------------------------------------------- - -bool DssiSynthIF::init(DssiSynth* s) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init\n"); - #endif - - synth = s; - const DSSI_Descriptor* dssi = synth->dssi; - const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin; - handle = ld->instantiate(ld, sampleRate); - - #ifdef OSC_SUPPORT - _oscif.oscSetSynthIF(this); - #endif - - queryPrograms(); - - int inports = synth->_inports; - if(inports != 0) - { - audioInBuffers = new float*[inports]; - for(int k = 0; k < inports; ++k) - { - //audioInBuffers[k] = new LADSPA_Data[segmentSize]; - //posix_memalign((void**)(audioInBuffers + k), 16, sizeof(float) * segmentSize); - posix_memalign((void**)&audioInBuffers[k], 16, sizeof(float) * segmentSize); - memset(audioInBuffers[k], 0, sizeof(float) * segmentSize); - ld->connect_port(handle, synth->iIdx[k], audioInBuffers[k]); - } - } - - int outports = synth->_outports; - if(outports != 0) - { - audioOutBuffers = new float*[outports]; - for(int k = 0; k < outports; ++k) - { - //audioOutBuffers[k] = new LADSPA_Data[segmentSize]; - //posix_memalign((void**)(audioOutBuffers + k), 16, sizeof(float) * segmentSize); - posix_memalign((void**)&audioOutBuffers[k], 16, sizeof(float) * segmentSize); - memset(audioOutBuffers[k], 0, sizeof(float) * segmentSize); - ld->connect_port(handle, synth->oIdx[k], audioOutBuffers[k]); - //printf("DssiSynthIF::init output port name: %s\n", ld->PortNames[synth->oIdx[k]]); // out1, out2, out3 etc - } - } - - int controlPorts = synth->_controlInPorts; - int controlOutPorts = synth->_controlOutPorts; - - if(controlPorts != 0) - controls = new Port[controlPorts]; - else - controls = 0; - - if(controlOutPorts != 0) - controlsOut = new Port[controlOutPorts]; - else - controlsOut = 0; - - synth->midiCtl2PortMap.clear(); - synth->port2MidiCtlMap.clear(); - synti->_guiUpdateControls.clear(); - synti->_guiUpdateProgram = false; - - for (int k = 0; k < controlPorts; ++k) { - int i = synth->pIdx[k]; - //controls[k].val = ladspaDefaultValue(ld, i); - ladspaDefaultValue(ld, i, &controls[k].val); - - // Set to false at first. - synti->_guiUpdateControls.push_back(false); - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init control port:%d port idx:%d name:%s\n", k, i, ld->PortNames[i]); - #endif - - // This code is duplicated in ::getControllerInfo() - // - - int ctlnum = DSSI_NONE; - if(dssi->get_midi_controller_for_port) - ctlnum = dssi->get_midi_controller_for_port(handle, i); - - // No controller number? Try to give it a unique one... - if(ctlnum == DSSI_NONE) - { - // FIXME: Be more careful. Must make sure to pick numbers not already chosen or which WILL BE chosen. - // Simple but flawed solution: Start them at 0x60000 + 0x2000 = 0x62000. Max NRPN number is 0x3fff. - // TODO: Update: Actually we want to try to use CC Controller7 controllers if possible (or a choice) because what if - // the user's controller hardware doesn't support RPN? - // If CC Controller7 is chosen we must make sure to use only non-common numbers. An already limited range - // of 127 now becomes narrower. See the cool document midi-controllers.txt in the DSSI source for a - // nice roundup of numbers and how to choose them and how they relate to synths and DSSI synths etc. ! - ctlnum = CTRL_NRPN14_OFFSET + 0x2000 + k; - } - else - { - int c = ctlnum; - // Can be both CC and NRPN! Prefer CC over NRPN. - if(DSSI_IS_CC(ctlnum)) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init is CC control\n"); - #endif - - ctlnum = DSSI_CC_NUMBER(c); - #ifdef DSSI_DEBUG - if(DSSI_IS_NRPN(ctlnum)) - printf("DssiSynthIF::init is also NRPN control. Using CC.\n"); - #endif - } - else - if(DSSI_IS_NRPN(ctlnum)) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init is NRPN control\n"); - #endif - - ctlnum = DSSI_NRPN_NUMBER(c) + CTRL_NRPN14_OFFSET; - } - - } - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init inserting to midiCtl2PortMap: ctlnum:%d k:%d\n", ctlnum, k); - #endif - - // We have a controller number! Insert it and the DSSI port number into both maps. - synth->midiCtl2PortMap.insert(std::pair<int, int>(ctlnum, k)); - synth->port2MidiCtlMap.insert(std::pair<int, int>(k, ctlnum)); - ld->connect_port(handle, i, &controls[k].val); - } - - for (int k = 0; k < controlOutPorts; ++k) { - int i = synth->opIdx[k]; - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init control output port:%d port idx:%d name:%s\n", k, i, ld->PortNames[i]); - #endif - - // p3.3.39 Removed. - /* - - //controls[k].val = ladspaDefaultValue(ld, i); - ladspaDefaultValue(ld, i, &controlsOut[k].val); - - // This code is duplicated in ::getControllerInfo() - // - - int ctlnum = DSSI_NONE; - if(dssi->get_midi_controller_for_port) - ctlnum = dssi->get_midi_controller_for_port(handle, i); - - // No controller number? Try to give it a unique one... - if(ctlnum == DSSI_NONE) - { - // FIXME: Be more careful. Must make sure to pick numbers not already chosen or which WILL BE chosen. - // Simple but flawed solution: Start them at 0x60000 + 0x3000 = 0x63000. Max NRPN number is 0x3fff. - // TODO: CC etc. etc. - ctlnum = CTRL_NRPN14_OFFSET + 0x3000 + k; - } - else - { - int c = ctlnum; - // Can be both CC and NRPN! Prefer CC over NRPN. - if(DSSI_IS_CC(ctlnum)) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init is CC control\n"); - #endif - - ctlnum = DSSI_CC_NUMBER(c); - - #ifdef DSSI_DEBUG - if(DSSI_IS_NRPN(ctlnum)) - printf("DssiSynthIF::init is also NRPN control. Using CC.\n"); - #endif - } - else - if(DSSI_IS_NRPN(ctlnum)) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init is NRPN control\n"); - #endif - - ctlnum = DSSI_NRPN_NUMBER(c) + CTRL_NRPN14_OFFSET; - } - - } - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init inserting to midiCtl2PortMap: ctlnum:%d k:%d\n", ctlnum, k); - #endif - - // We have a controller number! Insert it and the DSSI port number into the map. - // p3.3.39 Removed. Doesn't say whether it's in or out! Don't need this for now. - //synth->midiCtl2PortMap.insert(std::pair<int, int>(ctlnum, k)); - - */ - - // - Control outs are not handled but still must be connected to something. - ld->connect_port(handle, i, &controlsOut[k].val); - } - - // Set the latency to zero. - //controls[controlPorts].val = 0.0; - // Insert a controller for latency and the DSSI port number into the map. - //synth->midiCtl2PortMap.insert(std::pair<int, int>(CTRL_NRPN14_OFFSET + 0x2000, controlPorts)); - // Connect the port. - //ld->connect_port(handle, controlPorts, &controls[controlPorts].val); - - // Just a test. It works! We can instantiate a ladspa plugin for the synth. But it needs more work... - //plugins.add(&synth->info, LADSPA_Descriptor_Function(NULL), ld, false); - - if (ld->activate) - ld->activate(handle); - - // Set current configuration values. - if(dssi->configure) - { - char *rv = dssi->configure(handle, DSSI_PROJECT_DIRECTORY_KEY, - museProject.toLatin1().constData()); //song->projectPath() - - if(rv) - { - fprintf(stderr, "MusE: Warning: plugin doesn't like project directory: \"%s\"\n", rv); - free(rv); - } - - for(ciStringParamMap r = synti->_stringParamMap.begin(); r != synti->_stringParamMap.end(); ++r) - { - rv = 0; - rv = dssi->configure(handle, r->first.c_str(), r->second.c_str()); - if(rv) - { - fprintf(stderr, "MusE: Warning: plugin config key: %s value: %s \"%s\"\n", r->first.c_str(), r->second.c_str(), rv); - free(rv); - } - } - } - - // Set current program. - if(dssi->select_program) - dssi->select_program(handle, synti->_curBankL, synti->_curProgram); - - // - // For stored initial control values, let SynthI::initInstance() take care of that via ::setParameter(). - // - - return true; - } - -//--------------------------------------------------------- -// DssiSynthIF -//--------------------------------------------------------- - -DssiSynthIF::DssiSynthIF(SynthI* s) - : SynthIF(s) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::DssiSynthIF\n"); - #endif - - synth = 0; - handle = NULL; - controls = 0; - controlsOut = 0; - - //_curBank = 0; - //_curProgram = 0; - - //#ifdef OSC_SUPPORT - //_oscif.setSynthIF(this); - //#endif - - //_guiVisible = false; - //uiTarget = 0; - //uiOscShowPath = 0; - //uiOscControlPath = 0; - //uiOscConfigurePath = 0; - //uiOscProgramPath = 0; - //uiOscPath = 0; - //guiPid = -1; - //guiQProc = 0; - - audioInBuffers = 0; - audioOutBuffers = 0; - } - -//--------------------------------------------------------- -// ~DssiSynthIF -//--------------------------------------------------------- - -DssiSynthIF::~DssiSynthIF() -{ - #ifdef DSSI_DEBUG - printf("DssiSynthIF::~DssiSynthIF\n"); - #endif - - if(synth) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::~DssiSynthIF synth:%p\n", synth); - #endif - - if(synth->dssi) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::~DssiSynthIF synth->dssi:%p\n", synth->dssi); - #endif - - if(synth->dssi->LADSPA_Plugin) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::~DssiSynthIFsynth->dssi->LADSPA_Plugin:%p\n", synth->dssi->LADSPA_Plugin); - #endif - } - } - } - - if(synth && synth->dssi && synth->dssi->LADSPA_Plugin) - { - const DSSI_Descriptor* dssi = synth->dssi; - const LADSPA_Descriptor* descr = dssi->LADSPA_Plugin; - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::~DssiSynthIF checking cleanup function exists\n"); - #endif - - if(descr->cleanup) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::~DssiSynthIF calling cleanup function\n"); - #endif - - descr->cleanup(handle); - } - } - - /* - //if (guiPid != -1) - // kill(guiPid, SIGHUP); - if(guiQProc) - { - if(guiQProc->isRunning()) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::~DssiSynthIF killing guiQProc\n"); - #endif - - guiQProc->kill(); - } - - //delete guiQProc; - } - - if(uiOscShowPath) - free(uiOscShowPath); - if(uiOscControlPath) - free(uiOscControlPath); - if(uiOscConfigurePath) - free(uiOscConfigurePath); - if(uiOscProgramPath) - free(uiOscProgramPath); - if(uiOscPath) - free(uiOscPath); - if(uiTarget) - lo_address_free(uiTarget); - */ - - if(audioInBuffers) - { - //for(int i = 0; i < synth->_inports; ++i) - //{ - // if(audioInBuffers[i]) - // delete[] audioInBuffers[i]; - //} - for(unsigned long i = 0; i < synth->_inports; ++i) - { - if(audioInBuffers[i]) - free(audioInBuffers[i]); - } - delete[] audioInBuffers; - } - - if(audioOutBuffers) - { - //for(int i = 0; i < synth->_outports; ++i) - //{ - // if(audioOutBuffers[i]) - // delete[] audioOutBuffers[i]; - //} - for(unsigned long i = 0; i < synth->_outports; ++i) - { - if(audioOutBuffers[i]) - free(audioOutBuffers[i]); - } - delete[] audioOutBuffers; - } - - if(controls) - delete[] controls; - - if(controlsOut) - delete[] controlsOut; -} - -//--------------------------------------------------------- -// getParameter -//--------------------------------------------------------- - -float DssiSynthIF::getParameter(unsigned long n) const -{ - if(n >= synth->_controlInPorts) - { - printf("DssiSynthIF::getParameter param number %ld out of range of ports:%ld\n", n, synth->_controlInPorts); - return 0.0; - } - - if(!controls) - return 0.0; - - return controls[n].val; -} - -//--------------------------------------------------------- -// setParameter -//--------------------------------------------------------- - -void DssiSynthIF::setParameter(unsigned long n, float v) -{ - if(n >= synth->_controlInPorts) - { - printf("DssiSynthIF::setParameter param number %ld out of range of ports:%ld\n", n, synth->_controlInPorts); - return; - } - - if(!controls) - return; - - controls[n].val = v; - - // Notify that changes are to be sent upon heartbeat. - // TODO: No, at least not for now. So far, setParameter is only called during loading of stored params, - // and we don't want this interfering with oscUpdate which also sends the values. - //synti->_guiUpdateControls[n] = true; -} - -//--------------------------------------------------------- -// write -//--------------------------------------------------------- - -//void DssiSynthIF::write(Xml&) const -void DssiSynthIF::write(int level, Xml& xml) const -{ - //bool vstsaved = false; - -#ifdef DSSI_VST_CHUNK_SUPPORT - //--------------------------------------------- - // dump current state of synth - //--------------------------------------------- - printf("dumping DSSI custom data! %d\n", synth->dssi->getCustomData); - - // this is only needed and supported if - // we are talking to a VST plugin at the other end. - std::string name = synth->dssi->LADSPA_Plugin->Name; - if ((name.length()> 4) && name.substr(name.length() - 4) == " VST") - { - printf("is vst plugin, commencing data dump, apiversion=%d!\n", synth->dssi->DSSI_API_Version); - unsigned long len = 0; - void* p = 0; - synth->dssi->getCustomData(handle,&p, &len); - if (len) { - xml.tag(level++, "midistate"); - xml.nput(level++, "<event type=\"%d\"", Sysex); - xml.nput(" datalen=\"%d\">\n", len+7 /*VSTSAVE*/); - xml.nput(level, ""); - xml.nput("56 53 54 53 41 56 45 "); // embed a save marker "string 'VSTSAVE' - for (long unsigned int i = 0; i < len; ++i) { - if (i && (((i+7) % 16) == 0)) { - xml.nput("\n"); - xml.nput(level, ""); - } - xml.nput("%02x ", ((char*)(p))[i] & 0xff); - } - xml.nput("\n"); - xml.tag(level--, "/event"); - xml.etag(level--, "midistate"); - //vstsaved = true; - } - } -#else - printf("support for vst chunks not compiled in!\n"); -#endif - - /* - // p3.3.39 Store the state of current program and bank and all input control values, but only if VSTSAVE above didn't do it already! - // TODO: Not quite good enough, we would want to store all controls for EACH program, not just the current one. - // Need to modify controls array to be inside a program array and act as a cache when the user changes a control on a particular program. - if(!vstsaved) - { - if(synth->_controlInPorts) - { - // TODO: Hmm, what if these sizes change (platform etc.)? Hard code? Not good - need to store complete value. - const int fs = sizeof(float); - const int uls = sizeof(unsigned long); - - // Data length: Version major and minor bytes, bank + program, and controllers. - const unsigned long len = 2 + 2 * uls + synth->_controlInPorts * fs; - - unsigned long prog = _curBank; - unsigned long bnk = _curProgram; - - xml.tag(level++, "midistate"); - xml.nput(level++, "<event type=\"%d\"", Sysex); - xml.nput(" datalen=\"%d\">\n", len+9); // "PARAMSAVE" length + data length. - xml.nput(level, ""); - xml.nput("50 41 52 41 4d 53 41 56 45 "); // Embed a save marker string "PARAMSAVE". - - unsigned long i = 9; - - // Store PARAMSAVE version major... - char uc = DSSI_PARAMSAVE_VERSION_MAJOR; - if(i && ((i % 16) == 0)) - { - xml.nput("\n"); - xml.nput(level, ""); - } - xml.nput("%02x ", uc & 0xff); - ++i; - - // Store PARAMSAVE version minor... - uc = DSSI_PARAMSAVE_VERSION_MINOR; - if(i && ((i % 16) == 0)) - { - xml.nput("\n"); - xml.nput(level, ""); - } - xml.nput("%02x ", uc & 0xff); - ++i; - - // Store bank... - void* p = &bnk; - for(int j = 0; j < uls; ++j) - { - if(i && ((i % 16) == 0)) - { - xml.nput("\n"); - xml.nput(level, ""); - } - xml.nput("%02x ", ((char*)(p))[j] & 0xff); - ++i; - } - - // Store program... - p = &prog; - for(int j = 0; j < uls; ++j) - { - if(i && ((i % 16) == 0)) - { - xml.nput("\n"); - xml.nput(level, ""); - } - xml.nput("%02x ", ((char*)(p))[j] & 0xff); - ++i; - } - - // Store controls... - for(unsigned long c = 0; c < synth->_controlInPorts; ++c) - { - float v = controls[c].val; - p = &v; - for(int j = 0; j < fs; ++j) - { - if(i && ((i % 16) == 0)) - { - xml.nput("\n"); - xml.nput(level, ""); - } - xml.nput("%02x ", ((char*)(p))[j] & 0xff); - ++i; - } - } - xml.nput("\n"); - xml.tag(level--, "/event"); - xml.etag(level--, "midistate"); - } - } - */ - - // Store controls as parameters... - for(unsigned long c = 0; c < synth->_controlInPorts; ++c) - { - float f = controls[c].val; - xml.floatTag(level, "param", f); - //xml.tag(level, "param name=\"%s\" val=\"%s\"/", name, r->first.c_str(), r->second.c_str()); - } -} - -//--------------------------------------------------------- -// preProcessAlways -//--------------------------------------------------------- - -void DssiSynthIF::preProcessAlways() -{ - -} - -//--------------------------------------------------------- -// processEvent -// Return true if event pointer filled. -//-------------------------------------------------------- - -bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event) -{ - const DSSI_Descriptor* dssi = synth->dssi; - - int chn = e.channel(); - int a = e.dataA(); - int b = e.dataB(); - //for sysex - //QByteArray ba = QByteArray((const char*)e.data(), e.len()); - //we must had 0xF0 at the beginning and 0xF7 at the end of e.data() - //ba.push_front(0xF0); - //ba.push_back(0xF7); - - //QByteArray ba(); - ////ba.assign((const char*)e.data(), e.len()); - ////ba.duplicate((const char*)e.data(), e.len()); - ////ba.setRawData((const char*)e.data(), e.len()); - //int len = e.len() + 2; - - int len = e.len(); - char ca[len + 2]; - - ca[0] = 0xF0; - memcpy(ca + 1, (const char*)e.data(), len); - ca[len + 1] = 0xF7; - - len += 2; - - //snd_seq_event_t* event = &events[nevents]; - event->queue = SND_SEQ_QUEUE_DIRECT; - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event type:%d chn:%d a:%d b:%d\n", e.type(), chn, a, b); - #endif - - switch(e.type()) - { - case ME_NOTEON: - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_NOTEON\n"); - #endif - - if(b) - snd_seq_ev_set_noteon(event, chn, a, b); - else - snd_seq_ev_set_noteoff(event, chn, a, 0); - break; - case ME_NOTEOFF: - snd_seq_ev_set_noteoff(event, chn, a, 0); - break; - case ME_PROGRAM: - { - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_PROGRAM\n"); - #endif - - int bank = (a >> 8) & 0xff; - int prog = a & 0xff; - //_curBank = bank; - //_curProgram = prog; - synti->_curBankH = 0; - synti->_curBankL = bank; - synti->_curProgram = prog; - - if(dssi->select_program) - { - dssi->select_program(handle, bank, prog); - // Notify that changes are to be sent upon heartbeat. - synti->_guiUpdateProgram = true; - } - // Event pointer not filled. Return false. - return false; - } - break; - case ME_CONTROLLER: - { - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_CONTROLLER\n"); - #endif - - if((a == 0) || (a == 32)) - return false; - - if(a == CTRL_PROGRAM) - { - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_CONTROLLER, dataA is CTRL_PROGRAM\n"); - #endif - - int bank = (b >> 8) & 0xff; - int prog = b & 0xff; - - //_curBank = bank; - //_curProgram = prog; - synti->_curBankH = 0; - synti->_curBankL = bank; - synti->_curProgram = prog; - - if(dssi->select_program) - { - dssi->select_program(handle, bank, prog); - // Notify that changes are to be sent upon heartbeat. - synti->_guiUpdateProgram = true; - } - // Event pointer not filled. Return false. - return false; - } - - if(a == CTRL_PITCH) - { - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_CONTROLLER, dataA is CTRL_PITCH\n"); - #endif - - b &= 0x3fff; - snd_seq_ev_set_pitchbend(event, chn, b); - // Event pointer filled. Return true. - return true; - } - - const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin; - - ciMidiCtl2LadspaPort ip = synth->midiCtl2PortMap.find(a); - // Is it just a regular midi controller, not mapped to a LADSPA port (either by the plugin or by us)? - // NOTE: There's no way to tell which of these controllers is supported by the plugin. - // For example sustain footpedal or pitch bend may be supported, but not mapped to any LADSPA port. - if(ip == synth->midiCtl2PortMap.end()) - { - // p3.3.39 Changed to return false because of crashes with unknown controllers when switching a midi track - // among different dssi synths and regular synths etc. For example high RPN offset numbers (set by another - // device selected into the midi port before selecting this synth) were passing through here when in fact - // the particular synth had no such midi controllers. - // ========================== No, that leaves out regular controllers like footpedal - //#ifdef DSSI_DEBUG - //fprintf(stderr, "DssiSynthIF::processEvent dataA:%d not found in map (not a ladspa controller). Ignoring.\n", a); - //#endif - //return false; - - //#ifdef DSSI_DEBUG - //fprintf(stderr, "DssiSynthIF::processEvent dataA:%d not found in map (not a ladspa controller). Filling event as regular controller.\n", a); - //#endif - //snd_seq_ev_set_controller(event, chn, a, b); - //return true; - - int ctlnum = a; - //switch(midiControllerType(a)) - if(midiControllerType(a) != MidiController::Controller7) - return false; - else - { - /* - case MidiController::NRPN14: - case MidiController::Controller14: - case MidiController::Pitch: - case MidiController::Program: - case MidiController::RPN: - case MidiController::RPN14: - case MidiController::NRPN: - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent non-ladspa midi event controller unsupported. DataA:%d\n", a); - #endif - return false; - */ - - //case MidiController::Controller7: - #ifdef DSSI_DEBUG - //fprintf(stderr, "DssiSynthIF::processEvent midi event is Controller7. Changing to DSSI_CC type. Current dataA:%d\n", a); - fprintf(stderr, "DssiSynthIF::processEvent non-ladspa midi event is Controller7. Current dataA:%d\n", a); - #endif - //a = DSSI_CC(a); - a &= 0x7f; - ctlnum = DSSI_CC_NUMBER(ctlnum); - // break; - - /* - case MidiController::NRPN14: - #ifdef DSSI_DEBUG - // fprintf(stderr, "DssiSynthIF::processEvent midi event is NRPN. Changing to DSSI_NRPN type. Current dataA:%d\n", a); - fprintf(stderr, "DssiSynthIF::processEvent non-ladspa midi event is NRPN. Current dataA:%d\n", a); - #endif - //a = DSSI_NRPN(a - CTRL_NRPN14_OFFSET); - a &= 0x3fff; - ctlnum = DSSI_NRPN_NUMBER(ctlnum); - break; - case MidiController::Controller14: - a &= 0x7f; - break; - case MidiController::Pitch: - // Should be caught above! - #ifdef DSSI_DEBUG - //fprintf(stderr, "DssiSynthIF::processEvent non-ladspa midi event is Pitch. DataA:%d\n", a); - fprintf(stderr, "DssiSynthIF::processEvent Error! non-ladspa midi event is Pitch. Should have been caught already! DataA:%d\n", a); - #endif - //a &= 0x3fff; - //snd_seq_ev_set_pitchbend(event, chn, b); - // Event pointer filled. Return true. - //return true; - // Event pointer not filled. Return false. - return false; - case MidiController::Program: - // Should be caught above! - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent Error! non-ladspa midi event is Program. Should have been caught already! DataA:%d\n", a); - #endif - return false; - case MidiController::RPN: - case MidiController::RPN14: - case MidiController::NRPN: - default: - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent non-ladspa midi event is RPN, RPN14, or NRPN type. DataA:%d\n", a); - #endif - break; - */ - } - - // Verify it's the same number. - //if(ctlnum != a) - //{ - // #ifdef DSSI_DEBUG - // printf("DssiSynthIF::processEvent Error! non-ladspa midi ctlnum:%d != event dataA:%d\n", ctlnum, a); - // #endif - // Event not filled. Return false. - - // TEMP: TODO: Turn on later - //return false; - //} - - // Fill the event. - #ifdef DSSI_DEBUG - printf("DssiSynthIF::processEvent non-ladspa filling midi event chn:%d dataA:%d dataB:%d\n", chn, a, b); - #endif - snd_seq_ev_set_controller(event, chn, a, b); - return true; - } - - //int num = ip->first; - unsigned long k = ip->second; - - unsigned long i = synth->pIdx[k]; - - int ctlnum = DSSI_NONE; - if(dssi->get_midi_controller_for_port) - ctlnum = dssi->get_midi_controller_for_port(handle, i); - - // No midi controller for the ladspa port? Send to ladspa control. - if(ctlnum == DSSI_NONE) - { - // Sanity check. - if(k > synth->_controlInPorts) - return false; - - // TODO: If necessary... choose non-existing numbers... - //for(int k = 0; k < controlPorts; ++k) - //{ - // int i = synth->pIdx[k]; - //} - - // Simple but flawed solution: Start them at 0x60000 + 0x2000 = 0x62000. Max NRPN number is 0x3fff. - ctlnum = k + (CTRL_NRPN14_OFFSET + 0x2000); - } - // p3.3.39 - else - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::processEvent plugin requests DSSI-style ctlnum:%x(h) %d(d) be mapped to control port:%ld...\n", ctlnum, ctlnum, i); - #endif - - int c = ctlnum; - // Can be both CC and NRPN! Prefer CC over NRPN. - if(DSSI_IS_CC(ctlnum)) - { - ctlnum = DSSI_CC_NUMBER(c); - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::processEvent is CC ctlnum:%d\n", ctlnum); - #endif - - #ifdef DSSI_DEBUG - if(DSSI_IS_NRPN(ctlnum)) - printf("DssiSynthIF::processEvent is also NRPN control. Using CC.\n"); - #endif - } - else - if(DSSI_IS_NRPN(ctlnum)) - { - ctlnum = DSSI_NRPN_NUMBER(c) + CTRL_NRPN14_OFFSET; - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::processEvent is NRPN ctlnum:%x(h) %d(d)\n", ctlnum, ctlnum); - #endif - } - - } - - //{ - float val = midi2LadspaValue(ld, i, ctlnum, b); - - #ifdef DSSI_DEBUG - //fprintf(stderr, "DssiSynthIF::processEvent No midi controller for control port:%d port:%d dataA:%d Converting val from:%d to ladspa:%f\n", i, k, a, b, val); - fprintf(stderr, "DssiSynthIF::processEvent control port:%ld port:%ld dataA:%d Converting val from:%d to ladspa:%f\n", i, k, a, b, val); - #endif - - // Set the ladspa port value. - controls[k].val = val; - // FIXME: Testing - Works but is this safe in a RT process callback? Try hooking into gui heartbeat timer instead... - //lo_send(uiTarget, uiOscControlPath, "if", i, val); - // Notify that changes are to be sent upon heartbeat. - synti->_guiUpdateControls[k] = true; - - // Since we absorbed the message as a ladspa control change, return false - the event is not filled. - return false; - //} - - // p3.3.39 Removed. - // "Hosts should not deliver through run_synth any MIDI controller events that have already - // been mapped to control port values." - // D'oh! My mistake, did not understand that the mapping is only a *request* that the app map MIDI - // controller events to a LADSPA port, and must do the conversion, not to actually *send* them via MIDI... - /* - else - { - switch(midiControllerType(a)) - { - case MidiController::Controller7: - #ifdef DSSI_DEBUG - //fprintf(stderr, "DssiSynthIF::processEvent midi event is Controller7. Changing to DSSI_CC type. Current dataA:%d\n", a); - fprintf(stderr, "DssiSynthIF::processEvent midi event is Controller7. Current dataA:%d\n", a); - #endif - //a = DSSI_CC(a); - a &= 0x7f; - ctlnum = DSSI_CC_NUMBER(ctlnum); - break; - case MidiController::NRPN14: - #ifdef DSSI_DEBUG - // fprintf(stderr, "DssiSynthIF::processEvent midi event is NRPN. Changing to DSSI_NRPN type. Current dataA:%d\n", a); - fprintf(stderr, "DssiSynthIF::processEvent midi event is NRPN. Current dataA:%d\n", a); - #endif - //a = DSSI_NRPN(a - CTRL_NRPN14_OFFSET); - a &= 0x3fff; - ctlnum = DSSI_NRPN_NUMBER(ctlnum); - break; - case MidiController::Controller14: - a &= 0x7f; - break; - case MidiController::Pitch: - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is Pitch. DataA:%d\n", a); - #endif - a &= 0x3fff; - break; - case MidiController::Program: - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is Program. DataA:%d\n", a); - #endif - a &= 0x3fff; - break; - case MidiController::RPN: - case MidiController::RPN14: - case MidiController::NRPN: - default: - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is RPN, RPN14, or NRPN type. DataA:%d\n", a); - #endif - break; - } - - // Verify it's the same number. - if(ctlnum != a) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::processEvent Error! ctlnum:%d != event dataA:%d\n", ctlnum, a); - #endif - // Event not filled. Return false. - - // TEMP: TODO: Turn on later - //return false; - } - - // Fill the event. - // FIXME: Darn! We get to this point, but no change in sound (later). Nothing happens, at least with LTS - - // which is the only one I found so far with midi controllers. - // Tried with/without converting to DSSI_CC and DSSI_NRPN. What could be wrong here? - #ifdef DSSI_DEBUG - printf("DssiSynthIF::processEvent filling event chn:%d dataA:%d dataB:%d\n", chn, a, b); - #endif - snd_seq_ev_set_controller(event, chn, a, b); - } - */ - - } - break; - case ME_PITCHBEND: - snd_seq_ev_set_pitchbend(event, chn, a); - break; - case ME_AFTERTOUCH: - snd_seq_ev_set_chanpress(event, chn, a); - break; - case ME_SYSEX: - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_SYSEX\n"); - #endif - - if (QString((const char*)e.data()).startsWith("VSTSAVE")) { -#ifdef DSSI_VST_CHUNK_SUPPORT - printf("loading chunk from sysex %s!\n", e.data()+7); - dssi->setCustomData(handle, e.data()+7 /* len of str*/,e.len()-7); -#else - printf("support for vst chunks not compiled in!\n"); -#endif - // Event not filled. - return false; - } - /* - // p3.3.39 Read the state of current bank and program and all input control values. - // TODO: Needs to be better. See write(). - else - if (QString((const char*)e.data()).startsWith("PARAMSAVE")) - { - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_SYSEX PARAMSAVE\n"); - #endif - - unsigned long dlen = e.len() - 9; // Minus "PARAMSAVE" - if(dlen > 0) - { - //if(dlen < 2 * sizeof(unsigned long)) - if(dlen < (2 + 2 * sizeof(unsigned long))) // Version major and minor bytes, bank and program. - printf("DssiSynthIF::processEvent Error: PARAMSAVE data length does not include at least version major and minor, bank and program!\n"); - else - { - // Not required, yet. - //char vmaj = *((char*)(e.data() + 9)); // After "PARAMSAVE" - //char vmin = *((char*)(e.data() + 10)); - - unsigned long* const ulp = (unsigned long*)(e.data() + 11); // After "PARAMSAVE" + version major and minor. - // TODO: TODO: Set plugin bank and program. - _curBank = ulp[0]; - _curProgram = ulp[1]; - - dlen -= (2 + 2 * sizeof(unsigned long)); // After the version major and minor, bank and program. - - if(dlen > 0) - { - if((dlen % sizeof(float)) != 0) - printf("DssiSynthIF::processEvent Error: PARAMSAVE float data length not integral multiple of float size!\n"); - else - { - const unsigned long n = dlen / sizeof(float); - if(n != synth->_controlInPorts) - printf("DssiSynthIF::processEvent Warning: PARAMSAVE number of floats:%ld != number of controls:%ld\n", n, synth->_controlInPorts); - - // Point to location after "PARAMSAVE", version major and minor, bank and progam. - float* const fp = (float*)(e.data() + 9 + 2 + 2 * sizeof(unsigned long)); - - for(unsigned long i = 0; i < synth->_controlInPorts && i < n; ++i) - { - const float v = fp[i]; - controls[i].val = v; - } - } - } - } - } - // Event not filled. - return false; - } - */ - else - { - // NOTE: There is a limit on the size of a sysex. Got this: - // "DssiSynthIF::processEvent midi event is ME_SYSEX" - // "WARNING: MIDI event of type ? decoded to 367 bytes, discarding" - // That might be ALSA doing that. - snd_seq_ev_set_sysex(event, len, - //(unsigned char*)ba.data()); - (unsigned char*)ca); - } - break; - default: - if(debugMsg) - fprintf(stderr, "DssiSynthIF::processEvent midi event unknown type:%d\n", e.type()); - // Event not filled. - return false; - break; - } - - return true; -} - -//--------------------------------------------------------- -// getData -//--------------------------------------------------------- - -//void DssiSynthIF::getData(MidiEventList* el, unsigned pos, int ch, unsigned samples, float** data) -iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent /*i*/, unsigned pos, int ports, unsigned n, float** buffer) -{ - //#ifdef DSSI_DEBUG - // fprintf(stderr, "DssiSynthIF::getData elsize:%d pos:%d ports:%d samples:%d processed already?:%d\n", el->size(), pos, ports, n, synti->processed()); - //#endif - - //BEGIN: Process midi events - - // FIXME: Add 10(?) for good luck in case volatile size changes (increments) while we're processing. - //unsigned long nevents = el->size(); - unsigned long nevents = el->size() + synti->putFifo.getSize() + 10; - - /* - while (!synti->putFifo.isEmpty()) { - MidiEvent event = synti->putFifo.get(); - printf("Dssi: FIFO\n"); - } - */ - - snd_seq_event_t events[nevents]; - memset(events, 0, sizeof(events)); - nevents = 0; - - //int curPos = pos; - //unsigned endPos = pos + samples; - unsigned endPos = pos + n; - //int off = pos; - int frameOffset = audio->getFrameOffset(); - - //iMidiEvent i = el->begin(); - iMPEvent i = el->begin(); - - // Process event list events... - for(; i != el->end(); ++i) - { - //if(i->time() >= endPos) // Doesn't work, at least here in muse-1. The event times are all - // just slightly after the endPos, EVEN IF transport is stopped. - // So it misses all the notes. - if(i->time() >= (endPos + frameOffset)) // NOTE: frameOffset? Tested, examined printouts of times: Seems OK for playback. - break; - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::getData eventlist event time:%d\n", i->time()); - #endif - - // p3.3.39 Update hardware state so knobs and boxes are updated. Optimize to avoid re-setting existing values. - // Same code as in MidiPort::sendEvent() - if(synti->midiPort() != -1) - { - MidiPort* mp = &midiPorts[synti->midiPort()]; - if(i->type() == ME_CONTROLLER) - { - int da = i->dataA(); - int db = i->dataB(); - db = mp->limitValToInstrCtlRange(da, db); - if(!mp->setHwCtrlState(i->channel(), da, db)) - continue; - //mp->setHwCtrlState(i->channel(), da, db); - } - else - if(i->type() == ME_PITCHBEND) - { - int da = mp->limitValToInstrCtlRange(CTRL_PITCH, i->dataA()); - if(!mp->setHwCtrlState(i->channel(), CTRL_PITCH, da)) - continue; - //mp->setHwCtrlState(i->channel(), CTRL_PITCH, da); - } - else - if(i->type() == ME_PROGRAM) - { - if(!mp->setHwCtrlState(i->channel(), CTRL_PROGRAM, i->dataA())) - continue; - //mp->setHwCtrlState(i->channel(), CTRL_PROGRAM, i->dataA()); - } - } - - if(processEvent(*i, &events[nevents])) - ++nevents; - } - - // Now process putEvent events... - while(!synti->putFifo.isEmpty()) - { - MidiPlayEvent e = synti->putFifo.get(); - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::getData putFifo event time:%d\n", e.time()); - #endif - - // Set to the current time. - // FIXME: FIXME: Wrong - we should be setting some kind of linear realtime wallclock here, not song pos. - e.setTime(pos); - if(processEvent(e, &events[nevents])) - ++nevents; - } - - // Now process OSC gui input control fifo events. - // It is probably more important that these are processed last so that they take precedence over all other - // events because OSC + DSSI/DSSI-VST are fussy about receiving feedback via these control ports, from GUI changes. - #ifdef OSC_SUPPORT - unsigned long ctls = synth->_controlInPorts; - for(unsigned long k = 0; k < ctls; ++k) - { - OscControlFifo* cfifo = _oscif.oscFifo(k); - if(!cfifo) - continue; - - // If there are 'events' in the fifo, get exactly one 'event' per control per process cycle... - if(!cfifo->isEmpty()) - { - OscControlValue v = cfifo->get(); - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::getData OscControlFifo event input control number:%ld value:%f\n", k, v.value); - #endif - - // Set the ladspa control port value. - controls[k].val = v.value; - - // TODO: (From plugin module, adapt for synth if/when our own plugin gui is added to synths). - // Need to update the automation value, otherwise the block above overwrites with the last automation value. - ///if(_track) - ///{ - // Since we are now in the audio thread context, there's no need to send a message, - // just modify directly. - //audio->msgSetPluginCtrlVal(this, genACnum(_id, i), controls[i].val); - /// _track->setPluginCtrlVal(k, v.value) - ///} - } - } - #endif - -/* // This is from MESS... Tried this here, didn't work, need to re-adapt, try again. - int evTime = i->time(); - if(evTime == 0) - { - printf("DssiSynthIF::getData - time is 0!\n"); - //continue; - evTime=frameOffset; // will cause frame to be zero, problem? - } - - int frame = evTime - frameOffset; - - if(frame >= endPos) - { - printf("DssiSynthIF::getData frame > endPos!! frame = %d >= endPos %d, i->time() %d, frameOffset %d curPos=%d\n", frame, endPos, i->time(), frameOffset,curPos); - continue; - } - - if(frame > curPos) - { - if(frame < pos) - printf("DssiSynthIF::getData should not happen: missed event %d\n", pos -frame); - else - { -*/ - -/* - } - curPos = frame; - } -*/ -// } - - el->erase(el->begin(), i); - //END: Process midi events - - //BEGIN: Run the synth - // All ports must be connected to something! - - // First, copy the given input buffers to our local input buffers. - unsigned long np, k; - //np = portsin > synth->_inports ? synth->_inports : portsin; - //for(k = 0; k < np; ++k) - // memcpy(audioInBuffers[k], inbuffer[k], sizeof(float) * n); - //for(; k < portsin; ++k) - // memset(audioInBuffers[k], 0, sizeof(float) * n); - - // Watch our limits. - np = ports > synth->_outports ? synth->_outports : ports; - - const DSSI_Descriptor* dssi = synth->dssi; - const LADSPA_Descriptor* descr = dssi->LADSPA_Plugin; - k = 0; - // Connect the given buffers directly to the ports, up to a max of synth ports. - for(; k < np; ++k) - descr->connect_port(handle, synth->oIdx[k], buffer[k]); - // Connect the remaining ports to some local buffers (not used yet). - for(; k < synth->_outports; ++k) - descr->connect_port(handle, synth->oIdx[k], audioOutBuffers[k]); - - /* - // - // p3.3.39 Handle inputs... - // - //if((song->bounceTrack != this) && !noInRoute()) - if(!((AudioTrack*)synti)->noInRoute()) - { - RouteList* irl = ((AudioTrack*)synti)->inRoutes(); - iRoute i = irl->begin(); - if(!i->track->isMidiTrack()) - { - //if(debugMsg) - printf("DssiSynthIF::getData: Error: First route is a midi track route!\n"); - } - else - { - int ch = i->channel == -1 ? 0 : i->channel; - int remch = i->remoteChannel == -1 ? 0 : i->remoteChannel; - int chs = i->channels == -1 ? 0 : i->channels; - - // TODO: - //if(ch >= synth->_inports) - //iUsedIdx[ch] = true; - //if(chs == 2) - // iUsedIdx[ch + 1] = true; - - //((AudioTrack*)i->track)->copyData(framePos, channels, nframe, bp); - ((AudioTrack*)i->track)->copyData(pos, ports, - //(i->track->type() == Track::AUDIO_SOFTSYNTH && i->channel != -1) ? i->channel : 0, - i->channel, - i->channels, - n, bp); - } - - //unsigned pos, int ports, unsigned n, float** buffer - - ++i; - for(; i != irl->end(); ++i) - { - if(i->track->isMidiTrack()) - { - //if(debugMsg) - printf("DssiSynthIF::getData: Error: Route is a midi track route!\n"); - continue; - } - //((AudioTrack*)i->track)->addData(framePos, channels, nframe, bp); - ((AudioTrack*)i->track)->addData(framePos, channels, - //(i->track->type() == Track::AUDIO_SOFTSYNTH && i->channel != -1) ? i->channel : 0, - i->channel, - i->channels, - nframe, bp); - } - } - */ - - //#ifdef DSSI_DEBUG - //if(nevents) - // fprintf(stderr, "DssiSynthIF::getData run nevents:%d\n", nevents); - //#endif - - // Run the synth for one segment. This processes events and gets/fills our local buffers... - if(synth->dssi->run_synth) - { - synth->dssi->run_synth(handle, n, events, nevents); - - // NOTE: Just a test - //for(int m = 0; m < n; ++m) - //{ - // synth->dssi->run_synth(handle, 1, events, nevents); - //} - - } - else if (synth->dssi->run_multiple_synths) - { - snd_seq_event_t* ev = events; - synth->dssi->run_multiple_synths(1, &handle, n, &ev, &nevents); - } - //END: Run the synth - - return i; -} - -//--------------------------------------------------------- -// putEvent -//--------------------------------------------------------- - -//bool DssiSynthIF::putEvent(const MidiEvent& ev) -bool DssiSynthIF::putEvent(const MidiPlayEvent& ev) - { - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::putEvent midi event time:%d chn:%d a:%d b:%d\n", ev.time(), ev.channel(), ev.dataA(), ev.dataB()); - #endif - - if (midiOutputTrace) - ev.dump(); - - return synti->putFifo.put(ev); - - //return false; - } - - -//--------------------------------------------------------- -// incInstances -//--------------------------------------------------------- - -void DssiSynth::incInstances(int val) -{ - _instances += val; - if (_instances == 0) - { - if (handle) - { - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynth::incInstances no more instances, closing library\n"); - #endif - - dlclose(handle); - } - handle = 0; - dssi = NULL; - df = NULL; - pIdx.clear(); - opIdx.clear(); - iIdx.clear(); - oIdx.clear(); - rpIdx.clear(); - iUsedIdx.clear(); - midiCtl2PortMap.clear(); - port2MidiCtlMap.clear(); - //synti->_guiUpdateControls.clear(); - } -} - -//--------------------------------------------------------- -// initGui -//--------------------------------------------------------- -bool DssiSynthIF::initGui() -{ - #ifdef OSC_SUPPORT - return _oscif.oscInitGui(); - #endif - - return true; - - /* - // Are we already running? We don't want to allow another process do we... - if((guiQProc != 0) && (guiQProc->isRunning())) - return true; - - // - // start gui - // - static char oscUrl[1024]; - //snprintf(oscUrl, 1024, "%s/%s", url, synti->name().toAscii().data()); - //snprintf(oscUrl, 1024, "%s/%s", url, synti->name().toLatin1().constData()); - snprintf(oscUrl, 1024, "%s/%s/%s", url, synth->info.baseName().toLatin1().constData(), synti->name().toLatin1().constData()); - - //QString guiPath(info.path() + "/" + info.baseName()); - QString guiPath(synth->info.dirPath() + "/" + synth->info.baseName()); - - QDir guiDir(guiPath, "*", QDir::Unsorted, QDir::Files); - if (guiDir.exists()) - { - //const QFileInfoList list = guiDir.entryInfoList(); - QStringList list = guiDir.entryList(); - - //for (int i = 0; i < list.size(); ++i) { - for (unsigned int i = 0; i < list.count(); ++i) - { - - //QFileInfo fi = list.at(i); - QFileInfo fi(guiPath + QString("/") + list[i]); - - QString gui(fi.filePath()); - if (gui.contains('_') == 0) - continue; - struct stat buf; - - //if (stat(gui.toAscii().data(), &buf)) { - if (stat(gui.toLatin1().constData(), &buf)) { - - perror("stat failed"); - continue; - } - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::initGui %s %s %s %s\n", - //fi.filePath().toAscii().data(), - //fi.fileName().toAscii().data(), - fi.filePath().toLatin1().constData(), - //fi.fileName().toLatin1().constData(), - - oscUrl, - - synth->info.filePath().toLatin1().constData(), - - //name().toAscii().data(), - synth->name().toLatin1().constData()); - #endif - - if ((S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) && - (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - { - // Changed by T356. - // fork + execlp were causing the processes to remain after closing gui, requiring manual kill. - // Changed to QProcess, works OK now. - //if((guiPid = fork()) == 0) - { - // No QProcess created yet? Do it now. Only once per SynthIF instance. Exists until parent destroyed. - if(guiQProc == 0) - guiQProc = new QProcess(muse); - - // Don't forget this, he he... - guiQProc->clearArguments(); - - guiQProc->addArgument(fi.filePath()); - //guiQProc->addArgument(fi.fileName()); // No conventional 'Arg0' here. - guiQProc->addArgument(QString(oscUrl)); - guiQProc->addArgument(synth->info.filePath()); - guiQProc->addArgument(synth->name()); - guiQProc->addArgument(QString("channel 1")); - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::initGui starting QProcess\n"); - #endif - - if(guiQProc->start() == TRUE) - { - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::initGui started QProcess\n"); - #endif - - //guiPid = guiQProc->processIdentifier(); - } - else - { - - // execlp( - // fi.filePath().toAscii().data(), - // fi.fileName().toAscii().data(), - // fi.filePath().toLatin1().constData(), - // fi.fileName().toLatin1().constData(), - - // oscUrl, - - // info.filePath().toAscii().data(), - // name().toAscii().data(), - // synth->info.filePath().toLatin1().constData(), - // synth->name().toLatin1().constData(), - - // "channel 1", (void*)0); - - fprintf(stderr, "exec %s %s %s %s failed: %s\n", - // fi.filePath().toAscii().data(), - // fi.fileName().toAscii().data(), - fi.filePath().toLatin1().constData(), - fi.fileName().toLatin1().constData(), - oscUrl, - // name().toAscii().data(), - synth->name().toLatin1().constData(), - strerror(errno)); - - // It's Ok, Keep going. So nothing happens. So what. The timeout in showGui will just leave. - // Maybe it's a 'busy' issue somewhere - allow to try again later + save work now. - // exit(1); - - } - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::initGui after QProcess\n"); - #endif - } - } - } - //synth->_hasGui = true; - } - else { - printf("%s: no dir for dssi gui found: %s\n", - //name().toAscii().data(), guiPath.toAscii().data()); - synth->name().toLatin1().constData(), guiPath.toLatin1().constData()); - - //synth->_hasGui = false; - } - - return true; - */ -} - -//--------------------------------------------------------- -// guiHeartBeat -//--------------------------------------------------------- - -void DssiSynthIF::guiHeartBeat() -{ - #ifdef OSC_SUPPORT - // Update the gui's program if needed. - if(synti->_guiUpdateProgram) - { - _oscif.oscSendProgram(synti->_curProgram, synti->_curBankL); - synti->_guiUpdateProgram = false; - } - - // Update the gui's controls if needed. - unsigned long ports = synth->_controlInPorts; - if(ports > synti->_guiUpdateControls.size()) - return; - for(unsigned long i = 0; i < ports; ++i) - { - if(synti->_guiUpdateControls[i]) - { - unsigned long k = synth->pIdx[i]; - _oscif.oscSendControl(k, controls[i].val); - - // Reset. - synti->_guiUpdateControls[i] = false; - } - } - #endif -} - -#ifdef OSC_SUPPORT -//--------------------------------------------------------- -// oscUpdate -//--------------------------------------------------------- - -int DssiSynthIF::oscUpdate() -{ - // Send project directory. - _oscif.oscSendConfigure(DSSI_PROJECT_DIRECTORY_KEY, museProject.toLatin1().constData()); // song->projectPath() - - // Send current string configuration parameters. - //StringParamMap& map = synti->_stringParamMap; - int i = 0; - for(ciStringParamMap r = synti->_stringParamMap.begin(); r != synti->_stringParamMap.end(); ++r) - { - _oscif.oscSendConfigure(r->first.c_str(), r->second.c_str()); - // Avoid overloading the GUI if there are lots and lots of params. - if((i+1) % 50 == 0) - usleep(300000); - ++i; - } - - // Send current bank and program. - //unsigned long bank, prog; - //synti->currentProg(&prog, &bank, 0); - //_oscif.oscSendProgram(prog, bank); - _oscif.oscSendProgram(synti->_curProgram, synti->_curBankL); - - // Send current control values. - unsigned long ports = synth->_controlInPorts; - for(unsigned long i = 0; i < ports; ++i) - { - unsigned long k = synth->pIdx[i]; - _oscif.oscSendControl(k, controls[i].val); - // Avoid overloading the GUI if there are lots and lots of ports. - if((i+1) % 50 == 0) - usleep(300000); - } - - -#if 0 - /* Send current bank/program (-FIX- another race...) */ - if (instance->pendingProgramChange < 0) { - unsigned long bank = instance->currentBank; - unsigned long program = instance->currentProgram; - instance->uiNeedsProgramUpdate = 0; - if (instance->uiTarget) { - lo_send(instance->uiTarget, instance->ui_osc_program_path, "ii", bank, program); - } - } - - /* Send control ports */ - for (i = 0; i < instance->plugin->controlIns; i++) { - int in = i + instance->firstControlIn; - int port = pluginControlInPortNumbers[in]; - lo_send(instance->uiTarget, instance->ui_osc_control_path, "if", port, - pluginControlIns[in]); - /* Avoid overloading the GUI if there are lots and lots of ports */ - if ((i+1) % 50 == 0) - usleep(300000); - } -#endif - return 0; -} - -//--------------------------------------------------------- -// oscProgram -//--------------------------------------------------------- - -int DssiSynthIF::oscProgram(unsigned long program, unsigned long bank) - { - //int bank = argv[0]->i; - //int program = argv[1]->i; - - int ch = 0; // TODO: ?? - - int port = synti->midiPort(); - - //_curBank = bank; - //_curProgram = program; - synti->_curBankH = 0; - synti->_curBankL = bank; - synti->_curProgram = program; - - bank &= 0xff; - program &= 0xff; - - //MidiEvent event(0, ch, ME_CONTROLLER, CTRL_PROGRAM, (bank << 8) + program); - - if(port != -1) - { - //MidiPlayEvent event(0, port, ch, ME_CONTROLLER, CTRL_PROGRAM, (bank << 8) + program); - MidiPlayEvent event(0, port, ch, ME_PROGRAM, (bank << 8) + program, 0); - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::oscProgram midi event chn:%d a:%d b:%d\n", event.channel(), event.dataA(), event.dataB()); - #endif - - midiPorts[port].sendEvent(event); - } - - - - //synti->playMidiEvent(&event); // TODO - // - //MidiDevice* md = dynamic_cast<MidiDevice*>(synti); - //if(md) - // md->putEvent(event); - // - //synti->putEvent(event); - - return 0; - } - -//--------------------------------------------------------- -// oscControl -//--------------------------------------------------------- - -int DssiSynthIF::oscControl(unsigned long port, float value) - { - //int port = argv[0]->i; - //LADSPA_Data value = argv[1]->f; - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::oscControl received oscControl port:%ld val:%f\n", port, value); - #endif - - //int controlPorts = synth->_controlInPorts; - - //if(port >= controlPorts) - //if(port < 0 || port >= synth->rpIdx.size()) - if(port >= synth->rpIdx.size()) - { - //fprintf(stderr, "DssiSynthIF::oscControl: port number:%d is out of range of number of ports:%d\n", port, controlPorts); - fprintf(stderr, "DssiSynthIF::oscControl: port number:%ld is out of range of index list size:%zd\n", port, synth->rpIdx.size()); - return 0; - } - - // Convert from DSSI port number to control input port index. - unsigned long cport = synth->rpIdx[port]; - - if((int)cport == -1) - { - fprintf(stderr, "DssiSynthIF::oscControl: port number:%ld is not a control input\n", port); - return 0; - } - - // p3.3.39 Set the DSSI control input port's value. - // Observations: With a native DSSI synth like LessTrivialSynth, the native GUI's controls do not change the sound at all - // ie. they don't update the DSSI control port values themselves. - // Hence in response to the call to this oscControl, sent by the native GUI, it is required to that here. -/// controls[cport].val = value; - // DSSI-VST synths however, unlike DSSI synths, DO change their OWN sound in response to their gui controls. - // AND this function is called. - // Despite the descrepency we are STILL required to update the DSSI control port values here - // because dssi-vst is WAITING FOR A RESPONSE. (A CHANGE in the control port value). - // It will output something like "...4 events expected..." and count that number down as 4 actual control port value CHANGES - // are done here in response. Normally it says "...0 events expected..." when MusE is the one doing the DSSI control changes. - // TODO: (Done) May need FIFOs on each control(!) so that the control changes get sent one per process cycle. - // Observed countdown not actually going to zero upon string of changes. - // - // NOTE: NOTE: This line in RemoteVSTServer::setParameter(int p, float v) in dssi-vst-server.cpp : - // - // " if (tv.tv_sec > m_lastGuiComms.tv_sec + 10) " - // - // explains an observation that after ten seconds, the server automatically clears the expected number to 0. - // TODO: Now MusE should forget about all the VST fifo events past ten+ (?) seconds. Add event timestamps... - // You can't send any 'new' values until either you a): send all the expected events or b): wait ten seconds. - // (Because the server simply ignores the 'expected' messages.) - // - // Well, at least here are the fifos. Try this ... - OscControlFifo* cfifo = _oscif.oscFifo(cport); - if(cfifo) - { - OscControlValue cv; - //cv.idx = cport; - cv.value = value; - if(cfifo->put(cv)) - { - fprintf(stderr, "DssiSynthIF::oscControl: fifo overflow: in control number:%ld\n", cport); - } - } - - //const DSSI_Descriptor* dssi = synth->dssi; - //const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin; - - ciMidiCtl2LadspaPort ip = synth->port2MidiCtlMap.find(cport); - if(ip != synth->port2MidiCtlMap.end()) - { - // TODO: TODO: Update midi MusE's midi controller knobs, sliders, boxes etc with a call to the midi port's setHwCtrlState() etc. - // But first we need a ladspa2MidiValue() function! ... - // - // - //float val = ladspa2MidiValue(ld, i, ?, ?); - - } - -#if 0 - int port = argv[0]->i; - LADSPA_Data value = argv[1]->f; - - if (port < 0 || port > instance->plugin->descriptor->LADSPA_Plugin->PortCount) { - fprintf(stderr, "MusE: OSC: %s port number (%d) is out of range\n", - instance->friendly_name, port); - return 0; - } - if (instance->pluginPortControlInNumbers[port] == -1) { - fprintf(stderr, "MusE: OSC: %s port %d is not a control in\n", - instance->friendly_name, port); - return 0; - } - pluginControlIns[instance->pluginPortControlInNumbers[port]] = value; - if (verbose) { - printf("MusE: OSC: %s port %d = %f\n", - instance->friendly_name, port, value); - } -#endif - return 0; - } - -/* -//--------------------------------------------------------- -// oscExiting -//--------------------------------------------------------- - -int DssiSynthIF::oscExiting(lo_arg**) - { - //printf("not impl.: oscExiting\n"); - - // The gui is gone now, right? - _guiVisible = false; - - //const DSSI_Descriptor* dssi = synth->dssi; - //const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin; - //if(ld->deactivate) - // ld->deactivate(handle); - - if (uiOscPath == 0) { - printf("DssiSynthIF::oscExiting(): no uiOscPath\n"); - return 1; - } - char uiOscGuiPath[strlen(uiOscPath)+6]; - - sprintf(uiOscGuiPath, "%s/%s", uiOscPath, "quit"); - #ifdef DSSI_DEBUG - printf("DssiSynthIF::oscExiting(): sending quit to uiOscGuiPath:%s\n", uiOscGuiPath); - #endif - - lo_send(uiTarget, uiOscGuiPath, ""); - -#if 0 - int i; - - if (verbose) { - printf("MusE: OSC: got exiting notification for instance %d\n", - instance->number); - } - - if (instance->plugin) { - - // !!! No, this isn't safe -- plugins deactivated in this way - // would still be included in a run_multiple_synths call unless - // we re-jigged the instance array at the same time -- leave it - // for now - //if (instance->plugin->descriptor->LADSPA_Plugin->deactivate) { - // instance->plugin->descriptor->LADSPA_Plugin->deactivate - // (instanceHandles[instance->number]); - // } - // Leave this flag though, as we need it to determine when to exit - instance->inactive = 1; - } - - // Do we have any plugins left running? - - for (i = 0; i < instance_count; ++i) { - if (!instances[i].inactive) - return 0; - } - - if (verbose) { - printf("MusE: That was the last remaining plugin, exiting...\n"); - } - exiting = 1; -#endif - return 0; - } -*/ - -//--------------------------------------------------------- -// oscMidi -//--------------------------------------------------------- - -int DssiSynthIF::oscMidi(int a, int b, int c) - { - //int a = argv[0]->m[1]; - //int b = argv[0]->m[2]; - //int c = argv[0]->m[3]; - - if (a == ME_NOTEOFF) { - a = ME_NOTEON; - c = 0; - } - int channel = 0; // TODO: ?? - - int port = synti->midiPort(); - - //MidiEvent event(0, channel, a, b, c); - - if(port != -1) - { - MidiPlayEvent event(0, port, channel, a, b, c); - - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::oscMidi midi event chn:%d a:%d b:%d\n", event.channel(), event.dataA(), event.dataB()); - #endif - - midiPorts[port].sendEvent(event); - } - - //synti->playMidiEvent(&event); // TODO - // - //MidiDevice* md = dynamic_cast<MidiDevice*>(synti); - //if(md) - // md->putEvent(event); - // - //synti->putEvent(event); - // - - return 0; - } - -//--------------------------------------------------------- -// oscConfigure -//--------------------------------------------------------- - -int DssiSynthIF::oscConfigure(const char *key, const char *value) - { - //const char *key = (const char *)&argv[0]->s; - //const char *value = (const char *)&argv[1]->s; - - // This is pretty much the simplest legal implementation of - // configure in a DSSI host. - - // The host has the option to remember the set of (key,value) - // pairs associated with a particular instance, so that if it - // wants to restore the "same" instance on another occasion it can - // just call configure() on it for each of those pairs and so - // restore state without any input from a GUI. Any real-world GUI - // host will probably want to do that. This host doesn't have any - // concept of restoring an instance from one run to the next, so - // we don't bother remembering these at all. - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::oscConfigure synth name:%s key:%s value:%s\n", synti->name().toLatin1().constData(), key, value); - #endif - - // Add or modify the configuration map item. - synti->_stringParamMap.set(key, value); - - if (!strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, - strlen(DSSI_RESERVED_CONFIGURE_PREFIX))) { - fprintf(stderr, "MusE: OSC: UI for plugin '%s' attempted to use reserved configure key \"%s\", ignoring\n", - //synti->name().toAscii().data(), key); - synti->name().toLatin1().constData(), key); - - return 0; - } - - if (!synth->dssi->configure) - return 0; - - char* message = synth->dssi->configure(handle, key, value); - if (message) { - printf("MusE: on configure '%s' '%s', plugin '%s' returned error '%s'\n", - //key, value, synti->name().toAscii().data(), message); - key, value, synti->name().toLatin1().constData(), message); - - free(message); - } - - // also call back on UIs for plugins other than the one - // that requested this: - // if (n != instance->number && instances[n].uiTarget) { - // lo_send(instances[n].uiTarget, - // instances[n].ui_osc_configure_path, "ss", key, value); - // } - - // configure invalidates bank and program information, so - // we should do this again now: - queryPrograms(); - return 0; - } -#endif // OSC_SUPPORT - -//--------------------------------------------------------- -// queryPrograms -//--------------------------------------------------------- - -void DssiSynthIF::queryPrograms() - { - for (std::vector<DSSI_Program_Descriptor>::const_iterator i = programs.begin(); - i != programs.end(); ++i) { - free((void*)(i->Name)); - } - programs.clear(); - - //if (!(synth->dssi->get_program && synth->dssi->select_program)) - if (!synth->dssi->get_program) - return; - - for (int i = 0;; ++i) { - const DSSI_Program_Descriptor* pd = synth->dssi->get_program(handle, i); - if (pd == 0) - break; - DSSI_Program_Descriptor d; - d.Name = strdup(pd->Name); - d.Program = pd->Program; - d.Bank = pd->Bank; - programs.push_back(d); - } - } - -//--------------------------------------------------------- -// getPatchName -//--------------------------------------------------------- - -//QString DssiSynthIF::getPatchName(int, int prog) -const char* DssiSynthIF::getPatchName(int /*chan*/, int prog, MType /*type*/, bool /*drum*/) - { - unsigned program = prog & 0x7f; - int lbank = (prog >> 8) & 0xff; - int hbank = (prog >> 16) & 0xff; - - if (lbank == 0xff) - lbank = 0; - if (hbank == 0xff) - hbank = 0; - unsigned bank = (hbank << 8) + lbank; - - for (std::vector<DSSI_Program_Descriptor>::const_iterator i = programs.begin(); - i != programs.end(); ++i) { - if (i->Bank == bank && i->Program ==program) - return i->Name; - } - return "?"; - } - -//--------------------------------------------------------- -// populatePatchPopup -//--------------------------------------------------------- - -//void DssiSynthIF::populatePatchPopup(QMenu* menu, int) -void DssiSynthIF::populatePatchPopup(QMenu* menu, int /*ch*/, MType /*type*/, bool /*drum*/) - { - // The plugin can change the programs, patches etc. - // So make sure we're up to date by calling queryPrograms. - queryPrograms(); - - menu->clear(); - - for (std::vector<DSSI_Program_Descriptor>::const_iterator i = programs.begin(); - i != programs.end(); ++i) { - int bank = i->Bank; - int prog = i->Program; - int id = (bank << 16) + prog; - - QAction *act = menu->addAction(QString(i->Name)); - act->setData(id); - } - } - -int DssiSynthIF::getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max, int* initval) -{ - int controlPorts = synth->_controlInPorts; - if(id >= controlPorts) - //if(id >= midiCtl2PortMap.size()) - return 0; - - const DSSI_Descriptor* dssi = synth->dssi; - const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin; - - // Hmm, <map> has a weird [] operator. Would it work? - // For now just use duplicate code found in ::init() - //iMidiCtl2LadspaPort ip = midiCtl2PortMap[id]; - //int ctlnum = ip->first; - //int k = ip->second; - - int i = synth->pIdx[id]; - //int i = synth->pIdx[k]; - - //ladspaDefaultValue(ld, i, &controls[id].val); - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::getControllerInfo control port:%d port idx:%d name:%s\n", id, i, ld->PortNames[i]); - #endif - - int ctlnum = DSSI_NONE; - if(dssi->get_midi_controller_for_port) - ctlnum = dssi->get_midi_controller_for_port(handle, i); - - - // No controller number? Give it one. - if(ctlnum == DSSI_NONE) - { - // TODO: If neccesary... choose non-existing numbers... - //for(int k = 0; k < controlPorts; ++k) - //{ - // int i = synth->pIdx[k]; - //} - - // Simple but flawed solution: Start them at 0x60000 + 0x2000 = 0x62000. Max NRPN number is 0x3fff. - ctlnum = CTRL_NRPN14_OFFSET + 0x2000 + id; - } - else - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::getControllerInfo ctlnum:%d\n", ctlnum); - #endif - - int c = ctlnum; - // Can be both CC and NRPN! Prefer CC over NRPN. - if(DSSI_IS_CC(ctlnum)) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::getControllerInfo is CC control\n"); - #endif - - ctlnum = DSSI_CC_NUMBER(c); - - #ifdef DSSI_DEBUG - if(DSSI_IS_NRPN(ctlnum)) - printf("DssiSynthIF::getControllerInfo is also NRPN control. Using CC.\n"); - #endif - } - else - if(DSSI_IS_NRPN(ctlnum)) - { - #ifdef DSSI_DEBUG - printf("DssiSynthIF::getControllerInfo is NRPN control\n"); - #endif - - ctlnum = DSSI_NRPN_NUMBER(c) + CTRL_NRPN14_OFFSET; - } - } - - int def = CTRL_VAL_UNKNOWN; - if(ladspa2MidiControlValues(ld, i, ctlnum, min, max, &def)) - *initval = def; - else - *initval = CTRL_VAL_UNKNOWN; - - #ifdef DSSI_DEBUG - printf("DssiSynthIF::getControllerInfo passed ctlnum:%d min:%d max:%d initval:%d\n", ctlnum, *min, *max, *initval); - #endif - - *ctrl = ctlnum; - *name = ld->PortNames[i]; - return ++id; - - /* - // ...now create midi controllers for ports which did not define them ... - for(int k = 0; k < controlPorts; ++k) - { - int i = synth->pIdx[k]; - //controls[k].val = ladspaDefaultValue(ld, i); - ladspaDefaultValue(ld, i, &controls[k].val); - - printf("DssiSynthIF::getControllerInfo #2 control port:%d port idx:%d name:%s\n", k, i, ld->PortNames[i]); - - if(!dssi->get_midi_controller_for_port || (dssi->get_midi_controller_for_port(handle, i) == DSSI_NONE)) - { - int ctlnum; - //printf("DssiSynthIF::getControllerInfo #2 midi controller number:%d\n", ctlnum); - printf("DssiSynthIF::getControllerInfo #2 creating MidiController number:%d\n", ctlnum); - MidiController* mc = ladspa2MidiController(ld, i, ctlnum); - // Add to MidiInstrument controller list. - if(mc) - { - printf("DssiSynthIF::getControllerInfo #2 adding MidiController to instrument\n"); - ((MidiInstrument*)synti)->controller()->add(mc); - } - } - else - { - - } - } - */ - -} - -int DssiSynthIF::channels() const -{ - return synth->_outports > MAX_CHANNELS ? MAX_CHANNELS : synth->_outports; -} - -int DssiSynthIF::totalOutChannels() const -{ - return synth->_outports; -} - -int DssiSynthIF::totalInChannels() const -{ - return synth->_inports; -} - -//-------------------------------- -// Methods for PluginIBase: -//-------------------------------- - -bool DssiSynthIF::on() const { return true; } // Synth is not part of a rack plugin chain. Always on. -void DssiSynthIF::setOn(bool /*val*/) { } -int DssiSynthIF::pluginID() { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->UniqueID : 0; } -int DssiSynthIF::id() { return 0; } // Synth is not part of a rack plugin chain. Always 0. -QString DssiSynthIF::pluginLabel() const { return (synth && synth->dssi) ? QString(synth->dssi->LADSPA_Plugin->Label) : QString(); } -QString DssiSynthIF::name() const { return synti->name(); } -AudioTrack* DssiSynthIF::track() { return (AudioTrack*)synti; } -void DssiSynthIF::enableController(int i, bool v) { controls[i].enCtrl = v; } -bool DssiSynthIF::controllerEnabled(int i) const { return controls[i].enCtrl; } -bool DssiSynthIF::controllerEnabled2(int i) const { return controls[i].en2Ctrl; } -void DssiSynthIF::updateControllers() { } -void DssiSynthIF::writeConfiguration(int /*level*/, Xml& /*xml*/) { } -bool DssiSynthIF::readConfiguration(Xml& /*xml*/, bool /*readPreset*/) { return false; } -int DssiSynthIF::parameters() const { return synth ? synth->_controlInPorts : 0; } -void DssiSynthIF::setParam(int i, double val) { setParameter(i, val); } -double DssiSynthIF::param(int i) const { return getParameter(i); } -const char* DssiSynthIF::paramName(int i) { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->PortNames[i] : 0; } -//LADSPA_PortRangeHint DssiSynthIF::range(int i) { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->PortRangeHints[i] : 0; } -LADSPA_PortRangeHint DssiSynthIF::range(int i) { return synth->dssi->LADSPA_Plugin->PortRangeHints[i]; } - - -#else //DSSI_SUPPORT -void initDSSI() {} -#endif - |