From bdfcf19fdf158dc29534b305c2a96fb358b05a26 Mon Sep 17 00:00:00 2001 From: Paolo Marrone Date: Wed, 19 Mar 2025 19:42:22 +0100 Subject: [PATCH] test/plugin_ui now uses vinci windowing system + raw pixel drawing. Tested on windows only for now. --- test/plugin_ui.h | 228 +++++++++++++++++++++++++++++++++-------------- test/run.sh | 4 +- test/ui_apple.h | 21 ----- test/ui_apple.m | 32 ------- test/vars-pre.mk | 9 ++ 5 files changed, 174 insertions(+), 120 deletions(-) delete mode 100644 test/ui_apple.h delete mode 100644 test/ui_apple.m diff --git a/test/plugin_ui.h b/test/plugin_ui.h index 209dbe2..d4799b5 100644 --- a/test/plugin_ui.h +++ b/test/plugin_ui.h @@ -18,30 +18,22 @@ * File author: Stefano D'Angelo, Paolo Marrone */ -#if defined(_WIN32) || defined(__CYGWIN__) -#elif defined(__APPLE__) -# include "ui_apple.h" -#else -# include -#endif +#include "vinci.h" +#include +#include typedef struct { - void * widget; + void *widget; -#if defined(_WIN32) || defined(__CYGWIN__) -#elif defined(__APPLE__) -#else - Display * display; -#endif + vinci *vinci; + window *window; + int param_down; - float gain; - float delay; - float cutoff; - char bypass; - float y_z1; - - unsigned int width; - unsigned int height; + float gain; + float delay; + float cutoff; + char bypass; + float y_z1; plugin_ui_callbacks cbs; } plugin_ui; @@ -54,86 +46,192 @@ static void plugin_ui_get_default_size(uint32_t *width, uint32_t *height) { *height = HEIGHT; } +static void draw_rect(window *w, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t color) { + uint32_t *data = (uint32_t*) malloc(width * height * 4); + uint32_t p = 0; + for (uint32_t i = 0; i < height; i++) + for (uint32_t j = 0; j < width; j++, p++) + data[p] = color; + window_draw(w, (unsigned char*)data, 0, 0, width, height, x, y, width, height); + free(data); +} + +static void draw_slider(plugin_ui *pui, int id, float value) { + const int w = window_get_width(pui->window); + const int h = window_get_height(pui->window); + draw_rect(pui->window, 0.1 * w, 0.15 * (id + 1) * h, 0.8 * w * value, 0.1 * h, 0x6789ab); + draw_rect(pui->window, 0.1 * w + 0.8 * w * value, 0.15 * (id + 1) * h, 0.8 * w * (1.f - value), 0.1 * h, 0x1223bc); +} + +static void draw_button(plugin_ui *pui, int id, char value) { + const int w = window_get_width(pui->window); + const int h = window_get_height(pui->window); + draw_rect(pui->window, 0.4 * w, 0.15 * (id + 1) * h, 0.2 * w, 0.1 * h, value ? 0x6789ab : 0x1223bc); +} + +static void on_close(window *w) { + printf("on_close %p \n", (void*)w); fflush(stdout); +} + +static void on_mouse_press (window *win, int32_t x, int32_t y, uint32_t state) { + (void) state; + + plugin_ui *pui = (plugin_ui*) window_get_data(win); + const int w = window_get_width(win); + const int h = window_get_height(win); + + if (x >= 0.1 * w && x <= 0.9 * w && y >= 0.15 * h && y <= 0.25 * h) { + pui->param_down = 0; + pui->gain = (float)((x - (0.1 * w)) / (0.8 * w)); + pui->cbs.set_parameter_begin(pui->cbs.handle, 0, -60.f + 80.f * pui->gain); + draw_slider(pui, 0, pui->gain); + } else if (x >= 0.1 * w && x <= 0.9 * w && y >= 0.3 * h && y <= 0.4 * h) { + pui->param_down = 1; + pui->delay = (float)((x - (0.1 * w)) / (0.8 * w)); + pui->cbs.set_parameter_begin(pui->cbs.handle, 1, 1000.f * pui->delay); + draw_slider(pui, 1, pui->delay); + } else if (x >= 0.1 * w && x <= 0.9 * w && y >= 0.45 * h && y <= 0.55 * h) { + pui->param_down = 2; + pui->cutoff = (float)((x - (0.1 * w)) / (0.8 * w)); + pui->cbs.set_parameter_begin(pui->cbs.handle, 2, (632.4555320336746f * pui->cutoff + 20.653108640674372f) / (1.0326554320337158f - pui->cutoff)); + draw_slider(pui, 2, pui->cutoff); + } else if (x >= 0.4 * w && x <= 0.6 * w && y >= 0.6 * h && y <= 0.7 * h) { + pui->param_down = 4; + } +} + +static void on_mouse_release (window *win, int32_t x, int32_t y, uint32_t state) { + (void) state; + + plugin_ui *pui = (plugin_ui*) window_get_data(win); + const int w = window_get_width(win); + const int h = window_get_height(win); + + if (pui->param_down == 4) + if (x >= 0.4 * w && x <= 0.6 * w && y >= 0.6 * h && y <= 0.7 * h) { + pui->bypass = !pui->bypass; + pui->cbs.set_parameter(pui->cbs.handle, 3, pui->bypass ? 1.f : 0.f); + draw_button(pui, 3, pui->bypass); + } + + if (pui->param_down != -1) { + float v = x < 0.1 * w ? 0.f : (x > 0.9 * w ? 1.f : (float)((x - (0.1 * w)) / (0.8 * w))); + switch (pui->param_down) { + case 0: + pui->gain = v; + pui->cbs.set_parameter_end(pui->cbs.handle, 0, -60.f + 80.f * pui->gain); + draw_slider(pui, 0, pui->gain); + break; + case 1: + pui->delay = v; + pui->cbs.set_parameter_end(pui->cbs.handle, 1, 1000.f * pui->delay); + draw_slider(pui, 1, pui->delay); + break; + case 2: + pui->cutoff = v; + pui->cbs.set_parameter_end(pui->cbs.handle, 2, (632.4555320336746f * pui->cutoff + 20.653108640674372f) / (1.0326554320337158f - pui->cutoff)); + draw_slider(pui, 2, pui->cutoff); + break; + } + pui->param_down = -1; + } +} + +static void on_mouse_move (window *win, int32_t x, int32_t y, uint32_t state) { + (void) y; + (void) state; + + plugin_ui *pui = (plugin_ui*) window_get_data(win); + const int w = window_get_width(win); + + float v = x < 0.1 * w ? 0.f : (x > 0.9 * w ? 1.f : (float)((x - (0.1 * w)) / (0.8 * w))); + + switch (pui->param_down) { + case 0: + pui->gain = v; + pui->cbs.set_parameter(pui->cbs.handle, 0, -60.f + 80.f * pui->gain); + draw_slider(pui, 0, pui->gain); + break; + case 1: + pui->delay = v; + pui->cbs.set_parameter(pui->cbs.handle, 1, 1000.f * pui->delay); + draw_slider(pui, 1, pui->delay); + break; + case 2: + pui->cutoff = v; + pui->cbs.set_parameter(pui->cbs.handle, 2, (632.4555320336746f * pui->cutoff + 20.653108640674372f) / (1.0326554320337158f - pui->cutoff)); + draw_slider(pui, 2, pui->cutoff); + break; + } +} + +static void on_window_resize (window *w, int32_t width, int32_t height) { + draw_rect(w, 0, 0, width, height, 0xff9999); + + plugin_ui *pui = (plugin_ui*) window_get_data(w); + + draw_slider(pui, 0, pui->gain); + draw_slider(pui, 1, pui->delay); + draw_slider(pui, 2, pui->cutoff); + draw_button(pui, 3, pui->bypass); + draw_slider(pui, 4, pui->y_z1); +} + static plugin_ui *plugin_ui_create(char has_parent, void *parent, plugin_ui_callbacks *cbs) { plugin_ui *instance = malloc(sizeof(plugin_ui)); if (instance == NULL) return NULL; -#if defined(_WIN32) || defined(__CYGWIN__) -#elif defined(__APPLE__) - instance->widget = (void *)ui_create(has_parent, parent, WIDTH, HEIGHT); -#else - instance->display = XOpenDisplay(NULL); - if (instance->display == NULL) { - free(instance); - return NULL; - } - int s = DefaultScreen(instance->display); - Window w = XCreateSimpleWindow(instance->display, has_parent ? (Window)parent : RootWindow(instance->display, s), 0, 0, WIDTH, HEIGHT, 0, 0, 0); - XSelectInput(instance->display, w, ExposureMask | StructureNotifyMask); - XMapWindow(instance->display, w); - XSync(instance->display, False); + struct window_cbs wcbs; + memset(&wcbs, 0, sizeof(window_cbs)); + wcbs.on_window_close = on_close; + wcbs.on_mouse_press = on_mouse_press; + wcbs.on_mouse_release = on_mouse_release; + wcbs.on_mouse_move = on_mouse_move; + wcbs.on_window_resize = on_window_resize; - instance->widget = (void *)w; + instance->param_down = -1; + instance->vinci = vinci_new(); + instance->window = window_new(instance->vinci, has_parent ? parent : NULL, WIDTH, HEIGHT, &wcbs); + instance->widget = window_get_handle(instance->window); + window_set_data(instance->window, (void*) instance); + window_show(instance->window); - instance->width = WIDTH; - instance->height = HEIGHT; -#endif instance->cbs = *cbs; return instance; } static void plugin_ui_free(plugin_ui *instance) { -#if defined(_WIN32) || defined(__CYGWIN__) -#elif defined(__APPLE__) -#else - XDestroyWindow(instance->display, (Window)instance->widget); - XCloseDisplay(instance->display); -#endif + window_free(instance->window); free(instance); } static void plugin_ui_idle(plugin_ui *instance) { -#if defined(_WIN32) || defined(__CYGWIN__) -#elif defined(__APPLE__) -#else - Window w = (Window)instance->widget; - while (XEventsQueued(instance->display, QueuedAfterFlush) > 0) { - XEvent e; - XNextEvent(instance->display, &e); - if (e.type == Expose) { - XClearWindow(instance->display, w); - GC gc = DefaultGC(instance->display, DefaultScreen(instance->display)); - - XSetForeground(instance->display, gc, 0xff0000); - XFillRectangle(instance->display, w, gc, 10, 10, instance->width - 20, instance->height - 20); - } else if (e.type == ConfigureNotify) { - XWindowAttributes attrs; - XGetWindowAttributes(instance->display, w, &attrs); - instance->width = attrs.width; - instance->height = attrs.height; - } - } -#endif + vinci_idle(instance->vinci); } static void plugin_ui_set_parameter(plugin_ui *instance, size_t index, float value) { switch (index) { case 0: instance->gain = 0.0125f * value + 0.75f; + draw_slider(instance, 0, instance->gain); break; case 1: instance->delay = 0.001f * value; + draw_slider(instance, 1, instance->delay); break; case 2: // (bad) approx log unmap instance->cutoff = (1.0326554320337176f * value - 20.65310864067435f) / (value + 632.4555320336754f); + draw_slider(instance, 2, instance->cutoff); break; case 3: instance->bypass = value >= 0.5f; + draw_button(instance, 3, instance->bypass); break; case 4: instance->y_z1 = 0.5f * value + 0.5f; + draw_slider(instance, 4, instance->y_z1); break; } } diff --git a/test/run.sh b/test/run.sh index 4b88f47..db3861f 100755 --- a/test/run.sh +++ b/test/run.sh @@ -6,12 +6,12 @@ $dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/api $dir/../ $dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json $dir/../templates/vst3 $dir/../out/vst3 $dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json $dir/../templates/vst3-make $dir/../out/vst3 -cp $dir/plugin.h $dir/plugin_ui.h $dir/ui_apple.h $dir/ui_apple.m $dir/../out/vst3/src +cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/vst3/src cp $dir/vars-pre.mk $dir/../out/vst3 $dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2 $dir/../out/lv2 $dir/../tibia $dir/product.json,$dir/company.json,$dir/lv2.json $dir/../templates/lv2-make $dir/../out/lv2 -cp $dir/plugin.h $dir/plugin_ui.h $dir/ui_apple.h $dir/ui_apple.m $dir/../out/lv2/src +cp $dir/plugin.h $dir/plugin_ui.h $dir/../out/lv2/src cp $dir/vars-pre.mk $dir/../out/lv2 $dir/../tibia $dir/product.json,$dir/company.json $dir/../templates/web $dir/../out/web diff --git a/test/ui_apple.h b/test/ui_apple.h deleted file mode 100644 index 1383071..0000000 --- a/test/ui_apple.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Tibia - * - * Copyright (C) 2025 Orastron Srl unipersonale - * - * Tibia is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * Tibia is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tibia. If not, see . - * - * File author: Stefano D'Angelo - */ - -void *ui_create(char has_parent, void *parent, int width, int height); diff --git a/test/ui_apple.m b/test/ui_apple.m deleted file mode 100644 index 95ab87b..0000000 --- a/test/ui_apple.m +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Tibia - * - * Copyright (C) 2025 Orastron Srl unipersonale - * - * Tibia is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * Tibia is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tibia. If not, see . - * - * File author: Stefano D'Angelo - */ - -#import - -void *ui_create(char has_parent, void *parent, int width, int height) { - NSView *v = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, width, height)]; -/* WRONG - if (has_parent) { - NSView *p = (NSView *)parent; - [p addSubview:v positioned:NSWindowAbove relativeTo:nil]; - } -*/ - return (void *)v; -} diff --git a/test/vars-pre.mk b/test/vars-pre.mk index bd4e887..2d91b56 100644 --- a/test/vars-pre.mk +++ b/test/vars-pre.mk @@ -1,5 +1,7 @@ API_DIR := ../api +VINCI_DIR := ../../../vinci + ifeq ($(TEMPLATE), cmd) TINYWAV_DIR := ../../../tinywav MIDI_PARSER_DIR := ../../../midi-parser @@ -7,6 +9,8 @@ endif ifeq ($(TEMPLATE), lv2) ifeq ($(OS), Windows_NT) + C_SRCS_EXTRA := $(VINCI_DIR)/vinci-win32.c + LDFLAGS_EXTRA := -mwindows else UNAME_S := $(shell uname -s) ifeq ($(UNAME_S), Darwin) @@ -17,10 +21,13 @@ ifeq ($(TEMPLATE), lv2) LDFLAGS_EXTRA := $(shell pkg-config --libs x11) -Wl,-rpath,$(shell pkg-config --variable=libdir x11) endif endif + CFLAGS_EXTRA := $(CFLAGS_EXTRA) -I${VINCI_DIR} endif ifeq ($(TEMPLATE), vst3) ifeq ($(OS), Windows_NT) + C_SRCS_EXTRA := $(VINCI_DIR)/vinci-win32.c + LDFLAGS_EXTRA := -mwindows else UNAME_S := $(shell uname -s) ifeq ($(UNAME_S), Darwin) @@ -31,6 +38,8 @@ ifeq ($(TEMPLATE), vst3) LDFLAGS_EXTRA := $(shell pkg-config --libs x11) -Wl,-rpath,$(shell pkg-config --variable=libdir x11) endif endif + CFLAGS_EXTRA := $(CFLAGS_EXTRA) -I../../../vst3_c_api + CFLAGS_EXTRA := $(CFLAGS_EXTRA) -I${VINCI_DIR} endif ifeq ($(TEMPLATE), daisy-seed)