#define _BSD_SOURCE 1 #include /* for usleep */ #include #include #include #include #include #include #include #include #include #include "../pui/pui.h" #include "ptap.h" /*struct PTapUI : PTextures { PuglView *view; pthread_t thread; LV2UI_Write_Function write; LV2UI_Controller controller; 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); }; void PTapUI::InitWidgets() { char tmp[128]; scale = 1.0f; widget = new Container(); widget->back = 1; widget->colour = Colour(1, 1, 1, 1); widget->w = this->width * scale; widget->h = this->height * scale; int padding = 4; int cols = 2; int rows = (NUM_TAPS + NUM_CHANNELS + cols - 1) / cols; int c_w = (widget->w - padding * cols - padding) / cols; int c_h = (widget->h - 25 - padding * rows - padding) / rows; Container *t = new Container(); t->colour = Colour(0, 0, 0, .5f); t->x = 0; t->y = 0; t->w = widget->w; t->h = 25; this->widget->Pack(t); int slide_w = 25; // int slide_h = c_h - 25; for (int i = 0; i < NUM_TAPS + NUM_CHANNELS; i++) { Container *c = new VBox(); if (i < NUM_TAPS) c->frame = Colour(0, 0, 0, .15f); c->x = (i & 1) * (c_w + padding) + padding; c->y = (i >> 1) * (c_h + padding) + padding + 25; c->w = c_w; c->h = c_h; c->padding = padding; Container *c1 = new Container(); c1->h = 16; c->Pack(c1); Container *c_strip = new HBox(); c_strip->h = -1; c_strip->padding = padding; c->Pack(c_strip); Container *c_taps = new HBox(); if (i >= NUM_TAPS) c_taps->colour = Colour(1, 1, 1, 0.15f); c_taps->w = slide_w * NUM_TAPS; c_strip->Pack(c_taps); Container *c_ins = new HBox(); if (i >= NUM_TAPS) c_ins->colour = Colour(1, 1, 1, 0.15f); c_ins->w = slide_w * NUM_CHANNELS; c_strip->Pack(c_ins); if (i < NUM_TAPS) { snprintf(tmp, sizeof tmp, "Tap %d", i + 1); } else { strncpy(tmp, i == NUM_TAPS ? "Left Out" : "Right Out", sizeof tmp); } for (int j = 0; j < NUM_TAPS; j++) { Slider *slider = new VSlider(); strncpy(slider->group, tmp, sizeof slider->group); snprintf(slider->label, sizeof slider->label, "%d", j + 1); slider->big = false; if (i == j) { slider->colour = Colour(.5f, .7f, 1, 1); } else { slider->colour = Colour(.6f, .6f, .6f, 1); } slider->w = slide_w; slider->min = -1.f; slider->max = 1.f; slider->port = TAP_MATRIX + i * NUM_GAINS + j; c_taps->Pack(slider); } for (int j = 0; j < NUM_CHANNELS; j++) { Slider *slider = new VSlider(); strncpy(slider->group, tmp, sizeof slider->group); strncpy(slider->label, j == 0 ? "Left" : "Right", sizeof slider->label); slider->big = false; slider->w = slide_w; slider->min = -1.f; slider->max = 1.f; slider->port = TAP_MATRIX + i * NUM_GAINS + NUM_TAPS + j; c_ins->Pack(slider); } Slider *gain = new VSlider(); strncpy(gain->group, tmp, sizeof gain->group); strncpy(gain->label, "Gain", sizeof gain->label); gain->big = i >= NUM_TAPS; gain->colour = Colour(1, .2f, .2f, 1); gain->w = slide_w; gain->min = -1.f; gain->max = 1.f; gain->port = TAP_GAINS + i; c_strip->Pack(gain); if (i < NUM_TAPS) { Knob *delay = new Knob(); strncpy(delay->group, tmp, sizeof delay->group); strncpy(delay->label, "Delay", sizeof delay->label); delay->w = -1; delay->min = 0.f; delay->max = 10.f; delay->port = TAP_DELAYS + i; c_strip->Pack(delay); } this->widget->Pack(c); } tooltip = new Label(); tooltip->x = widget->w * 0.5f; tooltip->y = 10; tooltip->colour = Colour(1, 1, 1, 1); tooltip->SetLabel("INIT"); 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; } 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, }; const LV2UI_Descriptor *lv2ui_descriptor(uint32_t index) { if (index == 0) { return &s_lv2uidescriptor; } return NULL; }