aboutsummaryrefslogtreecommitdiff
path: root/canvas_ui.c
diff options
context:
space:
mode:
Diffstat (limited to 'canvas_ui.c')
-rw-r--r--canvas_ui.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/canvas_ui.c b/canvas_ui.c
new file mode 100644
index 0000000..b15372a
--- /dev/null
+++ b/canvas_ui.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source 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
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <canvas.h>
+
+#include <pugl/pugl.h>
+
+#include <cairo/cairo.h>
+
+typedef struct _plughandle_t plughandle_t;
+
+struct _plughandle_t {
+ PuglView *view;
+ double val;
+ int done;
+};
+
+static inline void
+_expose(plughandle_t *handle)
+{
+ cairo_t *ctx = puglGetContext(handle->view);
+ cairo_surface_t *surf = cairo_get_target(ctx);
+
+ // Draw background
+ int w, h;
+ puglGetSize(handle->view, &w, &h);
+
+ cairo_surface_set_device_scale(surf, w, h);
+
+ cairo_set_source_rgba(ctx, 0.0, 0.0, 0.0, 1.0);
+ cairo_rectangle(ctx, 0.0, 0.0, 1.0, 1.0);
+ cairo_fill(ctx);
+
+ cairo_set_source_rgba(ctx, handle->val, handle->val, 0.0, 1.0);
+ cairo_arc(ctx, 0.5, 0.5, 0.4, 0.0, 2*M_PI);
+ cairo_fill(ctx);
+}
+
+static inline void
+_close(plughandle_t *handle)
+{
+ handle->done = 1;
+}
+
+static inline void
+_enter(plughandle_t *handle)
+{
+ puglPostRedisplay(handle->view);
+}
+
+static inline void
+_leave(plughandle_t *handle)
+{
+ puglPostRedisplay(handle->view);
+}
+
+static void
+_event_func(PuglView *view, const PuglEvent *ev)
+{
+ plughandle_t *handle = puglGetHandle(view);
+
+ switch(ev->type)
+ {
+ case PUGL_NOTHING:
+ break;
+ case PUGL_BUTTON_PRESS:
+ break;
+ case PUGL_BUTTON_RELEASE:
+ break;
+ case PUGL_CONFIGURE:
+ break;
+ case PUGL_EXPOSE:
+ _expose(handle);
+ break;
+ case PUGL_CLOSE:
+ _close(handle);
+ break;
+ case PUGL_KEY_PRESS:
+ break;
+ case PUGL_KEY_RELEASE:
+ break;
+ case PUGL_ENTER_NOTIFY:
+ _enter(handle);
+ break;
+ case PUGL_LEAVE_NOTIFY:
+ _leave(handle);
+ break;
+ case PUGL_MOTION_NOTIFY:
+ break;
+ case PUGL_SCROLL:
+ break;
+ case PUGL_FOCUS_IN:
+ break;
+ case PUGL_FOCUS_OUT:
+ break;
+ }
+}
+
+static LV2UI_Handle
+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)
+{
+ plughandle_t *handle= calloc(1, sizeof(plughandle_t));
+ if(!handle)
+ return NULL;
+
+ void *parent = NULL;
+ LV2UI_Resize *host_resize = NULL;
+ for(int i=0; features[i]; i++)
+ {
+ if(!strcmp(features[i]->URI, LV2_UI__parent))
+ parent = features[i]->data;
+ else if(!strcmp(features[i]->URI, LV2_UI__resize))
+ host_resize = features[i]->data;
+ }
+
+ if(!parent)
+ {
+ free(handle);
+ return NULL;
+ }
+
+ handle->view = puglInit(NULL, NULL);
+ if(!handle->view)
+ {
+ free(handle);
+ return NULL;
+ }
+
+ const int w = 400;
+ const int h = 400;;
+ puglInitWindowClass(handle->view, "canvas");
+ puglInitWindowParent(handle->view, (intptr_t)parent);
+ puglInitWindowSize(handle->view, w, h);
+ puglInitWindowMinSize(handle->view, w, h);
+ puglInitWindowAspectRatio(handle->view, 1, 1, 1, 1);
+ puglInitResizable(handle->view, true);
+ puglInitTransientFor(handle->view, (intptr_t)parent);
+#ifdef PUGL_HAVE_GL
+ puglInitContextType(handle->view, PUGL_CAIRO_GL);
+#else
+ puglInitContextType(handle->view, PUGL_CAIRO);
+#endif
+ puglSetHandle(handle->view, handle);
+ puglSetEventFunc(handle->view, _event_func);
+
+ int stat = puglCreateWindow(handle->view, "Canvas");
+ if(stat)
+ {
+ free(handle);
+ return NULL;
+ }
+ puglShowWindow(handle->view);
+
+ const intptr_t child = puglGetNativeWindow(handle->view);
+ *(intptr_t *)widget = child;
+
+ if(host_resize)
+ host_resize->ui_resize(host_resize->handle, w, h);
+
+ return handle;
+}
+
+static void
+cleanup(LV2UI_Handle instance)
+{
+ plughandle_t *handle = instance;
+
+ if(handle->view)
+ {
+ if(puglGetVisible(handle->view))
+ puglHideWindow(handle->view);
+ puglDestroy(handle->view);
+ }
+
+ free(handle);
+}
+
+static void
+port_event(LV2UI_Handle instance, uint32_t index, uint32_t size,
+ uint32_t protocol, const void *buf)
+{
+ //FIXME
+}
+
+static int
+_resize(LV2UI_Handle instance, int w, int h)
+{
+ plughandle_t *handle = instance;
+
+ //FIXME
+ //puglInitWindowSize(handle->view, w, h);
+ //puglInitWindowMinSize(handle->view, w, h);
+
+ return 0;
+}
+
+static const LV2UI_Resize resize_ext = {
+ .ui_resize= _resize
+};
+
+static int
+_idle(LV2UI_Handle instance)
+{
+ plughandle_t *handle = instance;
+
+ handle->val += 0.01;
+ if(handle->val >= 1.0)
+ handle->val = 0.0;
+
+ puglPostRedisplay(handle->view);
+
+ if(puglProcessEvents(handle->view) != PUGL_SUCCESS)
+ {
+ //TODO
+ }
+
+ return handle->done;
+}
+
+static const LV2UI_Idle_Interface idle_ext = {
+ .idle = _idle
+};
+
+static const void *
+extension_data(const char *uri)
+{
+ if(!strcmp(uri, LV2_UI__idleInterface))
+ return &idle_ext;
+ else if(!strcmp(uri, LV2_UI__resize))
+ return &resize_ext;
+
+ return NULL;
+}
+
+const LV2UI_Descriptor canvas_canvas_ui = {
+ .URI = CANVAS_CANVAS_UI_URI,
+ .instantiate = instantiate,
+ .cleanup = cleanup,
+ .port_event = port_event,
+ .extension_data = extension_data
+};
+
+LV2_SYMBOL_EXPORT const LV2UI_Descriptor*
+lv2ui_descriptor(uint32_t index)
+{
+ switch(index)
+ {
+ case 0:
+ return &canvas_canvas_ui;
+ default:
+ return NULL;
+ }
+}