zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit e429ffb45d85dcbe8a6c8a3d6dffcbd383e1e408
parent 87cc5f927e9187bec928ab73b3ece644e1c9c578
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Mon,  2 Mar 2015 20:57:02 -0500

DSSI: Get Plugin To Compile/Link Properly

Diffstat:
Msrc/CMakeLists.txt | 3++-
Msrc/Misc/MiddleWare.cpp | 254++++++++++---------------------------------------------------------------------
Msrc/Misc/MiddleWare.h | 9++++++++-
Msrc/Output/DSSIaudiooutput.cpp | 22++--------------------
Msrc/UI/Connection.cpp | 219++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/UI/Connection.h | 3+++
Msrc/UI/ConnectionDummy.cpp | 4++++
7 files changed, 269 insertions(+), 245 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt @@ -377,8 +377,9 @@ target_link_libraries(zynaddsubfx ${AUDIO_LIBRARIES} ) -if (DssiEnable AND FALSE) +if (DssiEnable) add_library(zynaddsubfx_dssi SHARED + UI/ConnectionDummy.cpp Output/DSSIaudiooutput.cpp ) diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp @@ -15,9 +15,6 @@ #include "../UI/Connection.h" #include "../UI/Fl_Osc_Interface.h" -#ifndef NO_UI -#include "../UI/Fl_Osc_Widget.H" -#endif #include <map> @@ -431,8 +428,6 @@ struct ParamStore PADnoteParameters *pad[NUM_MIDI_PARTS][NUM_KIT_ITEMS]; }; -static Fl_Osc_Interface *genOscInterface(class MiddleWareImpl*); - /* Implementation */ class MiddleWareImpl { @@ -544,7 +539,7 @@ class MiddleWareImpl } public: - MiddleWareImpl(void); + MiddleWareImpl(MiddleWare *mw); ~MiddleWareImpl(void); void warnMemoryLeaks(void); @@ -760,7 +755,7 @@ public: std::atomic_int actual_load[NUM_MIDI_PARTS]; }; -MiddleWareImpl::MiddleWareImpl(void) +MiddleWareImpl::MiddleWareImpl(MiddleWare *mw) { server = lo_server_new_with_proto(NULL, LO_UDP, liblo_error_cb); lo_server_add_method(server, NULL, NULL, handler_function, NULL); @@ -774,7 +769,7 @@ MiddleWareImpl::MiddleWareImpl(void) idle = 0; master = new Master(); - osc = genOscInterface(this); + osc = GUI::genOscInterface(mw); //Grab objects of interest from master obj_store.extractMaster(master); @@ -1122,226 +1117,14 @@ void MiddleWareImpl::write(const char *path, const char *args, va_list va) warnx("Failed to write message to '%s'", path); } -/****************************************************************************** - * OSC Interface For User Interface * - * * - * This is a largely out of date section of code * - * Most type specific write methods are no longer used * - * See UI/Fl_Osc_* to see what is actually used in this interface * - ******************************************************************************/ -class UI_Interface:public Fl_Osc_Interface -{ - public: - UI_Interface(MiddleWareImpl *impl_) - :impl(impl_) - {} - - void requestValue(string s) override - { - //Fl_Osc_Interface::requestValue(s); - if(last_url != "GUI") { - impl->write("/echo", "ss", "OSC_URL", "GUI"); - last_url = "GUI"; - } - - impl->write(s.c_str(),""); - } - - void write(string s, const char *args, ...) override - { - va_list va; - va_start(va, args); - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); - ////fprintf(stderr, "."); - //fprintf(stderr, "write(%s:%s)\n", s.c_str(), args); - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); - impl->write(s.c_str(), args, va); - va_end(va); - } - - void writeRaw(const char *msg) override - { - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); - ////fprintf(stderr, "."); - //fprintf(stderr, "rawWrite(%s:%s)\n", msg, rtosc_argument_string(msg)); - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); - impl->handleMsg(msg); - } - - void writeValue(string s, string ss) override - { - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); - //fprintf(stderr, "writevalue<string>(%s,%s)\n", s.c_str(),ss.c_str()); - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); - impl->write(s.c_str(), "s", ss.c_str()); - } - - void writeValue(string s, char c) override - { - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); - //fprintf(stderr, "writevalue<char>(%s,%d)\n", s.c_str(),c); - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); - impl->write(s.c_str(), "c", c); - } - - void writeValue(string s, float f) override - { - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); - //fprintf(stderr, "writevalue<float>(%s,%f)\n", s.c_str(),f); - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); - impl->write(s.c_str(), "f", f); - } - - void createLink(string s, class Fl_Osc_Widget*w) override - { - assert(s.length() != 0); - Fl_Osc_Interface::createLink(s,w); - assert(!strstr(s.c_str(), "/part0/kit-1")); - map.insert(std::pair<string,Fl_Osc_Widget*>(s,w)); - } - - void renameLink(string old, string newer, Fl_Osc_Widget *w) override - { - //fprintf(stdout, "renameLink('%s','%s',%p)\n", - // old.c_str(), newer.c_str(), w); - removeLink(old, w); - createLink(newer, w); - } - - void removeLink(string s, class Fl_Osc_Widget*w) override - { - for(auto i = map.begin(); i != map.end(); ++i) { - if(i->first == s && i->second == w) { - map.erase(i); - break; - } - } - //printf("[%d] removing '%s' (%p)...\n", map.size(), s.c_str(), w); - } - - virtual void removeLink(class Fl_Osc_Widget *w) - { - bool processing = true; - while(processing) - { - //Verify Iterator invalidation sillyness - processing = false;//Exit if no new elements are found - for(auto i = map.begin(); i != map.end(); ++i) { - if(i->second == w) { - //printf("[%d] removing '%s' (%p)...\n", map.size()-1, - // i->first.c_str(), w); - map.erase(i); - processing = true; - break; - } - } - } - } - - //A very simplistic implementation of a UI agnostic refresh method - virtual void damage(const char *path) - { -#ifndef NO_UI - //printf("\n\nDamage(\"%s\")\n", path); - for(auto pair:map) { - if(strstr(pair.first.c_str(), path)) { - auto *tmp = dynamic_cast<Fl_Widget*>(pair.second); - //if(tmp) - // printf("%x, %d %d [%s]\n", (int)pair.second, tmp->visible_r(), tmp->visible(), pair.first.c_str()); - //else - // printf("%x, (NULL)[%s]\n", (int)pair.second,pair.first.c_str()); - if(!tmp || tmp->visible_r()) - pair.second->update(); - } - } -#endif - } - - void tryLink(const char *msg) override - { - - //DEBUG - //if(strcmp(msg, "/vu-meter"))//Ignore repeated message - // printf("trying the link for a '%s'<%s>\n", msg, rtosc_argument_string(msg)); - const char *handle = rindex(msg,'/'); - if(handle) - ++handle; - - int found_count = 0; - - auto range = map.equal_range(msg); - for(auto itr = range.first; itr != range.second; ++itr) { - auto widget = itr->second; - found_count++; - const char *arg_str = rtosc_argument_string(msg); - - //Always provide the raw message - widget->OSC_raw(msg); - - if(!strcmp(arg_str, "b")) { - widget->OSC_value(rtosc_argument(msg,0).b.len, - rtosc_argument(msg,0).b.data, - handle); - } else if(!strcmp(arg_str, "c")) { - widget->OSC_value((char)rtosc_argument(msg,0).i, - handle); - } else if(!strcmp(arg_str, "s")) { - widget->OSC_value((const char*)rtosc_argument(msg,0).s, - handle); - } else if(!strcmp(arg_str, "i")) { - widget->OSC_value((int)rtosc_argument(msg,0).i, - handle); - } else if(!strcmp(arg_str, "f")) { - widget->OSC_value((float)rtosc_argument(msg,0).f, - handle); - } else if(!strcmp(arg_str, "T") || !strcmp(arg_str, "F")) { - widget->OSC_value((bool)rtosc_argument(msg,0).T, handle); - } - } - - if(found_count == 0 - && strcmp(msg, "/vu-meter") - && strcmp(msg, "undo_change") - && !strstr(msg, "parameter") - && !strstr(msg, "Prespoint")) { - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40); - //fprintf(stderr, "Unknown widget '%s'\n", msg); - //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); - } - }; - - void dumpLookupTable(void) - { - if(!map.empty()) { - printf("Leaked controls:\n"); - for(auto i = map.begin(); i != map.end(); ++i) { - printf("Known control '%s' (%p)...\n", i->first.c_str(), i->second); - } - } - } - - - private: - std::multimap<string,Fl_Osc_Widget*> map; - MiddleWareImpl *impl; -}; - void MiddleWareImpl::warnMemoryLeaks(void) -{ - UI_Interface *o = (UI_Interface*)osc; - o->dumpLookupTable(); -} - -Fl_Osc_Interface *genOscInterface(class MiddleWareImpl *impl) -{ - return new UI_Interface(impl); -} +{} /****************************************************************************** * MidleWare Forwarding Stubs * ******************************************************************************/ MiddleWare::MiddleWare(void) -:impl(new MiddleWareImpl()) +:impl(new MiddleWareImpl(this)) {} MiddleWare::~MiddleWare(void) { @@ -1380,8 +1163,35 @@ void MiddleWare::transmitMsg(const char *msg) { impl->handleMsg(msg); } + +void MiddleWare::transmitMsg(const char *path, const char *args, ...) +{ + char buffer[1024]; + va_list va; + va_start(va,args); + if(rtosc_vmessage(buffer,1024,path,args,va)) + transmitMsg(buffer); + va_end(va); +} + +void MiddleWare::transmitMsg(const char *path, const char *args, va_list va) +{ + char buffer[1024]; + if(rtosc_vmessage(buffer, 1024, path, args, va)) + transmitMsg(buffer); +} void MiddleWare::pendingSetProgram(int part) { impl->pending_load[part]++; } + +std::string MiddleWare::activeUrl(void) +{ + return last_url; +} + +void MiddleWare::activeUrl(std::string u) +{ + last_url = u; +} diff --git a/src/Misc/MiddleWare.h b/src/Misc/MiddleWare.h @@ -19,10 +19,17 @@ class MiddleWare void tick(void); //Do A Readonly Operation (For Parameter Copy) void doReadOnlyOp(std::function<void()>); - //Handle a rtosc Message + //Handle a rtosc Message uToB void transmitMsg(const char *); + //Handle a rtosc Message uToB + void transmitMsg(const char *, const char *args, ...); + //Handle a rtosc Message uToB + void transmitMsg(const char *, const char *args, va_list va); //Indicate that a program will be loaded on a known part void pendingSetProgram(int part); + //Get/Set the active bToU url + std::string activeUrl(void); + void activeUrl(std::string u); private: class MiddleWareImpl *impl; }; diff --git a/src/Output/DSSIaudiooutput.cpp b/src/Output/DSSIaudiooutput.cpp @@ -43,6 +43,7 @@ class WavFile; namespace Nio { bool start(void){return 1;}; void stop(void){}; + void masterSwap(Master *){}; void waveNew(WavFile *){} void waveStart(void){} void waveStop(void){} @@ -365,24 +366,11 @@ void DSSIaudiooutput::selectProgram(unsigned long bank, unsigned long program) if((bank < master->bank.banks.size()) && (program < BANK_SIZE)) { const std::string bankdir = master->bank.banks[bank].dir; if(!bankdir.empty()) { - pthread_mutex_lock(&master->mutex); - - /* We have to turn off the CheckPADsynth functionality, else - * the program change takes way too long and we get timeouts - * and hence zombies (!) */ - int save = config.cfg.CheckPADsynth; - config.cfg.CheckPADsynth = 0; - /* Load the bank... */ master->bank.loadbank(bankdir); - /* restore the CheckPADsynth flag */ - config.cfg.CheckPADsynth = save; - /* Now load the instrument... */ master->bank.loadfromslot((unsigned int)program, master->part[0]); - - pthread_mutex_unlock(&master->mutex); } } } @@ -441,7 +429,6 @@ void DSSIaudiooutput::runSynth(unsigned long sample_count, unsigned long event_index = 0; unsigned long next_event_frame = 0; unsigned long to_frame = 0; - pthread_mutex_lock(&master->mutex); do { /* Find the time of the next event, if any */ @@ -491,7 +478,6 @@ void DSSIaudiooutput::runSynth(unsigned long sample_count, // Keep going until we have the desired total length of sample... } while(to_frame < sample_count); - pthread_mutex_unlock(&master->mutex); } /** @@ -547,7 +533,7 @@ DSSI_Descriptor *DSSIaudiooutput::initDssiDescriptor() newLadspaDescriptor->Name = "ZynAddSubFX"; newLadspaDescriptor->Maker = "Nasca Octavian Paul <zynaddsubfx@yahoo.com>"; - newLadspaDescriptor->Copyright = "GNU General Public License v.2"; + newLadspaDescriptor->Copyright = "GNU General Public License v2"; newLadspaDescriptor->PortCount = 2; newPortNames = new const char *[newLadspaDescriptor->PortCount]; @@ -646,10 +632,8 @@ DSSIaudiooutput::~DSSIaudiooutput() void DSSIaudiooutput::initBanks(void) { if(!banksInited) { - pthread_mutex_lock(&master->mutex); master->bank.rescanforbanks(); banksInited = true; - pthread_mutex_unlock(&master->mutex); } } @@ -687,7 +671,6 @@ long DSSIaudiooutput::bankNoToMap = 1; */ bool DSSIaudiooutput::mapNextBank() { - pthread_mutex_lock(&master->mutex); Bank &bank = master->bank; bool retval; if((bankNoToMap >= (int)bank.banks.size()) @@ -706,6 +689,5 @@ bool DSSIaudiooutput::mapNextBank() bankNoToMap++; retval = true; } - pthread_mutex_unlock(&master->mutex); return retval; } diff --git a/src/UI/Connection.cpp b/src/UI/Connection.cpp @@ -1,6 +1,8 @@ #include "Connection.h" #include "Fl_Osc_Interface.h" #include "../globals.h" +#include <map> +#include <cassert> #include <rtosc/rtosc.h> #include <rtosc/ports.h> @@ -10,6 +12,7 @@ #include "Fl_Osc_Tree.H" #include "common.H" #include "MasterUI.h" +#include "../Misc/MiddleWare.h" #ifdef NTK_GUI #include <FL/Fl_Shared_Image.H> @@ -18,6 +21,10 @@ #include <err.h> #endif // NTK_GUI +#ifndef NO_UI +#include "Fl_Osc_Widget.H" +#endif + using namespace GUI; class MasterUI *ui; extern rtosc::UndoHistory undo; @@ -112,7 +119,7 @@ void GUI::destroyUi(ui_handle_t ui) delete static_cast<MasterUI*>(ui); } -#define BEGIN(x) {x,"",NULL,[](const char *m, rtosc::RtData d){ \ +#define BEGIN(x) {x,":non-realtime\0",NULL,[](const char *m, rtosc::RtData d){ \ MasterUI *ui = static_cast<MasterUI*>(d.obj); \ rtosc_arg_t a0 = {0}, a1 = {0}; \ if(rtosc_narguments(m) > 0) \ @@ -191,3 +198,213 @@ void GUI::tickUi(ui_handle_t) { Fl::wait(0.02f); } + +/****************************************************************************** + * OSC Interface For User Interface * + * * + * This is a largely out of date section of code * + * Most type specific write methods are no longer used * + * See UI/Fl_Osc_* to see what is actually used in this interface * + ******************************************************************************/ +class UI_Interface:public Fl_Osc_Interface +{ + public: + UI_Interface(MiddleWare *impl_) + :impl(impl_) + {} + + void requestValue(string s) override + { + //Fl_Osc_Interface::requestValue(s); + if(impl->activeUrl() != "GUI") { + impl->transmitMsg("/echo", "ss", "OSC_URL", "GUI"); + impl->activeUrl("GUI"); + } + + impl->transmitMsg(s.c_str(),""); + } + + void write(string s, const char *args, ...) override + { + va_list va; + va_start(va, args); + //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); + ////fprintf(stderr, "."); + //fprintf(stderr, "write(%s:%s)\n", s.c_str(), args); + //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); + impl->transmitMsg(s.c_str(), args, va); + va_end(va); + } + + void writeRaw(const char *msg) override + { + fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); + //fprintf(stderr, "."); + fprintf(stderr, "rawWrite(%s:%s)\n", msg, rtosc_argument_string(msg)); + fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); + impl->transmitMsg(msg); + } + + void writeValue(string s, string ss) override + { + fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); + fprintf(stderr, "writevalue<string>(%s,%s)\n", s.c_str(),ss.c_str()); + fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); + impl->transmitMsg(s.c_str(), "s", ss.c_str()); + } + + void writeValue(string s, char c) override + { + fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); + fprintf(stderr, "writevalue<char>(%s,%d)\n", s.c_str(),c); + fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); + impl->transmitMsg(s.c_str(), "c", c); + } + + void writeValue(string s, float f) override + { + fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40); + fprintf(stderr, "writevalue<float>(%s,%f)\n", s.c_str(),f); + fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); + impl->transmitMsg(s.c_str(), "f", f); + } + + void createLink(string s, class Fl_Osc_Widget*w) override + { + assert(s.length() != 0); + Fl_Osc_Interface::createLink(s,w); + assert(!strstr(s.c_str(), "/part0/kit-1")); + map.insert(std::pair<string,Fl_Osc_Widget*>(s,w)); + } + + void renameLink(string old, string newer, Fl_Osc_Widget *w) override + { + fprintf(stdout, "renameLink('%s','%s',%p)\n", + old.c_str(), newer.c_str(), w); + removeLink(old, w); + createLink(newer, w); + } + + void removeLink(string s, class Fl_Osc_Widget*w) override + { + for(auto i = map.begin(); i != map.end(); ++i) { + if(i->first == s && i->second == w) { + map.erase(i); + break; + } + } + //printf("[%d] removing '%s' (%p)...\n", map.size(), s.c_str(), w); + } + + virtual void removeLink(class Fl_Osc_Widget *w) override + { + bool processing = true; + while(processing) + { + //Verify Iterator invalidation sillyness + processing = false;//Exit if no new elements are found + for(auto i = map.begin(); i != map.end(); ++i) { + if(i->second == w) { + //printf("[%d] removing '%s' (%p)...\n", map.size()-1, + // i->first.c_str(), w); + map.erase(i); + processing = true; + break; + } + } + } + } + + //A very simplistic implementation of a UI agnostic refresh method + virtual void damage(const char *path) override + { +#ifndef NO_UI + //printf("\n\nDamage(\"%s\")\n", path); + for(auto pair:map) { + if(strstr(pair.first.c_str(), path)) { + auto *tmp = dynamic_cast<Fl_Widget*>(pair.second); + //if(tmp) + // printf("%x, %d %d [%s]\n", (int)pair.second, tmp->visible_r(), tmp->visible(), pair.first.c_str()); + //else + // printf("%x, (NULL)[%s]\n", (int)pair.second,pair.first.c_str()); + if(!tmp || tmp->visible_r()) + pair.second->update(); + } + } +#endif + } + + void tryLink(const char *msg) override + { + + //DEBUG + //if(strcmp(msg, "/vu-meter"))//Ignore repeated message + // printf("trying the link for a '%s'<%s>\n", msg, rtosc_argument_string(msg)); + const char *handle = rindex(msg,'/'); + if(handle) + ++handle; + + int found_count = 0; + + auto range = map.equal_range(msg); + for(auto itr = range.first; itr != range.second; ++itr) { + auto widget = itr->second; + found_count++; + const char *arg_str = rtosc_argument_string(msg); + + //Always provide the raw message + widget->OSC_raw(msg); + + if(!strcmp(arg_str, "b")) { + widget->OSC_value(rtosc_argument(msg,0).b.len, + rtosc_argument(msg,0).b.data, + handle); + } else if(!strcmp(arg_str, "c")) { + widget->OSC_value((char)rtosc_argument(msg,0).i, + handle); + } else if(!strcmp(arg_str, "s")) { + widget->OSC_value((const char*)rtosc_argument(msg,0).s, + handle); + } else if(!strcmp(arg_str, "i")) { + widget->OSC_value((int)rtosc_argument(msg,0).i, + handle); + } else if(!strcmp(arg_str, "f")) { + widget->OSC_value((float)rtosc_argument(msg,0).f, + handle); + } else if(!strcmp(arg_str, "T") || !strcmp(arg_str, "F")) { + widget->OSC_value((bool)rtosc_argument(msg,0).T, handle); + } + } + + if(found_count == 0 + && strcmp(msg, "/vu-meter") + && strcmp(msg, "undo_change") + && !strstr(msg, "parameter") + && !strstr(msg, "Prespoint")) { + //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40); + //fprintf(stderr, "Unknown widget '%s'\n", msg); + //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40); + } + }; + + void dumpLookupTable(void) + { + if(!map.empty()) { + printf("Leaked controls:\n"); + for(auto i = map.begin(); i != map.end(); ++i) { + printf("Known control '%s' (%p)...\n", i->first.c_str(), i->second); + } + } + } + + + private: + std::multimap<string,Fl_Osc_Widget*> map; + MiddleWare *impl; +}; + +Fl_Osc_Interface *GUI::genOscInterface(MiddleWare *mw) +{ + return new UI_Interface(mw); +} + diff --git a/src/UI/Connection.h b/src/UI/Connection.h @@ -3,6 +3,7 @@ //remove the tendrils of the UI from the RT code class Fl_Osc_Interface; +class MiddleWare; namespace GUI { typedef void *ui_handle_t; @@ -12,4 +13,6 @@ void destroyUi(ui_handle_t); void raiseUi(ui_handle_t, const char *); void raiseUi(ui_handle_t, const char *, const char *, ...); void tickUi(ui_handle_t); + +Fl_Osc_Interface *genOscInterface(MiddleWare*); }; diff --git a/src/UI/ConnectionDummy.cpp b/src/UI/ConnectionDummy.cpp @@ -18,4 +18,8 @@ void tickUi(ui_handle_t) { usleep(100000); } +Fl_Osc_Interface *genOscInterface(MiddleWare*) +{ + return NULL; +} };