pplugins/ptap/ptapui.cpp

291 lines
6.2 KiB
C++

#define _BSD_SOURCE 1
#include <unistd.h> /* for usleep */
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lv2.h>
#include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
#include <pugl/pugl.h>
#include <limits.h>
#include "../pui/pui.h"
#define TAPS 6
/*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 = true;
widget->colour = Colour(1, 1, 1, 1);
widget->w = this->width * scale;
widget->h = this->height * scale;
int padding = 4;
int c_w = (widget->w - padding * 3) * 0.5f;
int c_h = (widget->h - 25 - padding * 5) * 0.25f;
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 < TAPS + 2; i++) {
Container *c = new VBox();
if (i < 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 >= TAPS) c_taps->colour = Colour(1, 1, 1, 0.15f);
c_taps->w = slide_w * TAPS;
c_strip->Pack(c_taps);
Container *c_ins = new HBox();
if (i >= TAPS) c_ins->colour = Colour(1, 1, 1, 0.15f);
c_ins->w = slide_w * 2;
c_strip->Pack(c_ins);
if (i < TAPS) {
snprintf(tmp, sizeof tmp, "Tap %d", i + 1);
} else {
strncpy(tmp, i == TAPS ? "Left Out" : "Right Out", sizeof tmp);
}
for (int j = 0; j < TAPS; j++) {
Slider *slider = new VSlider();
strncpy(slider->group, tmp, sizeof slider->group);
snprintf(slider->label, sizeof slider->label, "Tap %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 = (i * 10) + 4 + j;
c_taps->Pack(slider);
}
for (int j = 0; j < 2; 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 = (i * 10) + 4 + 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 >= TAPS;
gain->colour = Colour(1, .2f, .2f, 1);
gain->w = slide_w;
gain->min = -1.f;
gain->max = 1.f;
gain->port = (i * 10) + 4 + TAPS + 2;
c_strip->Pack(gain);
if (i < 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 = (i * 10) + 4 + TAPS + 3;
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 = 700;
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 =
{
"urn:fuzzle:ptap#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;
}