aboutsummaryrefslogtreecommitdiff
path: root/canvas.c
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2016-11-06 20:23:39 +0100
committerHanspeter Portner <dev@open-music-kontrollers.ch>2016-11-06 20:23:39 +0100
commit3000bdcdbd3ad7c5aeb367fac467c73fee63ca80 (patch)
tree10f96e9822647a9156d0be6ed1c0cfbcb93b8cdf /canvas.c
parent0983862a4e2bfeedae06c82a22733effea55ae5b (diff)
downloadcanvas_display.lv2-3000bdcdbd3ad7c5aeb367fac467c73fee63ca80.tar.xz
finalize API.
Diffstat (limited to 'canvas.c')
-rw-r--r--canvas.c366
1 files changed, 0 insertions, 366 deletions
diff --git a/canvas.c b/canvas.c
deleted file mode 100644
index 4d06252..0000000
--- a/canvas.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * 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 <stdatomic.h>
-#include <math.h>
-
-#include <canvas.h>
-
-#include <lv2_extensions.h>
-
-#include <cairo/cairo.h>
-
-#define MAX_GRAPH_BUF 0x10000
-
-typedef struct _plughandle_t plughandle_t;
-
-struct _plughandle_t {
- LV2_URID_Map *map;
- LV2_Atom_Forge forge;
-
- LV2_Log_Log *log;
- LV2_Log_Logger logger;
-
- const LV2_Atom_Sequence *control;
- LV2_Atom_Sequence *notify;
-
- LV2_URID patch_Get;
- LV2_URID patch_Set;
- LV2_URID patch_property;
- LV2_URID patch_value;
-
- atomic_flag lock;
-
- LV2_Inline_Display *queue_draw;
- LV2_Inline_Display_Image_Surface image_surface;
- struct {
- cairo_surface_t *surface;
- cairo_t *ctx;
- } cairo;
-
- LV2_Canvas canvas;
-
- union {
- LV2_Atom_Tuple graph;
- uint8_t buf [MAX_GRAPH_BUF];
- };
-};
-
-static inline void
-_spin_lock(atomic_flag *lock)
-{
- while(atomic_flag_test_and_set_explicit(lock, memory_order_acquire))
- {
- // spin
- }
-}
-
-static inline bool
-_try_lock(atomic_flag *lock)
-{
- return atomic_flag_test_and_set_explicit(lock, memory_order_acquire);
-}
-
-static inline void
-_unlock_lock(atomic_flag *lock)
-{
- atomic_flag_clear_explicit(lock, memory_order_release);
-}
-
-static inline void
-_init_lock(atomic_flag *lock)
-{
- atomic_flag_clear_explicit(lock, memory_order_relaxed);
-}
-
-static LV2_Handle
-instantiate(const LV2_Descriptor* descriptor, double rate,
- const char *bundle_path, const LV2_Feature *const *features)
-{
- plughandle_t *handle = calloc(1, sizeof(plughandle_t));
- if(!handle)
- return NULL;
-
- for(unsigned i=0; features[i]; i++)
- {
- if(!strcmp(features[i]->URI, LV2_URID__map))
- handle->map = features[i]->data;
- else if(!strcmp(features[i]->URI, LV2_LOG__log))
- handle->log = features[i]->data;
- else if(!strcmp(features[i]->URI, LV2_INLINEDISPLAY__queue_draw))
- handle->queue_draw = features[i]->data;
- }
-
- if(!handle->map)
- {
- fprintf(stderr,
- "%s: Host does not support urid:map\n", descriptor->URI);
- free(handle);
- return NULL;
- }
-
- handle->patch_Get = handle->map->map(handle->map->handle, LV2_PATCH__Get);
- handle->patch_Set = handle->map->map(handle->map->handle, LV2_PATCH__Set);
- handle->patch_property = handle->map->map(handle->map->handle, LV2_PATCH__property);
- handle->patch_value = handle->map->map(handle->map->handle, LV2_PATCH__value);
-
- if(handle->log)
- lv2_log_logger_init(&handle->logger, handle->map, handle->log);
-
- lv2_atom_forge_init(&handle->forge, handle->map);
-
- handle->graph.atom.size = 0;
- handle->graph.atom.type = handle->forge.Tuple;
-
- _init_lock(&handle->lock);
-
- lv2_canvas_init(&handle->canvas, handle->map);
-
- return handle;
-}
-
-static void
-connect_port(LV2_Handle instance, uint32_t port, void *data)
-{
- plughandle_t *handle = instance;
-
- switch(port)
- {
- case 0:
- handle->control = data;
- break;
- case 1:
- handle->notify = data;
- break;
- default:
- break;
- }
-}
-
-static void
-run(LV2_Handle instance, uint32_t nsamples)
-{
- plughandle_t *handle = instance;
-
- const uint32_t capacity = handle->notify->atom.size;
- lv2_atom_forge_set_buffer(&handle->forge, (uint8_t *)handle->notify, capacity);
- LV2_Atom_Forge_Frame frame;
- LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(&handle->forge, &frame, 0);
-
- LV2_ATOM_SEQUENCE_FOREACH(handle->control, ev)
- {
- const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
-
- if(lv2_atom_forge_is_object_type(&handle->forge, obj->atom.type))
- {
- if(obj->body.otype == handle->patch_Get)
- {
- const LV2_Atom_URID *property = NULL;
-
- lv2_atom_object_get(obj, handle->patch_property, &property, 0);
-
- if( property
- && (property->atom.type == handle->forge.URID)
- && (property->body == handle->canvas.urid.Canvas_graph) )
- {
- LV2_Atom_Forge_Frame obj_frame;
- if(ref)
- ref = lv2_atom_forge_frame_time(&handle->forge, ev->time.frames);
- if(ref)
- ref = lv2_atom_forge_object(&handle->forge, &obj_frame, 0, handle->patch_Set);
- if(ref)
- ref = lv2_atom_forge_key(&handle->forge, handle->patch_property);
- if(ref)
- ref = lv2_atom_forge_urid(&handle->forge, handle->canvas.urid.Canvas_graph);
- if(ref)
- ref = lv2_atom_forge_key(&handle->forge, handle->patch_value);
- if(ref)
- ref = lv2_atom_forge_write(&handle->forge, &handle->graph, lv2_atom_total_size(&handle->graph.atom));
- if(ref)
- lv2_atom_forge_pop(&handle->forge, &obj_frame);
- }
- }
- else if(obj->body.otype == handle->patch_Set)
- {
- const LV2_Atom_URID *property = NULL;
- const LV2_Atom_Tuple *graph = NULL;
-
- lv2_atom_object_get(obj, handle->patch_property, &property,
- handle->patch_value, &graph, 0);
-
- if( property
- && (property->atom.type == handle->forge.URID)
- && (property->body == handle->canvas.urid.Canvas_graph)
- && graph
- && (graph->atom.type == handle->forge.Tuple) )
- {
- const uint32_t sz = lv2_atom_total_size(&graph->atom);
-
- if( (sz <= MAX_GRAPH_BUF) && _try_lock(&handle->lock))
- {
- memcpy(&handle->graph, graph, sz);
-
- _unlock_lock(&handle->lock);
-
- if(handle->queue_draw)
- handle->queue_draw->queue_draw(handle->queue_draw->handle);
- }
-
- if(ref)
- ref = lv2_atom_forge_frame_time(&handle->forge, ev->time.frames);
- if(ref)
- ref = lv2_atom_forge_write(&handle->forge, obj, lv2_atom_total_size(&obj->atom));
- }
- }
- }
- }
-
- if(ref)
- lv2_atom_forge_pop(&handle->forge, &frame);
- else
- lv2_atom_sequence_clear(handle->notify);
-}
-
-static inline LV2_Inline_Display_Image_Surface *
-_cairo_init(plughandle_t *handle, int w, int h)
-{
- LV2_Inline_Display_Image_Surface *surf = &handle->image_surface;
-
- surf->width = w;
- surf->height = w > h ? h : w; // try to use 1:1 ratio
- surf->stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, surf->width);
- surf->data = realloc(surf->data, surf->stride * surf->height);
- if(!surf->data)
- return NULL;
-
- handle->cairo.surface = cairo_image_surface_create_for_data(
- surf->data, CAIRO_FORMAT_ARGB32, surf->width, surf->height, surf->stride);
-
- if(handle->cairo.surface)
- {
- cairo_surface_set_device_scale(handle->cairo.surface, surf->width, surf->height);
-
- handle->cairo.ctx = cairo_create(handle->cairo.surface);
- if(handle->cairo.ctx)
- {
- cairo_select_font_face(handle->cairo.ctx, "cairo:monospace", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
- }
- }
-
- return surf;
-}
-
-static inline void
-_cairo_deinit(plughandle_t *handle)
-{
- LV2_Inline_Display_Image_Surface *surf = &handle->image_surface;
-
- if(handle->cairo.ctx)
- {
- cairo_destroy(handle->cairo.ctx);
- handle->cairo.ctx = NULL;
- }
-
- if(handle->cairo.surface)
- {
- cairo_surface_finish(handle->cairo.surface);
- cairo_surface_destroy(handle->cairo.surface);
- handle->cairo.surface = NULL;
- }
-
- if(surf->data)
- {
- free(surf->data);
- surf->data = NULL;
- }
-}
-
-// non-rt
-static LV2_Inline_Display_Image_Surface *
-_render(LV2_Handle instance, uint32_t w, uint32_t h)
-{
- plughandle_t *handle = instance;
- LV2_Inline_Display_Image_Surface *surf = &handle->image_surface;
-
- if( (surf->width != (int)w) || (surf->height > (int)h) || !surf->data)
- {
- _cairo_deinit(handle);
- surf = _cairo_init(handle, w, h);
- }
-
- if(!surf)
- return NULL;
-
- _spin_lock(&handle->lock);
-
- lv2_canvas_render(&handle->canvas, handle->cairo.ctx, &handle->forge, &handle->graph);
-
- _unlock_lock(&handle->lock);
-
- return surf;
-}
-
-static const LV2_Inline_Display_Interface idisp_iface = {
- .render = _render
-};
-
-static void
-cleanup(LV2_Handle instance)
-{
- plughandle_t *handle = instance;
-
- _cairo_deinit(handle);
-
- if(handle->image_surface.data)
- free(handle->image_surface.data);
- handle->image_surface.data = NULL;
-
- free(handle);
-}
-
-static const void *
-extension_data(const char *uri)
-{
- if(!strcmp(uri, LV2_INLINEDISPLAY__interface))
- return &idisp_iface;
-
- return NULL;
-}
-
-const LV2_Descriptor canvas_canvas = {
- .URI = CANVAS_PREFIX"canvas",
- .instantiate = instantiate,
- .connect_port = connect_port,
- .activate = NULL,
- .run = run,
- .deactivate = NULL,
- .cleanup = cleanup,
- .extension_data = extension_data
-};
-
-LV2_SYMBOL_EXPORT const LV2_Descriptor*
-lv2_descriptor(uint32_t index)
-{
- switch(index)
- {
- case 0:
- return &canvas_canvas;
- default:
- return NULL;
- }
-}