pplugins/ptap/ptapui.c

175 lines
3.8 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>
struct ptapui {
PuglView *view;
pthread_t thread;
LV2UI_Write_Function write;
LV2UI_Controller controller;
int width;
int height;
bool exit;
};
static void *ui_thread(void *ptr)
{
struct ptapui *pui = (struct ptapui *)ptr;
while (!pui->exit) {
usleep(1000000 / 25);
puglProcessEvents(pui->view);
}
return NULL;
}
static void parameterChanged(struct ptapui *pui, uint32_t index, float value)
{
pui->write(pui->controller, index, sizeof value, 0, &value);
}
static void onReshape(PuglView *view, int width, int height)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
glOrtho(0, width, height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
glLoadIdentity();
}
static void onDisplay(PuglView *view)
{
struct ptapui *pui = (struct ptapui *)puglGetHandle(view);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
GLdouble x2 = 2.0;
GLdouble y2 = 2.0;
GLdouble x1 = pui->width - 2.0;
GLdouble y1 = pui->height - 2.0;
glColor3f(1.0f, 0.2f, 0.0f);
glVertex2f(x1, y1);
glVertex2f(x1, y2);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(x2, x2);
glVertex2f(x2, y1);
glEnd();
}
static void onKeyboard(PuglView *view, bool press, uint32_t key)
{
}
static void onMotion(PuglView *view, int x, int y)
{
}
static void onMouse(PuglView *view, int button, bool press, int x, int y)
{
}
static void onScroll(PuglView *view, float dx, float dy)
{
}
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;
}
struct ptapui *pui = malloc(sizeof *pui);
pui->write = write_function;
pui->controller = controller;
pui->width = 320;
pui->height = 240;
pui->exit = false;
pui->view = puglCreate(parent, "PTap", pui->width, pui->height, true);
puglSetHandle(pui->view, pui);
puglSetDisplayFunc(pui->view, onDisplay);
puglSetReshapeFunc(pui->view, onReshape);
puglSetKeyboardFunc(pui->view, onKeyboard);
puglSetMotionFunc(pui->view, onMotion);
puglSetMouseFunc(pui->view, onMouse);
puglSetScrollFunc(pui->view, onScroll);
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)
{
struct ptapui *pui = (struct ptapui *)ui;
pui->exit = true;
pthread_join(pui->thread, NULL);
puglDestroy(pui->view);
free(ui);
}
static void ptapui_port_event(
LV2UI_Handle ui,
uint32_t port_index,
uint32_t buffer_size,
uint32_t format,
const void *buffer)
{
}
static const void *ptapui_extension_data(const char *uri)
{
return NULL;
}
static const LV2UI_Descriptor s_lv2uidescriptor =
{
.URI = "urn:fuzzle:ptap#X11UI",
.instantiate = &ptapui_instantiate,
.cleanup = &ptapui_cleanup,
.port_event = &ptapui_port_event,
.extension_data = &ptapui_extension_data,
};
const LV2UI_Descriptor *lv2ui_descriptor(uint32_t index)
{
if (index == 0) {
return &s_lv2uidescriptor;
}
return NULL;
}