summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@bitmath.org>2010-07-29 15:54:31 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-08-05 22:48:38 +0200
commite0eb1015bf30fd0913db571b000ba6a83ea22660 (patch)
treea3d62152066cfb8521c80806596a4fb0fe322014 /src
parentb76660d71e2ea77752025089bd71deffad64e325 (diff)
Split the code into recognizer and inserter
Refactor code to make more room for gesture recognition. Also simplify public headers. Signed-off-by: Henrik Rydberg <rydberg@bitmath.org>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/evbuf.h64
-rw-r--r--src/gebuf.h5
-rw-r--r--src/gesture-client.c113
-rw-r--r--src/gesture-dev.c105
-rw-r--r--src/grail-api.c133
-rw-r--r--src/grail-inserter.c184
-rw-r--r--src/grail-inserter.h69
-rw-r--r--src/grail-recognizer.c97
-rw-r--r--src/grail-recognizer.h34
10 files changed, 498 insertions, 311 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 50a5afd..67f930a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,8 +7,8 @@ libgrail_la_LDFLAGS = \
7libgrail_la_SOURCES = \ 7libgrail_la_SOURCES = \
8 touch-dev.c \ 8 touch-dev.c \
9 touch-engine.c \ 9 touch-engine.c \
10 gesture-client.c \ 10 grail-inserter.c \
11 gesture-dev.c \ 11 grail-recognizer.c \
12 grail-api.c 12 grail-api.c
13 13
14AM_CFLAGS = $(CWARNFLAGS) -std=c99 14AM_CFLAGS = $(CWARNFLAGS) -std=c99
@@ -18,5 +18,4 @@ INCLUDES = -I$(top_srcdir)/include/
18libgrailincludedir = $(includedir) 18libgrailincludedir = $(includedir)
19libgrailinclude_HEADERS = \ 19libgrailinclude_HEADERS = \
20 $(top_srcdir)/include/grail-touch.h \ 20 $(top_srcdir)/include/grail-touch.h \
21 $(top_srcdir)/include/grail-gesture.h \
22 $(top_srcdir)/include/grail.h 21 $(top_srcdir)/include/grail.h
diff --git a/src/evbuf.h b/src/evbuf.h
new file mode 100644
index 0000000..dc5ad1e
--- /dev/null
+++ b/src/evbuf.h
@@ -0,0 +1,64 @@
1/*****************************************************************************
2 *
3 * mtdev - Multitouch Protocol Translation Library (MIT license)
4 *
5 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
6 * Copyright (C) 2010 Canonical Ltd.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 ****************************************************************************/
28
29#ifndef GRAIL_EVBUF_H
30#define GRAIL_EVBUF_H
31
32#define DIM_EVENTS 512
33
34struct evbuf {
35 int head;
36 int tail;
37 struct input_event buffer[DIM_EVENTS];
38};
39
40static inline void evbuf_clear(struct evbuf *evbuf)
41{
42 evbuf->head = evbuf->tail = 0;
43}
44
45static inline int evbuf_empty(const struct evbuf *evbuf)
46{
47 return evbuf->head == evbuf->tail;
48}
49
50static inline void evbuf_put(struct evbuf *evbuf,
51 const struct input_event *ev)
52{
53 evbuf->buffer[evbuf->head++] = *ev;
54 evbuf->head &= DIM_EVENTS - 1;
55}
56
57static inline void evbuf_get(struct evbuf *evbuf,
58 struct input_event *ev)
59{
60 *ev = evbuf->buffer[evbuf->tail++];
61 evbuf->tail &= DIM_EVENTS - 1;
62}
63
64#endif
diff --git a/src/gebuf.h b/src/gebuf.h
index e92431a..37e4a5c 100644
--- a/src/gebuf.h
+++ b/src/gebuf.h
@@ -29,6 +29,11 @@
29 29
30#define DIM_GESTURE_EVENTS 512 30#define DIM_GESTURE_EVENTS 512
31 31
32struct gesture_event {
33 touch_time_t time;
34 grail_prop_t prop[DIM_GRAIL_PROP];
35};
36
32struct gebuf { 37struct gebuf {
33 int head; 38 int head;
34 int tail; 39 int tail;
diff --git a/src/gesture-client.c b/src/gesture-client.c
deleted file mode 100644
index 91f1530..0000000
--- a/src/gesture-client.c
+++ /dev/null
@@ -1,113 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include <grail-gesture.h>
26#include <malloc.h>
27#include <string.h>
28#include <errno.h>
29#include "gebuf.h"
30
31#define GESTURE_GAP (1000 * 60 * 60)
32
33struct client_impl {
34 enum gesture_state state;
35 touch_time_t begin, end;
36 struct gebuf buf;
37};
38
39int client_init(struct gesture_client *client, void *priv)
40{
41 struct client_impl *x;
42 memset(client, 0, sizeof(*client));
43 x = calloc(DIM_GESTURE_TYPE, sizeof(*x));
44 if (!x)
45 return -ENOMEM;
46 client->impl = x;
47 client->priv = priv;
48 return 0;
49}
50
51void client_flag(struct gesture_client *client,
52 const struct gesture_flag *flag)
53{
54 if (client->priority[flag->type]) {
55 struct client_impl *x = &client->impl[flag->type];
56 switch(flag->state) {
57 case GS_BEGIN:
58 x->begin = flag->time;
59 x->end = flag->time + GESTURE_GAP;
60 break;
61 case GS_CANCEL:
62 x->end = x->begin;
63 break;
64 case GS_END:
65 x->end = flag->time;
66 break;
67 }
68 x->state = flag->state;
69 }
70}
71
72void client_event(struct gesture_client *client,
73 const struct gesture_event *ev)
74{
75 if (client->priority[ev->type]) {
76 struct client_impl *x = &client->impl[ev->type];
77 gebuf_put(&x->buf, ev);
78 }
79}
80
81void client_sync(struct gesture_client *client)
82{
83 struct gesture_event ev;
84 struct client_impl *x = client->impl;
85 int i, prio = 0;
86 for (i = 0; i < DIM_GESTURE_TYPE; i++) {
87 if (x[i].begin != x[i].end) {
88 if (client->priority[i] > prio)
89 prio = client->priority[i];
90 }
91 }
92 for (i = 0; i < DIM_GESTURE_TYPE; i++) {
93 if (client->priority[i] < prio) {
94 gebuf_clear(&x[i].buf);
95 } else if (prio && client->gesture) {
96 if (x[i].state == GS_END) {
97 while (!gebuf_empty(&x[i].buf)) {
98 gebuf_get(&x[i].buf, &ev);
99 client->gesture(client, &ev);
100 }
101 }
102 }
103 }
104 for (i = 0; i < DIM_GESTURE_TYPE; i++)
105 if (x[i].state == GS_END)
106 x[i].begin = x[i].end;
107}
108
109void client_destroy(struct gesture_client *client)
110{
111 free(client->impl);
112 memset(client, 0, sizeof(*client));
113}
diff --git a/src/gesture-dev.c b/src/gesture-dev.c
deleted file mode 100644
index 46c77d7..0000000
--- a/src/gesture-dev.c
+++ /dev/null
@@ -1,105 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include <grail-gesture.h>
26#include <malloc.h>
27#include <string.h>
28#include <errno.h>
29
30#define DIM_CLIENT 32
31
32struct gedev_impl {
33 int nclient;
34 struct gesture_client *client[DIM_CLIENT];
35};
36
37int gedev_init(struct gesture_dev *dev, void *priv)
38{
39 struct gedev_impl *x;
40 x = calloc(1, sizeof(*x));
41 if (!x)
42 return -ENOMEM;
43 dev->impl = x;
44 dev->priv = priv;
45 return 0;
46}
47
48int gedev_attach_client(struct gesture_dev *dev,
49 struct gesture_client *client)
50{
51 struct gedev_impl *x = dev->impl;
52 if (x->nclient >= DIM_CLIENT)
53 return -ENOMEM;
54 x->client[x->nclient++] = client;
55 return 0;
56}
57
58void gedev_flag(struct gesture_dev *dev,
59 const struct gesture_flag *flag)
60{
61 struct gedev_impl *x = dev->impl;
62 int i;
63 for (i = 0; i < x->nclient; i++)
64 client_flag(x->client[i], flag);
65}
66
67void gedev_event(struct gesture_dev *dev,
68 const struct gesture_event *ev)
69{
70 struct gedev_impl *x = dev->impl;
71 int i;
72 for (i = 0; i < x->nclient; i++)
73 client_event(x->client[i], ev);
74}
75
76void gedev_sync(struct gesture_dev *dev)
77{
78 struct gedev_impl *x = dev->impl;
79 int i;
80 for (i = 0; i < x->nclient; i++)
81 client_sync(x->client[i]);
82}
83
84void gedev_detach_client(struct gesture_dev *dev,
85 struct gesture_client *client)
86{
87 struct gedev_impl *x = dev->impl;
88 int i, j;
89 for (i = 0; i < x->nclient; i++)
90 if (x->client[i] == client)
91 break;
92 if (i >= x->nclient)
93 return;
94 x->nclient--;
95 for (j = i; j < x->nclient; j++)
96 x->client[j] = x->client[j + 1];
97 for (j = x->nclient; j < DIM_CLIENT; j++)
98 x->client[j] = 0;
99}
100
101void gedev_destroy(struct gesture_dev *dev)
102{
103 free(dev->impl);
104 memset(dev, 0, sizeof(*dev));
105}
diff --git a/src/grail-api.c b/src/grail-api.c
index dbe4977..19b66aa 100644
--- a/src/grail-api.c
+++ b/src/grail-api.c
@@ -1,4 +1,5 @@
1#include <grail-gesture.h> 1#include "grail-inserter.h"
2#include "grail-recognizer.h"
2#include <grail.h> 3#include <grail.h>
3#include <string.h> 4#include <string.h>
4#include <stdio.h> 5#include <stdio.h>
@@ -6,93 +7,46 @@
6#include <fcntl.h> 7#include <fcntl.h>
7#include <malloc.h> 8#include <malloc.h>
8#include <errno.h> 9#include <errno.h>
10#include "evbuf.h"
9 11
10struct grail_impl { 12struct grail_impl {
11 struct touch_dev dev; 13 struct touch_dev dev;
12 struct touch_engine engine; 14 struct touch_engine engine;
13 struct touch_frame frame; 15 struct evbuf evbuf;
14 struct gesture_dev gedev;
15 struct gesture_client client;
16 touch_time_t last_scroll;
17}; 16};
18 17
19static void gh_handle(struct grail_impl *gh,
20 const struct touch_frame *frame,
21 touch_time_t time)
22{
23#if 0
24 struct gesture_flag flag;
25 struct grail_event ev;
26 if (frame->ntouch == 1 || frame->ntouch == 2) {
27 flag.type = GE_MOVE;
28 flag.time = time;
29 flag.state = GS_BEGIN;
30 gedev_flag(&gh->dev, &flag);
31
32 ev.type = GE_MOVE;
33 ev.time = time;
34 ev.prop[0] =
35 frame->touch[0].prop[TP_POS_X] -
36 gh->frame.touch[0].prop[TP_POS_X];
37 ev.prop[1] =
38 frame->touch[0].prop[TP_POS_Y] -
39 gh->frame.touch[0].prop[TP_POS_Y];
40 if (ev.prop[0] || ev.prop[1])
41 gedev_event(&gh->dev, &ev);
42
43 flag.time = time + 1;
44 flag.state = GS_END;
45 gedev_flag(&gh->dev, &flag);
46 }
47 if (frame->ntouch == 2) {
48 flag.type = GE_VSCROLL;
49 flag.time = time;
50 flag.state = GS_BEGIN;
51 gedev_flag(&gh->dev, &flag);
52
53 ev.type = GE_VSCROLL;
54 ev.time = time;
55 ev.prop[0] =
56 frame->touch[0].prop[TP_POS_Y] -
57 gh->frame.touch[0].prop[TP_POS_Y];
58
59 if (ev.prop[0])
60 gedev_event(&gh->dev, &ev);
61
62 if (time > gh->last_scroll + 100) {
63 flag.time = time + 1;
64 flag.state = GS_END;
65 gedev_flag(&gh->dev, &flag);
66 gh->last_scroll = time;
67 }
68 } else {
69 flag.type = GE_VSCROLL;
70 flag.time = time;
71 flag.state = GS_CANCEL;
72 gedev_flag(&gh->dev, &flag);
73 }
74 gedev_sync(&gh->dev);
75 gh->frame = *frame;
76#endif
77}
78
79static void tp_event(struct touch_engine *engine, 18static void tp_event(struct touch_engine *engine,
80 const struct input_event *ev) 19 const struct input_event *ev)
81{ 20{
82 struct grail *ge = engine->priv; 21 struct grail *ge = engine->priv;
83 if (ge->event) 22 struct grail_impl *x = ge->impl;
84 ge->event(ge, ev); 23 evbuf_put(&x->evbuf, ev);
85} 24}
86 25
87static void tp_sync(struct touch_engine *engine, 26static void tp_sync(struct touch_engine *engine,
88 const struct input_event *syn) 27 const struct input_event *syn)
89{ 28{
29 struct input_event ev;
90 struct grail *ge = engine->priv; 30 struct grail *ge = engine->priv;
91#if 0 31 struct grail_impl *x = ge->impl;
92 struct touch_frame *frame = &engine->frame; 32 struct touch_frame *frame = &engine->frame;
93 gh_handle(ge, frame, frame->time); 33 grail_mask_t filtered[DIM_EV_TYPE_BYTES];
94#endif 34 int nevent = 0;
95 if (ge->event) 35 gin_frame_begin(ge, frame->time);
36 gru_recognize(ge, frame);
37 gin_frame_end(ge, filtered);
38 if (!ge->event) {
39 evbuf_clear(&x->evbuf);
40 return;
41 }
42 while (!evbuf_empty(&x->evbuf)) {
43 evbuf_get(&x->evbuf, &ev);
44 if (grail_get_mask(filtered, ev.type))
45 continue;
46 ge->event(ge, &ev);
47 nevent++;
48 }
49 if (nevent)
96 ge->event(ge, syn); 50 ge->event(ge, syn);
97} 51}
98 52
@@ -103,49 +57,48 @@ int grail_open(struct grail *ge, int fd)
103 x = calloc(1, sizeof(*x)); 57 x = calloc(1, sizeof(*x));
104 if (!x) 58 if (!x)
105 return -ENOMEM; 59 return -ENOMEM;
60 ret = gin_init(ge);
61 if (ret)
62 goto freemem;
63 ret = gru_init(ge);
64 if (ret)
65 goto freedev;
106 ret = touch_dev_open(&x->dev, fd); 66 ret = touch_dev_open(&x->dev, fd);
107 if (ret) 67 if (ret)
108 goto error; 68 goto freegru;
109 touch_engine_init(&x->engine, tp_event, tp_sync, ge); 69 touch_engine_init(&x->engine, tp_event, tp_sync, ge);
110 touch_engine_attach(&x->engine, &x->dev); 70 touch_engine_attach(&x->engine, &x->dev);
111 ge->impl = x; 71 ge->impl = x;
112 return 0; 72 return 0;
113 error: 73 freegru:
74 gru_destroy(ge);
75 freedev:
76 gin_destroy(ge);
77 freemem:
114 free(x); 78 free(x);
115 return ret; 79 return ret;
116} 80}
117 81
118int grail_idle(struct grail *ge, int fd, int ms)
119{
120 struct grail_impl *x = ge->impl;
121 return touch_dev_idle(&x->dev, fd, ms);
122}
123
124int grail_pull(struct grail *ge, int fd)
125{
126 struct grail_impl *x = ge->impl;
127 return touch_dev_pull(&x->dev, fd);
128}
129
130void grail_close(struct grail *ge, int fd) 82void grail_close(struct grail *ge, int fd)
131{ 83{
132 struct grail_impl *x = ge->impl; 84 struct grail_impl *x = ge->impl;
133 touch_engine_detach(&x->engine, &x->dev); 85 touch_engine_detach(&x->engine, &x->dev);
134 touch_dev_close(&x->dev, fd); 86 touch_dev_close(&x->dev, fd);
87 gru_destroy(ge);
88 gin_destroy(ge);
135 free(ge->impl); 89 free(ge->impl);
136 ge->impl = 0; 90 ge->impl = 0;
137} 91}
138 92
139void grail_add_client(struct grail *ge, grail_clientid_t id, 93int grail_idle(struct grail *ge, int fd, int ms)
140 const int *types, const int *priority, int ntypes)
141{ 94{
142 struct grail_impl *x = ge->impl; 95 struct grail_impl *x = ge->impl;
143 //gedev_attach_client(&x->dev, &x->client); 96 return touch_dev_idle(&x->dev, fd, ms);
144} 97}
145 98
146void grail_remove_client(struct grail *ge, grail_clientid_t id) 99int grail_pull(struct grail *ge, int fd)
147{ 100{
148 struct grail_impl *x = ge->impl; 101 struct grail_impl *x = ge->impl;
149 //gedev_detach_client(&x->dev, &x->client); 102 return touch_dev_pull(&x->dev, fd);
150} 103}
151 104
diff --git a/src/grail-inserter.c b/src/grail-inserter.c
new file mode 100644
index 0000000..b357e29
--- /dev/null
+++ b/src/grail-inserter.c
@@ -0,0 +1,184 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include "grail-inserter.h"
26#include <malloc.h>
27#include <string.h>
28#include <errno.h>
29
30static const int MAX_GESTURE_ID = 0xfff;
31
32int gin_init(struct grail *ge)
33{
34 struct gesture_inserter *x;
35 x = calloc(1, sizeof(*x));
36 if (!x)
37 return -ENOMEM;
38 ge->gin = x;
39 return 0;
40}
41
42void gin_destroy(struct grail *ge)
43{
44 free(ge->gin);
45 ge->gin = NULL;
46}
47
48void gin_frame_begin(struct grail *ge, grail_time_t time)
49{
50 struct gesture_inserter *gin = ge->gin;
51 gin->time = time;
52}
53
54static void send_event(struct grail *ge, struct slot_state *s,
55 const struct gesture_event *ev)
56{
57 struct grail_event gev;
58 int i;
59 if (!ge->gesture)
60 return;
61 gev.type = s->type;
62 gev.id = s->id;
63 gev.status = s->status;
64 gev.pos.x = s->x;
65 gev.pos.y = s->x;
66 gev.time = ev->time;
67 memcpy(gev.prop, ev->prop, DIM_GRAIL_PROP * sizeof(gev.prop[0]));
68 for (i = 0; i < s->nclient; i++) {
69 gev.client_id = s->client_id[i];
70 ge->gesture(ge, &gev);
71 }
72}
73
74void gin_frame_end(struct grail *ge, grail_mask_t *filtered)
75{
76 struct gesture_inserter *gin = ge->gin;
77 struct gesture_event ev;
78 grail_mask_t span[DIM_SLOT_BYTES];
79 int i, slot, spanned = 0;
80 memset(filtered, 0, DIM_EV_TYPE_BYTES);
81 memset(span, 0, sizeof(span));
82 for (slot = 0; slot < DIM_SLOT; slot++) {
83 struct slot_state *s = &gin->state[slot];
84 if (!grail_get_mask(gin->used, slot))
85 continue;
86 if (!s->nclient)
87 gin_gesture_discard(gin, slot);
88 }
89 for (slot = 0; slot < DIM_SLOT; slot++) {
90 struct slot_state *s = &gin->state[slot];
91 if (!grail_get_mask(gin->used, slot))
92 continue;
93 for (i = 0; i < DIM_SLOT_BYTES; i++) {
94 span[i] |= s->span[i];
95 spanned += !!span[i];
96 }
97 while (!gebuf_empty(&s->buf)) {
98 gebuf_get(&s->buf, &ev);
99 send_event(ge, s, &ev);
100 }
101 if (s->status == GRAIL_STATUS_BEGIN)
102 s->status = GRAIL_STATUS_UPDATE;
103 }
104 if (spanned)
105 grail_set_mask(filtered, EV_ABS);
106}
107
108int gin_gesture_begin(struct grail *ge, const struct touch_frame *frame,
109 int type, int x, int y, const grail_mask_t *span)
110{
111 struct grail_client_info info[DIM_CLIENT];
112 struct grail_coord coord[DIM_CLIENT];
113 struct gesture_inserter *gin = ge->gin;
114 struct slot_state *s;
115 int i, slot, nc, ncoord = 0;
116 for (slot = 0; slot < DIM_SLOT; slot++)
117 if (!grail_get_mask(gin->used, slot))
118 break;
119 if (slot >= DIM_SLOT)
120 return -1;
121 s = &gin->state[slot];
122 s->type = type;
123 s->id = gin->gestureid++ & MAX_GESTURE_ID;
124 s->status = GRAIL_STATUS_BEGIN;
125 s->x = x;
126 s->y = y;
127 s->nclient = 0;
128 if (ge->get_clients) {
129 grail_mask_t tps[DIM_GRAIL_TYPE_BYTES];
130 memset(tps, 0, sizeof(tps));
131 grail_set_mask(tps, type);
132 for (i = 0; i < DIM_SLOT; i++) {
133 const struct touch *t = &frame->touch[i];
134 if (!grail_get_mask(span, i))
135 continue;
136 coord[ncoord].x = t->prop[TP_POS_X];
137 coord[ncoord].y = t->prop[TP_POS_Y];
138 ncoord++;
139 }
140 nc = ge->get_clients(ge, info, DIM_CLIENT, coord, ncoord, tps);
141 for (i = 0; i < nc; i++) {
142 if (!grail_get_mask(info[i].mask, type))
143 continue;
144 s->client_id[s->nclient] = info[i].id;
145 s->nclient++;
146 }
147 }
148 memcpy(s->span, span, sizeof(s->span));
149 gebuf_clear(&s->buf);
150 grail_set_mask(gin->used, slot);
151 return slot;
152}
153
154void gin_gesture_end(struct gesture_inserter *gin, int slot)
155{
156 struct slot_state *s = &gin->state[slot];
157 s->status = GRAIL_STATUS_END;
158 grail_clear_mask(gin->used, slot);
159}
160
161void gin_gesture_discard(struct gesture_inserter *gin, int slot)
162{
163 struct slot_state *s = &gin->state[slot];
164 gebuf_clear(&s->buf);
165 gin_gesture_end(gin, slot);
166}
167
168void gin_gesture_end_all(struct gesture_inserter *gin)
169{
170 int slot;
171 for (slot = 0; slot < DIM_SLOT; slot++)
172 gin_gesture_end(gin, slot);
173}
174
175void gin_gesture_event(struct gesture_inserter *gin, int slot,
176 const grail_prop_t *prop)
177{
178 struct slot_state *s = &gin->state[slot];
179 struct gesture_event ev;
180 ev.time = gin->time;
181 memcpy(ev.prop, prop, sizeof(ev.prop));
182 gebuf_put(&s->buf, &ev);
183}
184
diff --git a/src/grail-inserter.h b/src/grail-inserter.h
new file mode 100644
index 0000000..1e02d5f
--- /dev/null
+++ b/src/grail-inserter.h
@@ -0,0 +1,69 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#ifndef _GRAIL_GESTURE_H
26#define _GRAIL_GESTURE_H
27
28#include <grail-touch.h>
29#include <grail.h>
30#include "gebuf.h"
31
32#define DIM_EV_TYPE EV_CNT
33#define DIM_EV_TYPE_BYTES (DIM_EV_TYPE >> 3)
34
35#define DIM_SLOT 32
36#define DIM_SLOT_BYTES (DIM_SLOT >> 3)
37
38#define DIM_CLIENT 32
39
40struct slot_state {
41 int type, id, status, x, y, nclient;
42 struct grail_client_id client_id[DIM_CLIENT];
43 grail_mask_t span[DIM_SLOT_BYTES];
44 struct gebuf buf;
45};
46
47struct gesture_inserter {
48 struct slot_state state[DIM_SLOT];
49 grail_mask_t used[DIM_SLOT_BYTES];
50 grail_time_t time;
51 int gestureid;
52};
53
54int gin_init(struct grail *ge);
55void gin_destroy(struct grail *ge);
56
57void gin_frame_begin(struct grail *ge, grail_time_t time);
58void gin_frame_end(struct grail *ge, grail_mask_t *filtered);
59
60int gin_gesture_begin(struct grail *ge, const struct touch_frame *frame,
61 int type, int x, int y, const grail_mask_t *span);
62void gin_gesture_discard(struct gesture_inserter *gin, int slot);
63void gin_gesture_end(struct gesture_inserter *gin, int slot);
64void gin_gesture_end_all(struct gesture_inserter *gin);
65
66void gin_gesture_event(struct gesture_inserter *gin, int slot,
67 const grail_prop_t *prop);
68
69#endif
diff --git a/src/grail-recognizer.c b/src/grail-recognizer.c
new file mode 100644
index 0000000..9ede059
--- /dev/null
+++ b/src/grail-recognizer.c
@@ -0,0 +1,97 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#include "grail-inserter.h"
26#include <string.h>
27#include <malloc.h>
28#include <errno.h>
29
30struct gesture_recognizer {
31 struct touch_frame frame;
32 touch_time_t scroll_time;
33 int scroll_active;
34 int scroll_gslot;
35 int scroll_slots[2];
36};
37
38int gru_init(struct grail *ge)
39{
40 ge->gru = calloc(1, sizeof(struct gesture_recognizer));
41 if (!ge->gru)
42 return -ENOMEM;
43 return 0;
44}
45
46void gru_destroy(struct grail *ge)
47{
48 free(ge->gru);
49 ge->gru = NULL;
50}
51
52void gru_recognize(struct grail *ge, const struct touch_frame *frame)
53{
54 struct gesture_inserter *gin = ge->gin;
55 struct gesture_recognizer *gru = ge->gru;
56 grail_prop_t prop[DIM_GRAIL_PROP];
57 grail_mask_t span[16];
58 int slot, nslot, x, y, dx, dy;
59 if (!gru)
60 return;
61 if (frame->ncreate || frame->ndestroy) {
62 gin_gesture_end_all(gin);
63 gru->scroll_active = 0;
64 return;
65 }
66 if (frame->ntouch != 2)
67 return;
68 memset(span, 0, sizeof(span));
69 nslot = 0;
70 x = y = dx = dy = 0;
71 for (slot = frame->slot; slot >= 0; slot = next_slot(frame, slot)) {
72 struct touch *ot = &gru->frame.touch[slot];
73 const struct touch *t = &frame->touch[slot];
74 gru->scroll_slots[nslot] = slot;
75 grail_set_mask(span, slot);
76 x += t->prop[TP_POS_X];
77 y += t->prop[TP_POS_Y];
78 dx += t->prop[TP_POS_X] - ot->prop[TP_POS_X];
79 dy += t->prop[TP_POS_Y] - ot->prop[TP_POS_Y];
80 nslot++;
81 }
82 x /= nslot;
83 y /= nslot;
84 dx /= nslot;
85 dy /= nslot;
86 if (!dy)
87 return;
88 if (!gru->scroll_active) {
89 gru->scroll_gslot = gin_gesture_begin(ge, frame,
90 GRAIL_TYPE_VSCROLL,
91 x, y, span);
92 gru->scroll_active = 1;
93 }
94 prop[0] = dy;
95 gin_gesture_event(gin, gru->scroll_gslot, prop);
96 gru->frame = *frame;
97}
diff --git a/src/grail-recognizer.h b/src/grail-recognizer.h
new file mode 100644
index 0000000..8c47162
--- /dev/null
+++ b/src/grail-recognizer.h
@@ -0,0 +1,34 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors:
21 * Henrik Rydberg <rydberg@bitmath.org>
22 *
23 ****************************************************************************/
24
25#ifndef _GRAIL_RECOGNIZER_H
26#define _GRAIL_RECOGNIZER_H
27
28#include "grail-inserter.h"
29
30int gru_init(struct grail *ge);
31void gru_recognize(struct grail *ge, const struct touch_frame *frame);
32void gru_destroy(struct grail *ge);
33
34#endif