diff --git a/ptap/ptapui.cpp b/ptap/ptapui.cpp index d5b95e1..0ffa841 100644 --- a/ptap/ptapui.cpp +++ b/ptap/ptapui.cpp @@ -13,58 +13,23 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define _BSD_SOURCE 1 -#include /* for usleep */ - -#include -#include -#include -#include -#include -#include -#include #include -#include #include "../pui/pui.h" +#include "../pui/lv2pui.h" #include "ptap.h" -/*struct PTapUI : PTextures { - PuglView *view; - pthread_t thread; - LV2UI_Write_Function write; - LV2UI_Controller controller; +struct PTapUI : LV2PUi { int width; int height; - bool exit; - int mx; - int my; - int mb; - int mm; - Widget *active; - - Container *widget; - - void InitWidgets(); -};*/ - -struct PTapUI : PUi { - pthread_t thread; - LV2UI_Write_Function write; - LV2UI_Controller controller; - int width; - int height; - bool exit; - - virtual ~PTapUI() {} - - void InitWidgets(); - - /* virtual */ void ParameterChanged(const Widget *w); + /* virtual */ void InitWidgets(); }; void PTapUI::InitWidgets() { + this->width = 250 + 50 * (NUM_TAPS + NUM_CHANNELS + 1); + this->height = 660; + char tmp[128]; scale = 1.0f; @@ -179,118 +144,10 @@ void PTapUI::InitWidgets() this->widget->Pack(tooltip); } -static void *ui_thread(void *ptr) -{ - PTapUI *pui = (PTapUI *)ptr; - while (!pui->exit) { - usleep(1000000 / 25); - puglProcessEvents(pui->view); - } - return NULL; -} +struct FLV2PUi_PTapUI : LV2PUiFactory { + /* virtual */ const char *GetUri() { return PTAP_URI "#X11UI"; } -void PTapUI::ParameterChanged(const Widget *w) -{ - if (w->port == UINT_MAX) return; - - this->write(this->controller, w->port, sizeof w->value, 0, &w->value); - - char tmp[64]; - snprintf(tmp, sizeof tmp, "(%s) %s: %0.4f", w->group, w->label, w->value); - tooltip->SetLabel(tmp); -} - -static LV2UI_Handle ptapui_instantiate( - const LV2UI_Descriptor *descriptor, - const char *plugin_uri, - const char *bundle_path, - LV2UI_Write_Function write_function, - LV2UI_Controller controller, - LV2UI_Widget *widget, - const LV2_Feature *const *host_features) -{ - PuglNativeWindow parent = 0; - LV2UI_Resize *resize = NULL; - for (; host_features && *host_features; host_features++) { - if (!strcmp((*host_features)->URI, LV2_UI__parent)) { - parent = (PuglNativeWindow)(*host_features)->data; - } else if (!strcmp((*host_features)->URI, LV2_UI__resize)) { - resize = (LV2UI_Resize *)(*host_features)->data; - } - } - - if (!parent) { - fprintf(stderr, "error: ptapui: No parent window provided.\n"); - return NULL; - } - - PTapUI *pui = new PTapUI(); - pui->write = write_function; - pui->controller = controller; - pui->width = 250 + 50 * (NUM_TAPS + NUM_CHANNELS + 1); - pui->height = 660; - pui->exit = false; - - pui->InitWidgets(); - - pui->view = puglCreate(parent, "PTap", pui->width, pui->height, true); - puglSetHandle(pui->view, pui); - - pui->SetFunc(); - - if (resize) { - resize->ui_resize(resize->handle, pui->width, pui->height); - } - - pthread_create(&pui->thread, NULL, ui_thread, pui); - - *widget = (void*)puglGetNativeWindow(pui->view); - return pui; -} - -static void ptapui_cleanup(LV2UI_Handle ui) -{ - PTapUI *pui = (PTapUI *)ui; - pui->exit = true; - pthread_join(pui->thread, NULL); - puglDestroy(pui->view); - delete pui; -} - -static void ptapui_port_event( - LV2UI_Handle ui, - uint32_t port_index, - uint32_t buffer_size, - uint32_t format, - const void *buffer) -{ - PUi *pui = (PUi *)ui; - Widget *w = pui->widget->GetWidget(port_index); - if (!w) return; - - w->SetValue(*((float *)buffer)); - pui->Repaint(); -} - -static const void *ptapui_extension_data(const char *uri) -{ - return NULL; -} - -static const LV2UI_Descriptor s_lv2uidescriptor = -{ - PTAP_URI "#X11UI", - &ptapui_instantiate, - &ptapui_cleanup, - &ptapui_port_event, - &ptapui_extension_data, + /* virtual */ LV2PUi *CreateInstance() { return new PTapUI(); } }; -const LV2UI_Descriptor *lv2ui_descriptor(uint32_t index) -{ - if (index == 0) { - return &s_lv2uidescriptor; - } - - return NULL; -} +static FLV2PUi_PTapUI iFLV2PUi_PTapUI; diff --git a/pui/Makefile b/pui/Makefile index 2cbdefe..4a4c59d 100644 --- a/pui/Makefile +++ b/pui/Makefile @@ -7,6 +7,7 @@ LDFLAGS += `pkg-config ftgl pugl-0 --libs` PUISRC := button.cpp PUISRC += container.cpp PUISRC += label.cpp +PUISRC += lv2pui.cpp PUISRC += knob.cpp PUISRC += pui.cpp PUISRC += slider.cpp diff --git a/pui/lv2pui.cpp b/pui/lv2pui.cpp new file mode 100644 index 0000000..85f8ead --- /dev/null +++ b/pui/lv2pui.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include "pui.h" +#include "lv2pui.h" + +static void *lv2pui_thread(void *ptr) +{ + LV2PUi *lv2pui = (LV2PUi *)ptr; + while (!lv2pui->exit) { + usleep(1000000 / 25); + puglProcessEvents(lv2pui->view); + } + return NULL; +} + +void LV2PUi::Instantiate( + const LV2UI_Descriptor *descriptor, + const char *bundle_path, + LV2UI_Write_Function write_function, + LV2UI_Controller controller, + LV2UI_Widget *widget, + const LV2_Feature *const *features) +{ + PuglNativeWindow parent = 0; + for (; features && *features; ++features) { + if (!strcmp((*features)->URI, LV2_UI__parent)) { + parent = (PuglNativeWindow)(*features)->data; + } else if (!strcmp((*features)->URI, LV2_UI__resize)) { + this->resize = (LV2UI_Resize *)(*features)->data; + } + } + + this->write = write_function; + this->controller = controller; + this->exit = false; + + this->InitWidgets(); + + int w = this->widget->w; + int h = this->widget->h; + + this->view = puglCreate(parent, "Test", w, h, true); + puglSetHandle(this->view, this); + this->SetFunc(); + + if (this->resize) { + this->resize->ui_resize(this->resize->handle, w, h); + } + + pthread_create(&this->thread, NULL, &lv2pui_thread, this); + + *widget = (void *)puglGetNativeWindow(this->view); +} + +static LV2UI_Handle lv2pui_instantiate( + const LV2UI_Descriptor *descriptor, + const char *plugin_uri, + const char *bundle_path, + LV2UI_Write_Function write_function, + LV2UI_Controller controller, + LV2UI_Widget *widget, + const LV2_Feature *const *features) +{ + char uri[128]; + snprintf(uri, sizeof uri, "%s#X11UI", plugin_uri); + + LV2PUi *lv2pui = LV2PUiFactoryBase::CreateInstance(uri); + if (!lv2pui) return NULL; + + lv2pui->Instantiate(descriptor, bundle_path, write_function, controller, widget, features); + return lv2pui; +} + +LV2PUi::~LV2PUi() +{ + this->exit = true; + pthread_join(this->thread, NULL); + puglDestroy(this->view); +} + +static void lv2pui_cleanup(LV2UI_Handle handle) +{ + LV2PUi *lv2pui = (LV2PUi *)handle; + delete lv2pui; +} + +void LV2PUi::ParameterChanged(const Widget *w) +{ + if (w->port == UINT_MAX) return; + + this->write(this->controller, w->port, sizeof w->value, 0, &w->value); + + if (!tooltip) return; + + char tmp[128]; + snprintf(tmp, sizeof tmp, "(%s): %s: %0.4f", w->group, w->label, w->value); + tooltip->SetLabel(tmp); +} + +void LV2PUi::PortEvent(uint32_t port_index, uint32_t buffer_size, uint32_t format, const void *buffer) +{ + Widget *w = this->widget->GetWidget(port_index); + if (!w) return; + + w->SetValue(*((float *)buffer)); + this->Repaint(); +} + +static void lv2pui_port_event( + LV2UI_Handle handle, + uint32_t port_index, + uint32_t buffer_size, + uint32_t format, + const void *buffer) +{ + LV2PUi *lv2pui = (LV2PUi *)handle; + lv2pui->PortEvent(port_index, buffer_size, format, buffer); +} + +static const void *lv2pui_extension_data(const char *uri) +{ + return NULL; +} + +static LV2UI_Descriptor s_lv2ui_descriptor = { + NULL, + &lv2pui_instantiate, + &lv2pui_cleanup, + &lv2pui_port_event, + &lv2pui_extension_data, +}; + +const LV2UI_Descriptor *lv2ui_descriptor(uint32_t index) +{ + const char *uri = LV2PUiFactoryBase::GetUri(index); + if (!uri) return NULL; + + s_lv2ui_descriptor.URI = uri; + return &s_lv2ui_descriptor; +} diff --git a/pui/lv2pui.h b/pui/lv2pui.h new file mode 100644 index 0000000..c2ca176 --- /dev/null +++ b/pui/lv2pui.h @@ -0,0 +1,113 @@ +#ifndef LV2PUI_H +#define LV2PUI_H + +#include +#include +#include + +struct LV2PUi : PUi { + pthread_t thread; + bool exit; + + LV2UI_Write_Function write; + LV2UI_Controller controller; + LV2UI_Resize *resize; + + virtual ~LV2PUi(); + + virtual void Instantiate( + const LV2UI_Descriptor *descriptor, + const char *bundle_path, + LV2UI_Write_Function write_function, + LV2UI_Controller controller, + LV2UI_Widget *widget, + const LV2_Feature *const *features + ); + + virtual void PortEvent(uint32_t port_index, uint32_t buffer_size, uint32_t format, const void *buffer); + + /* virtual */ void ParameterChanged(const Widget *w); +}; + +struct StringCompare { + bool operator () (const char *a, const char *b) const + { + return strcmp(a, b) < 0; + } +}; + +struct LV2PUiFactoryBase { +private: + const char *uri; + + typedef std::map LV2PUis; + + static LV2PUis &GetLV2PUis() + { + static LV2PUis &s_lv2puis = *new LV2PUis(); + return s_lv2puis; + } + +protected: + void RegisterLV2PUi(const char *uri) + { + if (!uri) return; + + this->uri = uri; + + //std::pair P = ; + GetLV2PUis().insert(LV2PUis::value_type(uri, this)); + } + +public: + LV2PUiFactoryBase() : uri(NULL) {} + + virtual ~LV2PUiFactoryBase() + { + if (!this->uri) return; + GetLV2PUis().erase(this->uri); + if (GetLV2PUis().empty()) delete &GetLV2PUis(); + } + + static LV2PUi *CreateInstance(const char *uri) + { + if (!uri) return NULL; + if (GetLV2PUis().size() == 0) return NULL; + + LV2PUis::iterator it = GetLV2PUis().begin(); + for (; it != GetLV2PUis().end(); ++it) { + LV2PUiFactoryBase *b = (*it).second; + if (!strcmp(uri, b->uri)) { + return b->CreateInstance(); + } + } + + return NULL; + } + + static const char *GetUri(uint32_t index) + { + if (GetLV2PUis().size() <= index) return NULL; + + LV2PUis::iterator it = GetLV2PUis().begin(); + for (; it != GetLV2PUis().end(); ++it) { + if (!index--) { + LV2PUiFactoryBase *b = (*it).second; + return b->uri; + } + } + + return NULL; + } + + virtual LV2PUi *CreateInstance() = 0; +}; + +template +struct LV2PUiFactory : LV2PUiFactoryBase { + LV2PUiFactory() { this->RegisterLV2PUi(((T *)this)->GetUri()); } + + const char *GetUri(); +}; + +#endif /* LV2PUI_H */ diff --git a/pui/pui.h b/pui/pui.h index 676fb55..b6a0441 100644 --- a/pui/pui.h +++ b/pui/pui.h @@ -39,6 +39,8 @@ struct PUi : PTextures { virtual ~PUi(); + virtual void InitWidgets() = 0; + inline void Repaint() { puglPostRedisplay(this->view); } void OnReshape(int w, int h);