/*****************************************************************************
*
* grail - Gesture Recognition And Instantiation Library
*
* Copyright (C) 2010-2011 Canonical Ltd.
*
* This program 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, either version 3 of the License, or (at your
* option) any later version.
*
* This program 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 this program. If not, see .
*
****************************************************************************/
#include "grail-impl.h"
#include
#include
#include
static struct grail_control *create_control(int size)
{
struct grail_control *c = calloc(1, size);
if (!c)
return 0;
c->glue_ms = 60;
c->bar_center_x = 0.03;
c->bar_center_y = 0.03;
c->bar_drag_x = 0.03;
c->bar_drag_y = 0.03;
c->bar_scale = 0.3;
c->bar_angle = 0.1;
c->drop_x_ms = 300;
c->drop_y_ms = 300;
c->drop_scale_ms = 300;
c->drop_angle_ms = 300;
return c;
}
static void destroy_slots(struct grail_element **slots, int nslot)
{
int i;
if (slots) {
for (i = nslot - 1; i >= 0; i--)
free(slots[i]);
free(slots);
}
}
static void destroy_frame(struct grail_frame *frame, int nslot)
{
if (frame) {
destroy_slots(frame->slots, nslot);
free(frame->ongoing);
free(frame);
}
}
static void destroy_frames(struct grail_frame **frames, int nframe, int nslot)
{
int i;
if (frames) {
for (i = nframe - 1; i >= 0; i--)
destroy_frame(frames[i], nslot);
free(frames);
}
}
static struct grail_element **create_slots(int nslot, int ntouch, int size)
{
struct grail_element **slots;
struct grail_element *s;
int i;
slots = calloc(nslot, sizeof(slots[0]));
if (!slots)
return 0;
for (i = 0; i < nslot; i++) {
s = calloc(1, size + ntouch * sizeof(void *));
if (!s)
goto out;
s->slot = i;
s->id = -1;
s->touches = (void *)((char *)s + size);
slots[i] = s;
}
return slots;
out:
destroy_slots(slots, nslot);
return 0;
}
static struct grail_frame *create_frame(int nslot, int ntouch,
int frame_size, int slot_size)
{
struct grail_frame *frame;
int i;
frame = calloc(1, frame_size);
if (!frame)
return 0;
frame->ongoing = calloc(nslot, sizeof(frame->ongoing[0]));
frame->slots = create_slots(nslot, ntouch, slot_size);
if (!frame->ongoing || !frame->slots)
goto out;
return frame;
out:
destroy_frame(frame, nslot);
return 0;
}
static struct grail_frame **create_frames(int nframe, int nslot, int ntouch,
int frame_size, int slot_size)
{
struct grail_frame **frames;
struct grail_frame *f;
int i;
frames = calloc(nframe, sizeof(frames[0]));
if (!frames)
return 0;
for (i = 0; i < nframe; i++) {
f = create_frame(nslot, ntouch, frame_size, slot_size);
if (!f)
goto out;
frames[i] = f;
}
return frames;
out:
destroy_frames(frames, nframe, nslot);
return 0;
}
int create_grail2(struct grail_impl *x,
utouch_frame_handle fh,
unsigned int num_frames,
grail_select_callback select,
unsigned int version,
unsigned int control_size,
unsigned int frame_size,
unsigned int slot_size)
{
struct utouch_surface *s = utouch_frame_get_surface(fh);
unsigned int ntouch = utouch_frame_get_num_slots(fh);
unsigned int nslot = get_slot_count(ntouch);
int i, j;
x->select = select;
x->control_size = MAX(control_size, sizeof(struct grail_control));
x->frame_size = MAX(frame_size, sizeof(struct grail_frame));
x->slot_size = MAX(slot_size, sizeof(struct grail_element));
x->num_frames = num_frames;
x->num_slots = nslot;
x->num_touches = ntouch;
x->ctl = create_control(x->control_size);
if (!x->ctl)
goto freemem;
x->frames = create_frames(num_frames, nslot, ntouch,
x->frame_size, x->slot_size);
if (!x->frames)
goto freemem;
for (i = 0; i < num_frames; i++)
x->frames[(i + 1) % num_frames]->prev = x->frames[i];
return 0;
freemem:
destroy_grail2(x);
return -ENOMEM;
}
void destroy_grail2(struct grail_impl *x)
{
destroy_frames(x->frames, x->num_frames, x->num_slots);
free(x->ctl);
}
grail_handle GRAIL_PUBLIC grail_new_raw(utouch_frame_handle fh,
unsigned int num_frames,
grail_select_callback select,
unsigned int version,
unsigned int control_size,
unsigned int frame_size,
unsigned int slot_size)
{
struct grail *ge;
struct grail_impl *x;
ge = calloc(1, sizeof(*ge));
if (!ge)
return 0;
x = calloc(1, sizeof(*x));
if (!x)
goto out;
x->fh = fh;
if (create_grail2(x, fh, num_frames, select,
version, control_size, frame_size, slot_size))
goto out;
ge->impl = x;
return ge;
out:
free(x);
free(ge);
return 0;
}
void GRAIL_PUBLIC grail_delete(grail_handle ge)
{
destroy_grail2(ge->impl);
free(ge->impl);
free(ge);
}
struct grail_control GRAIL_PUBLIC *grail_get_control(grail_handle ge)
{
return ge->impl->ctl;
}