summaryrefslogtreecommitdiff
path: root/src/frame.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-12-30 17:58:01 +0100
committerHenrik Rydberg <rydberg@euromail.se>2010-12-30 17:58:01 +0100
commitf0aba58c91933a4702a7cc74f7daf4192868f570 (patch)
tree648c41fe09adb72344769dd6242638cbad835482 /src/frame.c
Initial load of utouch-framev1.0.0
Compiles and runs on mtdev. ABI proof. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src/frame.c')
-rw-r--r--src/frame.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/src/frame.c b/src/frame.c
new file mode 100644
index 0000000..9c4be97
--- /dev/null
+++ b/src/frame.c
@@ -0,0 +1,303 @@
1/*****************************************************************************
2 *
3 * utouch-frame - Touch Frame 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 ****************************************************************************/
21
22#include "frame-impl.h"
23#include <errno.h>
24#include <math.h>
25#include <memory.h>
26#include <stdlib.h>
27#include <sys/time.h>
28
29#define MAX(a, b) ((a) > (b) ? (a) : (b))
30
31unsigned int utouch_frame_get_version(void)
32{
33 return UTOUCH_FRAME_VERSION;
34}
35
36static void destroy_slots(struct utouch_contact **slots, int nslot)
37{
38 int i;
39
40 if (slots) {
41 for (i = nslot - 1; i >= 0; i--)
42 free(slots[i]);
43 free(slots);
44 }
45}
46
47static void destroy_frame(struct utouch_frame *frame, int nslot)
48{
49 if (frame) {
50 destroy_slots(frame->slots, nslot);
51 free(frame->active);
52 free(frame);
53 }
54}
55
56static void destroy_frames(struct utouch_frame **frames, int nframe, int nslot)
57{
58 int i;
59
60 if (frames) {
61 for (i = nframe - 1; i >= 0; i--)
62 destroy_frame(frames[i], nslot);
63 free(frames);
64 }
65}
66
67static struct utouch_contact **create_slots(int nslot, int size)
68{
69 struct utouch_contact **slots;
70 struct utouch_contact *s;
71 int i;
72
73 slots = calloc(nslot, sizeof(slots[0]));
74 if (!slots)
75 return 0;
76
77 for (i = 0; i < nslot; i++) {
78 s = calloc(1, size);
79 if (!s)
80 goto out;
81 slots[i] = s;
82 s->slot = i;
83 s->id = -1;
84 }
85
86 return slots;
87out:
88 destroy_slots(slots, nslot);
89 return 0;
90}
91
92static struct utouch_frame *create_frame(int nslot,
93 int frame_size, int slot_size)
94{
95 struct utouch_frame *frame;
96 int i;
97
98 frame = calloc(1, frame_size);
99 if (!frame)
100 return 0;
101
102 frame->active = calloc(nslot, sizeof(frame->active[0]));
103 frame->slots = create_slots(nslot, slot_size);
104 if (!frame->active || !frame->slots)
105 goto out;
106
107 return frame;
108out:
109 destroy_frame(frame, nslot);
110 return 0;
111}
112
113static struct utouch_frame **create_frames(int nframe, int nslot,
114 int frame_size, int slot_size)
115{
116 struct utouch_frame **frames;
117 struct utouch_frame *f;
118 int i;
119
120 frames = calloc(nframe, sizeof(frames[0]));
121 if (!frames)
122 return 0;
123
124 for (i = 0; i < nframe; i++) {
125 f = create_frame(nslot, frame_size, slot_size);
126 if (!f)
127 goto out;
128 frames[i] = f;
129 }
130
131 return frames;
132out:
133 destroy_frames(frames, nframe, nslot);
134 return 0;
135}
136
137utouch_frame_handle utouch_frame_new_engine_raw(unsigned int nframe,
138 unsigned int nslot,
139 unsigned int rate,
140 unsigned int version,
141 unsigned int surface_size,
142 unsigned int frame_size,
143 unsigned int slot_size)
144{
145 struct utouch_frame *f, *pf;
146 utouch_frame_handle fh;
147 int i, j;
148
149 fh = calloc(1, sizeof(struct utouch_frame_engine));
150 if (!fh)
151 return 0;
152
153 fh->num_frames = nframe;
154 fh->num_slots = nslot;
155 fh->hold_ms = 1000 / rate;
156
157 surface_size = MAX(surface_size, sizeof(struct utouch_surface));
158 frame_size = MAX(frame_size, sizeof(struct utouch_frame));
159 slot_size = MAX(slot_size, sizeof(struct utouch_contact));
160
161 fh->surface = calloc(1, surface_size);
162 fh->frames = create_frames(nframe, nslot, frame_size, slot_size);
163 fh->next = create_frame(nslot, frame_size, slot_size);
164 if (!fh->surface || !fh->frames || !fh->next)
165 goto out;
166
167 pf = fh->frames[nframe - 1];
168 for (i = 0; i < nframe; i++) {
169 f = fh->frames[i];
170 for (j = 0; j < nslot; j++)
171 f->slots[j]->prev = pf->slots[j];
172 f->prev = pf;
173 pf = f;
174 }
175
176 return fh;
177out:
178 utouch_frame_delete_engine(fh);
179 return 0;
180}
181
182void utouch_frame_delete_engine(utouch_frame_handle fh)
183{
184 destroy_frame(fh->next, fh->num_slots);
185 destroy_frames(fh->frames, fh->num_frames, fh->num_slots);
186 free(fh->surface);
187 free(fh);
188}
189
190struct utouch_surface *utouch_frame_get_surface(utouch_frame_handle fh)
191{
192 return fh->surface;
193}
194
195struct utouch_contact *utouch_frame_get_current_slot(utouch_frame_handle fh)
196{
197 return fh->next->slots[fh->slot];
198}
199
200int utouch_frame_set_current_slot(utouch_frame_handle fh, int slot)
201{
202 if (slot < 0 || slot >= fh->num_slots)
203 return -EINVAL;
204 fh->slot = slot;
205 return 0;
206}
207
208static void copy_contact(utouch_frame_handle fh,
209 struct utouch_contact *a,
210 const struct utouch_contact *b)
211{
212 struct utouch_surface *s = fh->surface;
213
214 a->active = b->id != -1;
215 a->id = b->id;
216 a->tool_type = b->tool_type;
217 a->x = b->x;
218 a->y = b->y;
219 a->touch_major = b->touch_major;
220 a->touch_minor = s->use_touch_minor && b->touch_minor > 0 ?
221 b->touch_minor : b->touch_major;
222 a->width_major = b->width_major;
223 a->width_minor = s->use_width_minor && b->width_minor > 0 ?
224 b->width_minor : b->width_major;
225 a->orientation = b->orientation;
226 a->pressure = b->pressure;
227 a->distance = b->distance;
228}
229
230static int detect_addrem(const struct utouch_contact *a,
231 const struct utouch_contact *b)
232{
233 return a->id != b->id || a->tool_type != b->tool_type;
234}
235
236static int detect_mod(const struct utouch_contact *a,
237 const struct utouch_contact *b)
238{
239 return a->x != b->x || a->y != b->y ||
240 a->touch_major != b->touch_major ||
241 a->touch_minor != b->touch_minor ||
242 a->width_major != b->width_major ||
243 a->width_minor != b->width_minor ||
244 a->orientation != b->orientation ||
245 a->pressure != b->pressure ||
246 a->distance != b->distance;
247}
248
249static utouch_frame_time_t get_time_ms()
250{
251 static const utouch_frame_time_t ms = 1000;
252 struct timeval tv;
253 gettimeofday(&tv, 0);
254 return tv.tv_usec / ms + tv.tv_sec * ms;
255}
256
257const struct utouch_frame *utouch_frame_sync(utouch_frame_handle fh,
258 utouch_frame_time_t time)
259{
260 struct utouch_frame *frame = fh->frames[fh->frame];
261 const struct utouch_frame *prev = frame->prev;
262 struct utouch_frame *next = fh->next;
263 int naddrem = 0, nmod = 0;
264 int i;
265
266 frame->num_active = 0;
267 for (i = 0; i < fh->num_slots; i++) {
268 struct utouch_contact *p = frame->slots[i];
269 const struct utouch_contact *q = next->slots[i];
270
271 copy_contact(fh, p, q);
272 if (p->active)
273 frame->active[frame->num_active++] = p;
274
275 naddrem += detect_addrem(p->prev, p);
276 nmod += detect_mod(p->prev, p);
277 }
278 if (naddrem + nmod == 0)
279 return 0;
280
281 frame->time = time ? time : get_time_ms();
282 if (naddrem == 0 && frame->time < prev->time + fh->hold_ms)
283 return 0;
284
285 if (frame->num_active != prev->num_active) {
286 next->mod_time = frame->time;
287 next->revision++;
288 }
289 if (naddrem) {
290 next->slot_mod_time = frame->time;
291 next->slot_revision++;
292 }
293
294 frame->revision = next->revision;
295 frame->slot_revision = next->slot_revision;
296 frame->mod_time = next->mod_time;
297 frame->slot_mod_time = next->slot_mod_time;
298 frame->sequence_id = next->sequence_id++;
299
300 fh->frame = (fh->frame + 1) % fh->num_frames;
301
302 return frame;
303}