diff options
Diffstat (limited to 'modules/cairo/cairo.c')
-rw-r--r-- | modules/cairo/cairo.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/modules/cairo/cairo.c b/modules/cairo/cairo.c new file mode 100644 index 0000000..a4956ad --- /dev/null +++ b/modules/cairo/cairo.c @@ -0,0 +1,231 @@ +/** + * @file cairo.c Cairo module + * + * Copyright (C) 2010 Creytiv.com + */ +#define _BSD_SOURCE 1 +#include <unistd.h> +#include <pthread.h> +#include <math.h> +#include <re.h> +#include <rem.h> +#include <baresip.h> +#include <cairo/cairo.h> + + +#if !defined (M_PI) +#define M_PI 3.14159265358979323846264338327 +#endif + + +/* + * Note: This module is very experimental! + * + * Use Cairo library to draw graphics into a frame buffer + */ + +struct vidsrc_st { + struct vidsrc *vs; /* inheritance */ + + struct vidsrc_prm prm; + struct vidsz size; + cairo_surface_t *surface; + cairo_t *cr; + double step; + bool run; + pthread_t thread; + vidsrc_frame_h *frameh; + void *arg; +}; + + +static struct vidsrc *vidsrc; + + +static void destructor(void *arg) +{ + struct vidsrc_st *st = arg; + + if (st->run) { + st->run = false; + pthread_join(st->thread, NULL); + } + + if (st->cr) + cairo_destroy(st->cr); + if (st->surface) + cairo_surface_destroy(st->surface); + + mem_deref(st->vs); +} + + +static void draw_gradient(cairo_t *cr, double step, int width, int height) +{ + cairo_pattern_t *pat; + double r, g, b; + double x, y, tx, ty; + char buf[128]; + double fontsize = 20.0; + + r = 0.1 + fabs(sin(5 * step)); + g = 0.0; + b = 0.1 + fabs(sin(3 * step)); + + x = width * (sin(10 * step) + 1)/2; + y = height * (1 - fabs(sin(30 * step))); + + tx = width/2 * (sin(5 * step) + 1)/2; + ty = fontsize + (height - fontsize) * (1 - fabs(sin(20 * step))); + + + pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height); + cairo_pattern_add_color_stop_rgba (pat, 1, r, g, b, 1); + cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0, 0, 1); + cairo_rectangle (cr, 0, 0, width, height); + cairo_set_source (cr, pat); + cairo_fill (cr); + cairo_pattern_destroy (pat); + + pat = cairo_pattern_create_radial (x-128, y-128, 25.6, + x+128, y+128, 128.0); + cairo_pattern_add_color_stop_rgba (pat, 0, 0, 1, 0, 1); + cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 1); + cairo_set_source (cr, pat); + cairo_arc (cr, x, y, 76.8, 0, 2 * M_PI); + cairo_fill (cr); + cairo_pattern_destroy (pat); + + /* Draw text */ + cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, fontsize); + + re_snprintf(buf, sizeof(buf), "%H", fmt_gmtime, NULL); + + cairo_move_to (cr, tx, ty); + cairo_text_path (cr, buf); + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_fill_preserve (cr); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_set_line_width (cr, 0.1); + cairo_stroke (cr); +} + + +static void process(struct vidsrc_st *st) +{ + struct vidframe f; + + draw_gradient(st->cr, st->step, st->size.w, st->size.h); + st->step += 0.02 / st->prm.fps; + + vidframe_init_buf(&f, VID_FMT_RGB32, &st->size, + cairo_image_surface_get_data(st->surface)); + + st->frameh(&f, st->arg); +} + + +static void *read_thread(void *arg) +{ + struct vidsrc_st *st = arg; + uint64_t ts = 0; + + while (st->run) { + + uint64_t now; + + sys_msleep(2); + + now = tmr_jiffies(); + if (!ts) + ts = now; + + if (ts > now) + continue; + + process(st); + + ts += 1000/st->prm.fps; + } + + return NULL; +} + + +static int alloc(struct vidsrc_st **stp, struct vidsrc *vs, + struct media_ctx **ctx, struct vidsrc_prm *prm, + const struct vidsz *size, const char *fmt, + const char *dev, vidsrc_frame_h *frameh, + vidsrc_error_h *errorh, void *arg) +{ + struct vidsrc_st *st; + int err = 0; + + (void)ctx; + (void)fmt; + (void)dev; + (void)errorh; + + if (!stp || !prm || !size || !frameh) + return EINVAL; + + st = mem_zalloc(sizeof(*st), destructor); + if (!st) + return ENOMEM; + + st->vs = mem_ref(vs); + st->frameh = frameh; + st->arg = arg; + st->prm = *prm; + st->size = *size; + + st->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + size->w, size->h); + st->cr = cairo_create(st->surface); + + info("cairo: surface with format %d (%d x %d) stride=%d\n", + cairo_image_surface_get_format(st->surface), + cairo_image_surface_get_width(st->surface), + cairo_image_surface_get_height(st->surface), + cairo_image_surface_get_stride(st->surface)); + + st->step = rand_u16() / 1000.0; + + st->run = true; + err = pthread_create(&st->thread, NULL, read_thread, st); + if (err) { + st->run = false; + goto out; + } + + out: + if (err) + mem_deref(st); + else + *stp = st; + + return err; +} + + +static int module_init(void) +{ + return vidsrc_register(&vidsrc, "cairo", alloc, NULL); +} + + +static int module_close(void) +{ + vidsrc = mem_deref(vidsrc); + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(cairo) = { + "cairo", + "vidsrc", + module_init, + module_close +}; |