Merge lp:~oif-team/geis/geis2-add-filters into lp:geis

Proposed by Stephen M. Webb
Status: Superseded
Proposed branch: lp:~oif-team/geis/geis2-add-filters
Merge into: lp:geis
Diff against target: 2455 lines (+1784/-68)
28 files modified
.bzrignore (+2/-2)
ChangeLog (+150/-0)
configure.ac (+1/-0)
include/geis/geis.h (+69/-2)
libutouch-geis/Makefile.am (+3/-1)
libutouch-geis/backend/Makefile.am (+1/-1)
libutouch-geis/backend/test_fixture/Makefile.am (+22/-0)
libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c (+45/-3)
libutouch-geis/backend/test_fixture/geis_backend_test_fixture.h (+5/-3)
libutouch-geis/geis.c (+133/-22)
libutouch-geis/geis_attr.c (+23/-1)
libutouch-geis/geis_device.c (+16/-7)
libutouch-geis/geis_filter.c (+456/-0)
libutouch-geis/geis_filter.h (+123/-0)
libutouch-geis/geis_filter_term.c (+206/-0)
libutouch-geis/geis_filter_term.h (+139/-0)
libutouch-geis/geis_private.h (+16/-1)
libutouch-geis/geis_subscription.c (+88/-22)
libutouch-geis/geis_subscription.h (+22/-1)
libutouch-geis/libutouch-geis.ver (+9/-0)
testsuite/geis2/Makefile.am (+1/-0)
testsuite/geis2/check_device.c (+41/-1)
testsuite/geis2/check_filter.c (+41/-0)
testsuite/geis2/check_geis2_api.c (+2/-0)
testsuite/geis2/check_subscription.c (+66/-1)
testsuite/libutouch-geis/Makefile.am (+1/-0)
testsuite/libutouch-geis/check_filter.c (+101/-0)
testsuite/libutouch-geis/check_geis2_internals.c (+2/-0)
To merge this branch: bzr merge lp:~oif-team/geis/geis2-add-filters
Reviewer Review Type Date Requested Status
Chase Douglas (community) Approve
Henrik Rydberg (community) Needs Fixing
Review via email: mp+45129@code.launchpad.net

This proposal has been superseded by a proposal from 2011-01-06.

Description of the change

GEIS v2.0 filter API

This series provides the public API layer of the GEIS v2.0 filter module. The implementation layer is still to come, it depends on additional back end work.

To post a comment you must log in.
Revision history for this message
Henrik Rydberg (rydberg) wrote :

At geis.h:132, there is a "teh".

In geis_filter_term_bag_new(), there is an error path that returns non-null.

That's about what I could find. Perhaps also adding _get_attr_for_factility() before respinning this patch would be good.

review: Needs Fixing
Revision history for this message
Chase Douglas (chasedouglas) wrote :

Seems reasonable to me from a high-level perspective. I'm not going to go into a line-level code review, so I'm approving.

We still need to figure out continuations in this filter framework, but we'll do so next week at the rally.

review: Approve
lp:~oif-team/geis/geis2-add-filters updated
104. By Stephen M. Webb

Added missing geis_attr_value_to_pointer function.

105. By Stephen M. Webb

Fixed failure-mode return value in geis_filter_term_bag_new().

106. By Stephen M. Webb

Added device cacheing.

107. By Stephen M. Webb

Moved back end test fixture into a subproject.

108. By Stephen M. Webb

Marked missing geis_event_* symbols as exported.

109. By Stephen M. Webb

Added group test for back end device creation.

110. By Stephen M. Webb

Added GEIS v2.0 filter implementation (part 4, device subscription).

111. By Stephen M. Webb

Minor tweaks.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-12-09 16:14:15 +0000
3+++ .bzrignore 2011-01-06 00:59:08 +0000
4@@ -1,9 +1,9 @@
5+**.la
6+**.lo
7 **.pdf
8 **/Makefile
9 *.deps
10 *.libs
11-*/*.la
12-*/*.lo
13 *Makefile.in
14 aclocal.m4
15 autom4te.cache
16
17=== modified file 'ChangeLog'
18--- ChangeLog 2010-12-29 20:35:48 +0000
19+++ ChangeLog 2011-01-06 00:59:08 +0000
20@@ -1,3 +1,153 @@
21+2011-01-05 Stephen M. Webb <stephen.webb@canonical.com>
22+
23+ Minor tweaks.
24+
25+ * include/geis/geis.h: fixed typos in comments
26+ (GEIS_DEVICE_ATTRIBUTE_NAME): new constant
27+ * libutouch-geis/geis_device.c: used new constant instead of hard-coded string
28+ * testsuite/geis2/check_subscription.c: same
29+
30+2011-01-05 Stephen M. Webb <stephen.webb@canonical.com>
31+
32+ Added GEIS v2.0 filter implementation (part 4, device subscription)
33+
34+ * libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c
35+ (_subscription): add debug output to the test fixture
36+ * libutouch-geis/geis_device.c: made name an attr for filtering on
37+ * libutouch-geis/geis_filter.h
38+ (geis_filter_term_by_facility_count): new function
39+ (geis_filter_term_by_facility): new function
40+ * libutouch-geis/geis_filter.c: implemented the above new functions
41+ * libutouch-geis/geis_subscription.h
42+ (geis_subscription_filter_count): new function
43+ (geis_subscription_filter): new function
44+ * libutouch-geis/geis_subscription.c: implemented the above new functions
45+ * testsuite/geis2/check_subscription.c (device_filter): new test case
46+
47+2011-01-05 Stephen M. Webb <stephen.webb@canonical.com>
48+
49+ Added group test for back end device creation.
50+
51+ * libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c
52+ (_create_test_devices): new function
53+ (geis_backend_new_test_fixture): used it
54+ * libutouch-geis/backend/test_fixture/geis_backend_test_fixture.h
55+ (geis_backend_new_test_fixture): added track_devices parameter
56+ * libutouch-geis/geis.c (_set_valist): refactored to propagate init args
57+ * testsuite/geis2/check_device.c: new test case
58+
59+2011-01-05 Stephen M. Webb <stephen.webb@canonical.com>
60+
61+ Marked missing geis_event_* symbols as exported.
62+
63+ * libutouch-geis/libutouch-geis.ver (geis_event_attr): exported
64+ (geis_event_attr_by_name): exported
65+ (geis_event_attr_count): exported
66+ (geis_event_delete): exported
67+ (geis_event_type): exported
68+
69+2011-01-05 Stephen M. Webb <stephen.webb@canonical.com>
70+
71+ Moved back end test fixture into a subproject.
72+
73+ * libutouch-geis/backend/test_fixture: new subproject
74+ * libutouch-geis/backend/test_fixture/Makefile.am: new file
75+ * libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c: renamed
76+ from libutouch-geis/geis_backend_test_fixture.c
77+ * libutouch-geis/backend/test_fixture/geis_backend_test_fixture.h: renamed
78+ from libutouch-geis/geis_backend_test_fixture.h
79+ * configure.ac (AC_OUTPUT): added libutouch-geis/backend/test_fixture/Makefile
80+ * libutouch-geis/Makefile.am: linked in new subproject
81+ * libutouch-geis/backend/Makefile.am: added new subproject
82+ * libutouch-geis/geis.c: changed header qualification
83+
84+2011-01-05 Stephen M. Webb <stephen.webb@canonical.com>
85+
86+ Added device cacheing.
87+
88+ * libutouch-geis/geis_private.h (geis_get_device_attr_type): new function
89+ * libutouch-geis/geis.c (struct _Geis): added devices field
90+ (_device_event_handler): new function
91+ (_input_event_handler): dispatched BE device events
92+ (geis_new_empty): initialized devices field
93+ (geis_new_delete): destroyed devices field
94+ * libutouch-geis/geis_filter.c (_get_attr_type_for_facility): implemented for
95+ the device facility
96+
97+2011-01-05 Stephen M. Webb <stephen.webb@canonical.com>
98+
99+ Fixed failure-mode return value from geis_filter_term_bag_new
100+
101+ * libutouch-geis/geis_filter_term.c (geis_filter_term_bag_new): returned
102+ NULL on failure
103+
104+2011-01-05 Stephen M. Webb <stephen.webb@canonical.com>
105+
106+ Added missing geis_attr_value_to_pointer.
107+
108+ * libutouch-geis/geis_attr.c (geis_attr_value_to_pointer): new function
109+ (geis_attr_value_to_string): added case to handle GEIS_ATTR_TYPE_POINTER
110+
111+2011-01-03 Stephen M. Webb <stephen.webb@canonical.com>
112+
113+ Added GEIS v2.0 filter implementation (part 3, filter terms)
114+
115+ * libutouch-geis/geis_filter_term.c: new file
116+ * libutouch-geis/geis_filter_term.h: new file
117+ * include/geis/geis.h (GeisFilterOperation): fixed typo
118+ * libutouch-geis/Makefile.am: added new files
119+ * libutouch-geis/geis_filter.c (geis_filter_add_term): implemented function
120+ (_facility_is_valid): new function
121+ (_operation_is_valid): new function
122+ (_get_attr_for_facility): new function
123+
124+2011-01-01 Stephen M. Webb <stephen.webb@canonical.com>
125+
126+ Added GEIS v2.0 filter implementation (part 2)
127+
128+ * libutouch-geis/geis_filter.c: fixed refcounting on bag insertion
129+ * libutouch-geis/geis_subscription.c
130+ (geis_subscription_add_filter): implemented stubbed-out function
131+ (geis_subscription_remove_filter): implemented stubbed-out function
132+ * testsuite/geis2/check_subscription.c: new test case
133+
134+2010-12-20 Stephen M. Webb <stephen.webb@canonical.com>
135+
136+ Added GEIS v2.0 filter implementation (part 1)
137+
138+ * testsuite/libutouch-geis/check_filter.c: new test suite
139+ * libutouch-geis/geis_filter.h (GeisFilterBag): new data structure
140+ (geis_filter_bag_new): new function
141+ (geis_filter_bag_delete): new function
142+ (geis_filter_bag_count): new function
143+ (geis_filter_bag_filter): new function
144+ (geis_filter_bag_insert): new function
145+ (geis_filter_bag_remove): new function
146+ (geis_filter_ref): new function
147+ (geis_filter_unref): new function
148+ * libutouch-geis/geis_filter.c: implemented new functions
149+ * testsuite/libutouch-geis/Makefile.am: added new test suite
150+ * testsuite/libutouch-geis/check_geis2_internals.c: added new test suite
151+
152+2010-12-29 Stephen M. Webb <stephen.webb@canonical.com>
153+
154+ Added GEIS v2.0 filter API
155+
156+ * libutouch-geis/geis_filter.c: new file
157+ * libutouch-geis/geis_filter.h: new file
158+ * testsuite/geis2/check_filter.c: new test suite
159+ * include/geis/geis.h (GeisFilter): new type
160+ (GeisFilterFacility): new enumeration
161+ (GeisFilterOperation): new enumeration
162+ (gei_filter_new): new function
163+ (geis_filter_delete): new function
164+ (geis_filter_name): new function
165+ (geis_filter_add_term): new function
166+ * libutouch-geis/Makefile.am: added new files
167+ * libutouch-geis/libutouch-geis.ver: added new symbols
168+ * testsuite/geis2/Makefile.am: added new test suite
169+ * testsuite/geis2/check_geis2_api.c: added new test suite
170+
171 2010-12-29 Stephen M. Webb <stephen.webb@canonical.com>
172
173 Added backend subdirectory to libutouch-geis.
174
175=== modified file 'configure.ac'
176--- configure.ac 2010-12-29 20:35:48 +0000
177+++ configure.ac 2011-01-06 00:59:08 +0000
178@@ -88,6 +88,7 @@
179 libutouch-geis-xcb/xcb_gesture.xml
180 libutouch-geis/Makefile
181 libutouch-geis/backend/Makefile
182+ libutouch-geis/backend/test_fixture/Makefile
183 testsuite/Makefile
184 testsuite/libutouch-geis/Makefile
185 testsuite/geis1/Makefile
186
187=== modified file 'include/geis/geis.h'
188--- include/geis/geis.h 2010-12-21 01:47:05 +0000
189+++ include/geis/geis.h 2011-01-06 00:59:08 +0000
190@@ -100,6 +100,7 @@
191 #define GEIS_GESTURE_ATTRIBUTE_TOUCH_4_X "touch 4 x"
192 #define GEIS_GESTURE_ATTRIBUTE_TOUCH_4_Y "touch 4 y"
193
194+#define GEIS_DEVICE_ATTRIBUTE_NAME "device name"
195
196 #define GEIS_FALSE 0
197 #define GEIS_TRUE 1
198@@ -856,7 +857,7 @@
199 GEIS_API void geis_device_unref(GeisDevice device);
200
201 /**
202- * Gets the name of teh input device.
203+ * Gets the name of the input device.
204 *
205 * @param[in] device The device.
206 */
207@@ -947,11 +948,77 @@
208 /* @} */
209
210 /**
211+ * @defgroup geis2_filter Gesture Filter (GEIS v2.0)
212+ * @{
213+ */
214+
215+typedef struct _GeisFilter *GeisFilter;
216+
217+typedef enum _GeisFilterFacility
218+{
219+ GEIS_FILTER_DEVICE = 1000,
220+ GEIS_FILTER_GESTURE_TYPE = 2000,
221+ GEIS_FILTER_REGION = 3000
222+} GeisFilterFacility;
223+
224+typedef enum _GeisFilterOperation
225+{
226+ GEIS_FILTER_OP_EQ,
227+ GEIS_FILTER_OP_NE,
228+ GEIS_FILTER_OP_GT,
229+ GEIS_FILTER_OP_GE,
230+ GEIS_FILTER_OP_LT,
231+ GEIS_FILTER_OP_LE,
232+} GeisFilterOperation;
233+
234+
235+/**
236+ * Creates a new filter.
237+ *
238+ * @param[in] geis The GEIS API instance.
239+ * @param[in] name A name.
240+ *
241+ * @returns a GeisFilter object or NULL on failure.
242+ */
243+GEIS_API GeisFilter geis_filter_new(Geis geis, GeisString name);
244+
245+/**
246+ * Destroys a GEIS v2.0 filter object.
247+ *
248+ * @param[in] filter The filter.
249+ */
250+GEIS_API GeisStatus geis_filter_delete(GeisFilter filter);
251+
252+/**
253+ * Gets the name given to the filter when it was created.
254+ *
255+ * @param[in] filter The filter.
256+ */
257+GEIS_API GeisString geis_filter_name(GeisFilter filter);
258+
259+/**
260+ * Adds a term to a filter.
261+ *
262+ * @param[in] filter The filter.
263+ * @param[in] facility The term facility.
264+ * @param[in] ... A list of zero or more term descriptions.
265+ *
266+ * A term description is generally a (attr-name, filter-op, value) triple in
267+ * which the meaning of the filter-op and value depend on the type of the attr.
268+ *
269+ * The term description list must be terminated by a NULL.
270+ */
271+GEIS_API GeisStatus geis_filter_add_term(GeisFilter filter,
272+ GeisFilterFacility facility,
273+ ...);
274+
275+/* @} */
276+
277+/**
278 * @defgroup geis2_subscription Gesture Subscription (GEIS v2.0)
279 * @{
280 */
281
282-typedef struct _GeisFilter *GeisFilter;
283 typedef struct _GeisSubscription *GeisSubscription;
284
285 /**
286
287=== modified file 'libutouch-geis/Makefile.am'
288--- libutouch-geis/Makefile.am 2010-12-29 20:35:48 +0000
289+++ libutouch-geis/Makefile.am 2011-01-06 00:59:08 +0000
290@@ -31,11 +31,12 @@
291 geis_backend.h geis_backend.c \
292 geis_backend_protected.h \
293 geis_backend_multiplexor.h geis_backend_multiplexor.c \
294- geis_backend_test_fixture.h geis_backend_test_fixture.c \
295 geis_device.h geis_device.c \
296 geis_error.h geis_error.c \
297 geis_event.h geis_event.c \
298 geis_event_queue.h geis_event_queue.c \
299+ geis_filter.h geis_filter.c \
300+ geis_filter_term.h geis_filter_term.c \
301 geis_logging.h geis_logging.c \
302 geis_region.h geis_region.c \
303 geis_subscription.h geis_subscription.c \
304@@ -57,6 +58,7 @@
305 -lm
306
307 libutouch_geis_la_LIBADD = \
308+ ${builddir}/backend/test_fixture/libutouch-geis-test-fixture.la \
309 $(top_builddir)/libutouch-geis-xcb/libutouch-geis.la
310
311 EXTRA_DIST = $(version_script)
312
313=== modified file 'libutouch-geis/backend/Makefile.am'
314--- libutouch-geis/backend/Makefile.am 2010-12-29 20:35:48 +0000
315+++ libutouch-geis/backend/Makefile.am 2011-01-06 00:59:08 +0000
316@@ -19,5 +19,5 @@
317 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
318 #
319
320-SUBDIRS =
321+SUBDIRS = test_fixture
322
323
324=== added directory 'libutouch-geis/backend/test_fixture'
325=== added file 'libutouch-geis/backend/test_fixture/Makefile.am'
326--- libutouch-geis/backend/test_fixture/Makefile.am 1970-01-01 00:00:00 +0000
327+++ libutouch-geis/backend/test_fixture/Makefile.am 2011-01-06 00:59:08 +0000
328@@ -0,0 +1,22 @@
329+#
330+# @file libutouch-geis/backend/test_fixture/Makefile.am
331+#
332+# Build recipes for the test fixture back end.
333+#
334+
335+noinst_LTLIBRARIES = libutouch-geis-test-fixture.la
336+
337+libutouch_geis_test_fixture_la_SOURCES = \
338+ geis_backend_test_fixture.h geis_backend_test_fixture.c
339+
340+libutouch_geis_test_fixture_la_CPPFLAGS = \
341+ -Wall -Wextra \
342+ -fvisibility=hidden \
343+ -I$(top_srcdir) \
344+ -I$(top_srcdir)/include \
345+ -I$(top_srcdir)/libutouch-geis
346+
347+libutouch_geis_test_fixture_la_LDFLAGS =
348+
349+libutouch_geis_test_fixture_la_LIBADD =
350+
351
352=== renamed file 'libutouch-geis/geis_backend_test_fixture.c' => 'libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c'
353--- libutouch-geis/geis_backend_test_fixture.c 2010-12-15 01:48:35 +0000
354+++ libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2011-01-06 00:59:08 +0000
355@@ -21,13 +21,21 @@
356 #include "geis_backend.h"
357 #include "geis_backend_protected.h"
358
359+#include "geis_attr.h"
360+#include "geis_device.h"
361+#include "geis_event.h"
362+#include "geis_filter.h"
363+#include "geis_filter_term.h"
364 #include "geis_logging.h"
365+#include "geis_private.h"
366+#include "geis_subscription.h"
367 #include <stdlib.h>
368
369
370 typedef struct _GeisBackendTestFixture
371 {
372 struct _GeisBackend tf_base;
373+ Geis tf_geis;
374 } *GeisBackendTestFixture;
375
376
377@@ -39,11 +47,29 @@
378
379
380 static GeisStatus
381-_subscribe(GeisBackend be __attribute__((unused)),
382- GeisSubscription sub __attribute__((unused)))
383+_subscribe(GeisBackend be,
384+ GeisSubscription sub)
385 {
386 geis_debug("begins");
387 GeisStatus status = GEIS_STATUS_SUCCESS;
388+ GeisSize i, j;
389+ for (i = 0; i < geis_subscription_filter_count(sub); ++i)
390+ {
391+ GeisFilter filter = geis_subscription_filter(sub, i);
392+ geis_debug("processing filter '%s'", geis_filter_name(filter));
393+ for (j = 0;
394+ j < geis_filter_term_by_facility_count(filter, GEIS_FILTER_DEVICE);
395+ ++j)
396+ {
397+ GeisFilterTerm term = geis_filter_term_by_facility(filter,
398+ GEIS_FILTER_DEVICE,
399+ j);
400+ geis_debug(" DEVICE \"%s\" (%d) \"%s\"",
401+ geis_attr_name(geis_filter_term_attr(term)),
402+ geis_filter_term_operation(term),
403+ geis_attr_value_to_string(geis_filter_term_attr(term)));
404+ }
405+ }
406 geis_debug("ends");
407 return status;
408 }
409@@ -66,8 +92,18 @@
410 };
411
412
413+static void _create_test_devices(GeisBackendTestFixture tf)
414+{
415+ GeisDevice device = geis_device_new("abs-test-device", 0);
416+ GeisEvent event = geis_event_new(GEIS_EVENT_DEVICE_AVAILABLE);
417+ GeisAttr attr = geis_attr_new("geis-device", GEIS_ATTR_TYPE_POINTER, device);
418+ geis_event_add_attr(event, attr);
419+ geis_post_event(tf->tf_geis, event);
420+}
421+
422+
423 GeisBackend
424-geis_backend_new_test_fixture(Geis geis __attribute__((unused)))
425+geis_backend_new_test_fixture(Geis geis, GeisBoolean track_devices)
426 {
427 GeisBackendTestFixture tf = calloc(1, sizeof(struct _GeisBackendTestFixture));
428 if (!tf)
429@@ -77,6 +113,12 @@
430 }
431
432 geis_backend_init_base(&tf->tf_base, &tf_vtbl, "GEIS2 test fixture");
433+ tf->tf_geis = geis;
434+
435+ if (track_devices)
436+ {
437+ _create_test_devices(tf);
438+ }
439
440 geis_debug("%s back end created", geis_backend_name(&tf->tf_base));
441
442
443=== renamed file 'libutouch-geis/geis_backend_test_fixture.h' => 'libutouch-geis/backend/test_fixture/geis_backend_test_fixture.h'
444--- libutouch-geis/geis_backend_test_fixture.h 2010-12-02 19:09:57 +0000
445+++ libutouch-geis/backend/test_fixture/geis_backend_test_fixture.h 2011-01-06 00:59:08 +0000
446@@ -2,7 +2,7 @@
447 * @file geis_backend_test_fixture.h
448 * @brief internal GEIS test fixture back end class
449 *
450- * Copyright 2010 Canonical Ltd.
451+ * Copyright 2010, 2011 Canonical Ltd.
452 *
453 * This library is free software; you can redistribute it and/or modify it under
454 * the terms of the GNU Lesser General Public License as published by the Free
455@@ -26,10 +26,12 @@
456 /**
457 * Constructs a new GEIS Test Fuixture back end.
458 *
459- * @param[in] geis The API instance the back end will run in.
460+ * @param[in] geis The API instance the back end will run in.
461+ * @param[in] track_devices Indicates devices should be tracked.
462 *
463 * The Test Fixture back end is used in unit tests.
464 */
465-GeisBackend geis_backend_new_test_fixture(Geis geis);
466+GeisBackend geis_backend_new_test_fixture(Geis geis,
467+ GeisBoolean track_devices);
468
469 #endif /* GEIS_BACKEND_TEST_FIXTURE_H_ */
470
471=== modified file 'libutouch-geis/geis.c'
472--- libutouch-geis/geis.c 2010-12-15 01:48:35 +0000
473+++ libutouch-geis/geis.c 2011-01-06 00:59:08 +0000
474@@ -2,7 +2,7 @@
475 * @file libutouch-geis/geis.c
476 * @brief implementation of the uTouch GEIS v2.0 API instance
477 *
478- * Copyright 2010 Canonical Ltd.
479+ * Copyright 2010, 2011 Canonical Ltd.
480 *
481 * This library is free software; you can redistribute it and/or modify it under
482 * the terms of the GNU Lesser General Public License as published by the Free
483@@ -22,11 +22,14 @@
484 #include "geis_private.h"
485
486 #include <errno.h>
487+#include "geis_attr.h"
488 #include "geis_backend.h"
489-#include "geis_backend_test_fixture.h"
490+#include "test_fixture/geis_backend_test_fixture.h"
491 #include "geis_backend_multiplexor.h"
492 #include "geis_error.h"
493+#include "geis_event.h"
494 #include "geis_event_queue.h"
495+#include "geis_device.h"
496 #include "geis_logging.h"
497 #include <stdarg.h>
498 #include <string.h>
499@@ -44,6 +47,7 @@
500 GeisEventQueue output_event_queue;
501 GeisEventCallback output_event_callback;
502 void *output_event_callback_context;
503+ GeisDeviceBag devices;
504 };
505
506
507@@ -59,6 +63,39 @@
508 geis_event_queue_enqueue(geis->output_event_queue, event);
509 }
510
511+
512+/*
513+ * Handles device events coming in from the back end.
514+ */
515+static GeisBoolean
516+_device_event_handler(Geis geis, GeisEvent event)
517+{
518+ GeisBoolean handled = GEIS_FALSE;
519+ GeisAttr attr = geis_event_attr_by_name(event, "geis-device");
520+ if (!attr)
521+ {
522+ geis_warning("invalid device event received from back end.");
523+ handled = GEIS_TRUE;
524+ goto final_exit;
525+ }
526+
527+ GeisDevice device = geis_attr_value_to_pointer(attr);
528+
529+ GeisEventType event_type = geis_event_type(event);
530+ if (event_type == GEIS_EVENT_DEVICE_AVAILABLE)
531+ {
532+ geis_device_bag_insert(geis->devices, device);
533+ }
534+ else if (event_type == GEIS_EVENT_DEVICE_UNAVAILABLE)
535+ {
536+ geis_device_bag_remove(geis->devices, device);
537+ }
538+
539+final_exit:
540+ return handled;
541+}
542+
543+
544 /*
545 * Filters and transforms raw gesture events into cooked gesture events.
546 *
547@@ -84,9 +121,24 @@
548 event = geis_event_queue_dequeue(geis->input_event_queue);
549 if (event)
550 {
551- geis->output_event_callback(geis,
552- event,
553- geis->output_event_callback_context);
554+ GeisBoolean handled = 0;
555+ switch (geis_event_type(event))
556+ {
557+ case GEIS_EVENT_DEVICE_AVAILABLE:
558+ case GEIS_EVENT_DEVICE_UNAVAILABLE:
559+ handled = _device_event_handler(geis, event);
560+ break;
561+
562+ default:
563+ break;
564+ }
565+
566+ if (!handled)
567+ {
568+ geis->output_event_callback(geis,
569+ event,
570+ geis->output_event_callback_context);
571+ }
572 }
573 }
574 }
575@@ -152,8 +204,18 @@
576 }
577 geis->output_event_callback = _default_output_event_callback;
578
579+ geis->devices = geis_device_bag_new();
580+ if (!geis->output_event_queue)
581+ {
582+ geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR);
583+ geis_error("creation of geis device bag failed");
584+ goto unwind_output_queue;
585+ }
586+
587 goto final_exit;
588
589+unwind_output_queue:
590+ geis_event_queue_delete(geis->output_event_queue);
591 unwind_input_signal_pipe:
592 close(geis->input_event_signal_pipe[0]);
593 close(geis->input_event_signal_pipe[1]);
594@@ -172,39 +234,55 @@
595 }
596
597
598+typedef enum _BackendType
599+{
600+ BACK_END_TYPE_NONE,
601+ BACK_END_TYPE_MOCK_ENGINE
602+} BackendType;
603+
604 /**
605 * Sets optional parts of a Geis API instance from a variable argument list.
606 */
607-static void
608-geis_set_valist(Geis geis, GeisString init_arg_name, va_list varargs)
609+static GeisBoolean
610+_set_valist(Geis geis, GeisString init_arg_name, va_list varargs)
611 {
612+ GeisBoolean status = GEIS_TRUE;
613+ BackendType back_end_type = BACK_END_TYPE_NONE;
614+ GeisBoolean track_devices = GEIS_FALSE;
615+
616 while (init_arg_name)
617 {
618 if (0 == strcmp(init_arg_name, GEIS_INIT_SERVICE_PROVIDER))
619 {
620 geis_debug("initializing GEIS server");
621 }
622+ else if (0 == strcmp(init_arg_name, GEIS_INIT_TRACK_DEVICES))
623+ {
624+ track_devices = GEIS_TRUE;
625+ }
626 else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_MOCK_ENGINE))
627 {
628- if (NULL != geis->backend)
629- {
630- geis_error("multiple back ends requested, only using %s",\
631- geis_backend_name(geis->backend));
632- }
633- else
634- {
635- geis_debug("initializing GEIS test fixture");
636- geis->backend = geis_backend_new_test_fixture(geis);
637- }
638+ if (back_end_type != BACK_END_TYPE_NONE)
639+ {
640+ geis_error("multiple back ends requested, only using last request");
641+ }
642+ back_end_type = BACK_END_TYPE_MOCK_ENGINE;
643 }
644
645 init_arg_name = va_arg(varargs, GeisString);
646 }
647
648- if (NULL == geis->backend)
649- {
650- geis_debug("initializing default GEIS back end");
651- }
652+ if (back_end_type ==BACK_END_TYPE_MOCK_ENGINE)
653+ {
654+ geis->backend = geis_backend_new_test_fixture(geis, track_devices);
655+ }
656+ else
657+ {
658+ geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR);
659+ geis_error("back end required but not specified");
660+ status = GEIS_FALSE;
661+ }
662+ return status;
663 }
664
665
666@@ -214,15 +292,23 @@
667 Geis
668 geis_new(GeisString init_arg_name, ...)
669 {
670+ GeisBoolean success = GEIS_FALSE;
671 Geis geis = geis_new_empty();
672 if (geis)
673 {
674 va_list varargs;
675 va_start(varargs, init_arg_name);
676- geis_set_valist(geis, init_arg_name, varargs);
677+ success = _set_valist(geis, init_arg_name, varargs);
678 va_end(varargs);
679 }
680
681+ if (!success)
682+ {
683+ geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR);
684+ geis_error("can not initialize GEIS API");
685+ geis_delete(geis);
686+ geis = NULL;
687+ }
688 return geis;
689 }
690
691@@ -238,6 +324,11 @@
692 return GEIS_STATUS_BAD_ARGUMENT;
693 }
694
695+ geis_device_bag_delete(geis->devices);
696+ geis_event_queue_delete(geis->output_event_queue);
697+ close(geis->input_event_signal_pipe[0]);
698+ close(geis->input_event_signal_pipe[1]);
699+ geis_event_queue_delete(geis->input_event_queue);
700 if (geis->backend)
701 geis_backend_delete(geis->backend);
702 geis_backend_multiplexor_delete(geis->backend_multiplexor);
703@@ -420,3 +511,23 @@
704 }
705
706
707+GeisAttrType
708+geis_get_device_attr_type(Geis geis, GeisString attr_name)
709+{
710+ GeisSize i = 0;
711+ for (; i < geis_device_bag_count(geis->devices); ++i)
712+ {
713+ GeisDevice device = geis_device_bag_device(geis->devices, i);
714+ GeisSize j = 0;
715+ for (; j < geis_device_attr_count(device); ++j)
716+ {
717+ GeisAttr attr = geis_device_attr(device, j);
718+ if (0 == strcmp(geis_attr_name(attr), attr_name))
719+ {
720+ return geis_attr_type(attr);
721+ }
722+ }
723+ }
724+ return GEIS_ATTR_TYPE_UNKNOWN;
725+}
726+
727
728=== modified file 'libutouch-geis/geis_attr.c'
729--- libutouch-geis/geis_attr.c 2010-12-14 15:24:58 +0000
730+++ libutouch-geis/geis_attr.c 2011-01-06 00:59:08 +0000
731@@ -2,7 +2,7 @@
732 * @file geis_attr.c
733 * @brief internal uTouch GeisAttr facilities
734 *
735- * Copyright 2010 Canonical Ltd.
736+ * Copyright 2010, 2011 Canonical Ltd.
737 *
738 * This library is free software; you can redistribute it and/or modify it under
739 * the terms of the GNU Lesser General Public License as published by the Free
740@@ -304,6 +304,23 @@
741 }
742
743
744+GeisPointer
745+geis_attr_value_to_pointer(GeisAttr attr)
746+{
747+ GeisPointer p_value = NULL;
748+ switch (attr->attr_type)
749+ {
750+ case GEIS_ATTR_TYPE_POINTER:
751+ p_value = attr->v_value;
752+ break;
753+
754+ default:
755+ break;
756+ }
757+ return p_value;
758+}
759+
760+
761 GeisString
762 geis_attr_value_to_string(GeisAttr attr)
763 {
764@@ -326,6 +343,11 @@
765 s_value = buf;
766 break;
767
768+ case GEIS_ATTR_TYPE_POINTER:
769+ sprintf(buf, "%p", attr->v_value);
770+ s_value = buf;
771+ break;
772+
773 case GEIS_ATTR_TYPE_STRING:
774 s_value = attr->s_value;
775 break;
776
777=== modified file 'libutouch-geis/geis_device.c'
778--- libutouch-geis/geis_device.c 2010-12-21 13:59:31 +0000
779+++ libutouch-geis/geis_device.c 2011-01-06 00:59:08 +0000
780@@ -2,7 +2,7 @@
781 * @file libutouch-geis/geis_region.c
782 * @brief implementation of the uTouch GEIS v2.0 API Input Device module
783 *
784- * Copyright 2010 Canonical Ltd.
785+ * Copyright 2010, 2010 Canonical Ltd.
786 *
787 * This library is free software; you can redistribute it and/or modify it under
788 * the terms of the GNU Lesser General Public License as published by the Free
789@@ -30,7 +30,6 @@
790 struct _GeisDevice
791 {
792 GeisSize ref_count;
793- GeisString name;
794 GeisInteger id;
795 GeisAttrBag attr_bag;
796 };
797@@ -177,12 +176,15 @@
798 goto unwind_device;
799 }
800
801- device->name = strdup(name);
802- if (!device->name)
803+ GeisAttr name_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_NAME,
804+ GEIS_ATTR_TYPE_STRING,
805+ (void *)name);
806+ if (!name_attr)
807 {
808 geis_debug("error allocating device name");
809 goto unwind_attrs;
810 }
811+ geis_attr_bag_insert(device->attr_bag, name_attr);
812
813 device->id = id;
814 geis_device_ref(device);
815@@ -204,7 +206,7 @@
816 static void
817 _device_delete(GeisDevice device)
818 {
819- free((char *)device->name);
820+ geis_attr_bag_delete(device->attr_bag);
821 free(device);
822 }
823
824@@ -233,12 +235,19 @@
825
826
827 /*
828- * Gets the name of teh input device.
829+ * Gets the name of the input device.
830 */
831 GeisString
832 geis_device_name(GeisDevice device)
833 {
834- return device->name;
835+ GeisString device_name = NULL;
836+ GeisAttr name_attr = geis_attr_bag_find(device->attr_bag,
837+ GEIS_DEVICE_ATTRIBUTE_NAME);
838+ if (name_attr)
839+ {
840+ device_name = geis_attr_value_to_string(name_attr);
841+ }
842+ return device_name;
843 }
844
845
846
847=== added file 'libutouch-geis/geis_filter.c'
848--- libutouch-geis/geis_filter.c 1970-01-01 00:00:00 +0000
849+++ libutouch-geis/geis_filter.c 2011-01-06 00:59:08 +0000
850@@ -0,0 +1,456 @@
851+/**
852+ * @file libutouch-geis/geis_filter.c
853+ * @brief implementation of the uTouch GEIS v2.0 API filter module
854+ *
855+ * Copyright 2010, 2011 Canonical Ltd.
856+ *
857+ * This library is free software; you can redistribute it and/or modify it under
858+ * the terms of the GNU Lesser General Public License as published by the Free
859+ * Software Foundation; either version 3 of the License, or (at your option) any
860+ * later version.
861+ *
862+ * This library is distributed in the hope that it will be useful, but WITHOUT
863+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
864+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
865+ * details.
866+ *
867+ * You should have received a copy of the GNU Lesser General Public License
868+ * along with this program; if not, write to the Free Software Foundation, Inc.,
869+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
870+ */
871+#include "geis_config.h"
872+#include "geis_filter.h"
873+
874+#include "geis_attr.h"
875+#include "geis_error.h"
876+#include "geis_filter_term.h"
877+#include "geis_logging.h"
878+#include "geis_private.h"
879+#include <stdarg.h>
880+#include <stdlib.h>
881+#include <string.h>
882+
883+
884+struct _GeisFilter
885+{
886+ GeisSize ref_count;
887+ GeisString name;
888+ Geis geis;
889+ GeisFilterTermBag terms;
890+};
891+
892+struct _GeisFilterBag
893+{
894+ GeisFilter *filter_store;
895+ GeisSize filter_store_size;
896+ GeisSize filter_count;
897+};
898+
899+static const int filter_bag_growth_constant = 2;
900+
901+
902+/*
903+ * Creates a new filter bag,
904+ */
905+GeisFilterBag
906+geis_filter_bag_new()
907+{
908+ GeisFilterBag bag = calloc(1, sizeof(struct _GeisFilterBag));
909+ if (!bag)
910+ {
911+ geis_error("failed to allocate filter bag");
912+ goto final_exit;
913+ }
914+
915+ bag->filter_store_size = 3;
916+ bag->filter_count = 0;
917+ bag->filter_store = calloc(bag->filter_store_size, sizeof(GeisFilter));
918+ if (!bag->filter_store)
919+ {
920+ geis_error("failed to allocate filter bag store");
921+ goto unwind_bag;
922+ }
923+ goto final_exit;
924+
925+unwind_bag:
926+ free(bag);
927+final_exit:
928+ return bag;
929+}
930+
931+
932+/*
933+ * Destroys a filter bag.
934+ */
935+void
936+geis_filter_bag_delete(GeisFilterBag bag)
937+{
938+ GeisSize i;
939+ for (i = bag->filter_count; i > 0; --i)
940+ {
941+ geis_filter_delete(bag->filter_store[i-1]);
942+ }
943+ free(bag);
944+}
945+
946+
947+/*
948+ * Gets the number of filters in the bag.
949+ */
950+GeisSize
951+geis_filter_bag_count(GeisFilterBag bag)
952+{
953+ return bag->filter_count;
954+}
955+
956+
957+/*
958+ * Gets an indicated filter from a bag.
959+ */
960+GeisFilter
961+geis_filter_bag_filter(GeisFilterBag bag, GeisSize index)
962+{
963+ GeisFilter filter = NULL;
964+ if (index < bag->filter_count)
965+ {
966+ filter = bag->filter_store[index];
967+ }
968+ return filter;
969+}
970+
971+
972+/*
973+ * Inserts a filter in the bag.
974+ */
975+GeisStatus
976+geis_filter_bag_insert(GeisFilterBag bag, GeisFilter filter)
977+{
978+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
979+ geis_filter_ref(filter);
980+ if (bag->filter_count >= bag->filter_store_size)
981+ {
982+ GeisSize new_store_size = bag->filter_store_size * filter_bag_growth_constant;
983+ GeisFilter *new_store = realloc(bag->filter_store,
984+ new_store_size * sizeof(struct _GeisFilter));
985+ if (!new_store)
986+ {
987+ geis_error("failed to reallocate filter bag");
988+ goto error_exit;
989+ }
990+ bag->filter_store = new_store;
991+ bag->filter_store_size = new_store_size;
992+ }
993+ bag->filter_store[bag->filter_count++] = filter;
994+ status = GEIS_STATUS_SUCCESS;
995+ goto final_exit;
996+
997+error_exit:
998+ geis_filter_unref(filter);
999+final_exit:
1000+ return status;
1001+}
1002+
1003+
1004+/*
1005+ * Remoes a filter from the bag.
1006+ */
1007+GeisStatus
1008+geis_filter_bag_remove(GeisFilterBag bag, GeisFilter filter)
1009+{
1010+ GeisSize i;
1011+ GeisStatus status = GEIS_STATUS_SUCCESS;
1012+ for (i = 0; i < bag->filter_count; ++i)
1013+ {
1014+ if (bag->filter_store[i] == filter)
1015+ {
1016+ GeisSize j;
1017+ geis_filter_delete(bag->filter_store[i]);
1018+ --bag->filter_count;
1019+ for (j = i; j < bag->filter_count; ++j)
1020+ {
1021+ bag->filter_store[j] = bag->filter_store[j+1];
1022+ }
1023+ break;
1024+ }
1025+ }
1026+ return status;
1027+}
1028+
1029+
1030+/*
1031+ * Creates a GEIS v2.0 filter object.
1032+ */
1033+GeisFilter
1034+geis_filter_new(Geis geis, GeisString name)
1035+{
1036+ GeisFilter filter = calloc(1, sizeof(struct _GeisFilter));
1037+ if (!filter)
1038+ {
1039+ geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR);
1040+ geis_error("error allocating filter");
1041+ goto final_exit;
1042+ }
1043+
1044+ if (name)
1045+ {
1046+ filter->name = strdup(name);
1047+ }
1048+ else
1049+ {
1050+ filter->name = strdup("");
1051+ }
1052+ if (!filter->name)
1053+ {
1054+ geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR);
1055+ geis_error("error allocating filter name");
1056+ goto unwind_filter;
1057+ }
1058+
1059+ filter->terms = geis_filter_term_bag_new();
1060+ if (!filter->terms)
1061+ {
1062+ geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR);
1063+ geis_error("error allocating filter terms");
1064+ goto unwind_name;
1065+ }
1066+
1067+ filter->geis = geis;
1068+ geis_filter_ref(filter);
1069+ goto final_exit;
1070+
1071+unwind_name:
1072+ free((char *)filter->name);
1073+unwind_filter:
1074+ free(filter);
1075+ filter = NULL;
1076+final_exit:
1077+ return filter;
1078+}
1079+
1080+
1081+/*
1082+ * Destroys a GEIS v2.0 filter object.
1083+ */
1084+GeisStatus
1085+geis_filter_delete(GeisFilter filter)
1086+{
1087+ GeisStatus status = GEIS_STATUS_SUCCESS;
1088+ if (geis_filter_unref(filter) == 0)
1089+ {
1090+ geis_filter_term_bag_delete(filter->terms);
1091+ free((char *)filter->name);
1092+ free(filter);
1093+ }
1094+ return status;
1095+}
1096+
1097+
1098+/*
1099+ * Gets the name given to the filter when it was created.
1100+ */
1101+GeisString
1102+geis_filter_name(GeisFilter filter)
1103+{
1104+ return filter->name;
1105+}
1106+
1107+
1108+/*
1109+ * Indicates if the facility is valid.
1110+ */
1111+static GeisBoolean
1112+_facility_is_valid(GeisFilterFacility facility)
1113+{
1114+ return facility == GEIS_FILTER_DEVICE
1115+ || facility == GEIS_FILTER_GESTURE_TYPE
1116+ || facility == GEIS_FILTER_REGION;
1117+}
1118+
1119+
1120+/*
1121+ * Indicates if the operation is valid.
1122+ */
1123+static GeisBoolean
1124+_operation_is_valid(GeisFilterOperation op)
1125+{
1126+ return op == GEIS_FILTER_OP_EQ
1127+ || op == GEIS_FILTER_OP_NE
1128+ || op == GEIS_FILTER_OP_GT
1129+ || op == GEIS_FILTER_OP_GE
1130+ || op == GEIS_FILTER_OP_LT
1131+ || op == GEIS_FILTER_OP_LE;
1132+}
1133+
1134+
1135+/*
1136+ * Gets the attr description by name.
1137+ * @todo implement this function
1138+ */
1139+static GeisAttrType
1140+_get_attr_type_for_facility(Geis geis,
1141+ GeisFilterFacility facility,
1142+ GeisString attr_name)
1143+{
1144+ GeisAttrType type = GEIS_ATTR_TYPE_UNKNOWN;
1145+ switch (facility)
1146+ {
1147+ case GEIS_FILTER_DEVICE:
1148+ type = geis_get_device_attr_type(geis, attr_name);
1149+ break;
1150+ default:
1151+ break;
1152+ }
1153+ return type;
1154+}
1155+
1156+
1157+/*
1158+ * Adds a term to a filter.
1159+ */
1160+GeisStatus
1161+geis_filter_add_term(GeisFilter filter,
1162+ GeisFilterFacility facility,
1163+ ...)
1164+{
1165+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
1166+ va_list varargs;
1167+ GeisString attr_name;
1168+
1169+ if (!_facility_is_valid(facility))
1170+ {
1171+ status = GEIS_STATUS_BAD_ARGUMENT;
1172+ geis_error_push(filter->geis, status);
1173+ geis_error("invalid filter facility");
1174+ goto final_exit;
1175+ }
1176+
1177+ va_start(varargs, facility);
1178+ for (attr_name = va_arg(varargs, GeisString);
1179+ attr_name;
1180+ attr_name = va_arg(varargs, GeisString))
1181+ {
1182+ GeisAttrType attr_type = _get_attr_type_for_facility(filter->geis,
1183+ facility,
1184+ attr_name);
1185+ if (attr_type == GEIS_ATTR_TYPE_UNKNOWN)
1186+ {
1187+ status = GEIS_STATUS_BAD_ARGUMENT;
1188+ geis_error_push(filter->geis, status);
1189+ geis_error("invalid attr name for facility");
1190+ goto final_exit;
1191+ }
1192+
1193+ GeisFilterOperation op = va_arg(varargs, GeisFilterOperation);
1194+ if (!_operation_is_valid(op))
1195+ {
1196+ status = GEIS_STATUS_BAD_ARGUMENT;
1197+ geis_error_push(filter->geis, status);
1198+ geis_error("invalid filter operation");
1199+ goto final_exit;
1200+ }
1201+
1202+ switch (attr_type)
1203+ {
1204+ case GEIS_ATTR_TYPE_BOOLEAN:
1205+ {
1206+ GeisBoolean value = va_arg(varargs, GeisBoolean);
1207+ GeisAttr attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_BOOLEAN, &value);
1208+ GeisFilterTerm term = geis_filter_term_new(facility, op, attr);
1209+ geis_filter_term_bag_insert(filter->terms, term);
1210+ }
1211+ break;
1212+
1213+ case GEIS_ATTR_TYPE_FLOAT:
1214+ {
1215+ GeisFloat value = va_arg(varargs, double);
1216+ GeisAttr attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_FLOAT, &value);
1217+ GeisFilterTerm term = geis_filter_term_new(facility, op, attr);
1218+ geis_filter_term_bag_insert(filter->terms, term);
1219+ }
1220+ break;
1221+
1222+ case GEIS_ATTR_TYPE_INTEGER:
1223+ {
1224+ GeisInteger value = va_arg(varargs, GeisInteger);
1225+ GeisAttr attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_INTEGER, &value);
1226+ GeisFilterTerm term = geis_filter_term_new(facility, op, attr);
1227+ geis_filter_term_bag_insert(filter->terms, term);
1228+ }
1229+ break;
1230+
1231+ case GEIS_ATTR_TYPE_POINTER:
1232+ {
1233+ GeisPointer value = va_arg(varargs, GeisPointer);
1234+ GeisAttr attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_POINTER, value);
1235+ GeisFilterTerm term = geis_filter_term_new(facility, op, attr);
1236+ geis_filter_term_bag_insert(filter->terms, term);
1237+ }
1238+ break;
1239+
1240+ case GEIS_ATTR_TYPE_STRING:
1241+ {
1242+ GeisString value = va_arg(varargs, GeisString);
1243+ GeisAttr attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_STRING, (void *)value);
1244+ GeisFilterTerm term = geis_filter_term_new(facility, op, attr);
1245+ geis_filter_term_bag_insert(filter->terms, term);
1246+ }
1247+ break;
1248+
1249+ default:
1250+ status = GEIS_STATUS_BAD_ARGUMENT;
1251+ geis_error_push(filter->geis, status);
1252+ geis_error("invalid filter argument");
1253+ goto final_exit;
1254+ break;
1255+ }
1256+ }
1257+ va_end(varargs);
1258+ status = GEIS_STATUS_SUCCESS;
1259+
1260+final_exit:
1261+ return status;
1262+}
1263+
1264+
1265+/*
1266+ * Atomically increments filter refcount.
1267+ */
1268+void
1269+geis_filter_ref(GeisFilter filter)
1270+{
1271+ __sync_add_and_fetch(&filter->ref_count, 1);
1272+}
1273+
1274+
1275+/*
1276+ * Atomically decrements and returns filter refcount.
1277+ */
1278+GeisSize
1279+geis_filter_unref(GeisFilter filter)
1280+{
1281+ return __sync_sub_and_fetch(&filter->ref_count, 1);
1282+}
1283+
1284+/*
1285+ * Gets the number of terms in the filter grouped by facility.
1286+ */
1287+GeisSize
1288+geis_filter_term_by_facility_count(GeisFilter filter,
1289+ GeisFilterFacility facility)
1290+{
1291+ return geis_filter_term_bag_count(filter->terms, facility);
1292+}
1293+
1294+
1295+/*
1296+ * Gets the indicated term in the filter by facility.
1297+ */
1298+GeisFilterTerm
1299+geis_filter_term_by_facility(GeisFilter filter,
1300+ GeisFilterFacility facility,
1301+ GeisSize index)
1302+{
1303+ return geis_filter_term_bag_filter(filter->terms, facility, index);
1304+}
1305+
1306+
1307
1308=== added file 'libutouch-geis/geis_filter.h'
1309--- libutouch-geis/geis_filter.h 1970-01-01 00:00:00 +0000
1310+++ libutouch-geis/geis_filter.h 2011-01-06 00:59:08 +0000
1311@@ -0,0 +1,123 @@
1312+/**
1313+ * @file geis_filter.h
1314+ * @brief internal uTouch Geis filter module private interface
1315+ *
1316+ * Copyright 2010 Canonical Ltd.
1317+ *
1318+ * This library is free software; you can redistribute it and/or modify it under
1319+ * the terms of the GNU Lesser General Public License as published by the Free
1320+ * Software Foundation; either version 3 of the License, or (at your option) any
1321+ * later version.
1322+ *
1323+ * This library is distributed in the hope that it will be useful, but WITHOUT
1324+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1325+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1326+ * details.
1327+ *
1328+ * You should have received a copy of the GNU Lesser General Public License
1329+ * along with this program; if not, write to the Free Software Foundation, Inc.,
1330+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1331+ */
1332+#ifndef GEIS_FILTER_H_
1333+#define GEIS_FILTER_H_
1334+
1335+#include "geis/geis.h"
1336+#include "geis_filter_term.h"
1337+
1338+/**
1339+ * @defgroup utouch_geis_filter_container A Filter Container
1340+ * @{
1341+ */
1342+
1343+/**
1344+ * An unsorted container for holding filters.
1345+ */
1346+typedef struct _GeisFilterBag *GeisFilterBag;
1347+
1348+/**
1349+ * Creates a new filter bag,
1350+ */
1351+GeisFilterBag geis_filter_bag_new();
1352+
1353+/**
1354+ * Destroys a filter bag.
1355+ *
1356+ * @param[in] bag The filter bag,
1357+ */
1358+void geis_filter_bag_delete(GeisFilterBag bag);
1359+
1360+/**
1361+ * Gets the number of filters in the bag.
1362+ *
1363+ * @param[in] bag The filter bag,
1364+ */
1365+GeisSize geis_filter_bag_count(GeisFilterBag bag);
1366+
1367+/**t
1368+ * Gets an indicated filter from a bag.
1369+ *
1370+ * @param[in] bag The filter bag.
1371+ * @param[in] index The index.
1372+ */
1373+GeisFilter geis_filter_bag_filter(GeisFilterBag bag, GeisSize index);
1374+
1375+/**
1376+ * Inserts a filter in the bag.
1377+ *
1378+ * @param[in] bag The filter bag.
1379+ * @param[in] filter The filter to insert.
1380+ */
1381+GeisStatus geis_filter_bag_insert(GeisFilterBag bag, GeisFilter filter);
1382+
1383+/**
1384+ * Remoes a filter from the bag.
1385+ *
1386+ * @param[in] bag The filter bag.
1387+ * @param[in] filter The filter to remove.
1388+ */
1389+GeisStatus geis_filter_bag_remove(GeisFilterBag bag, GeisFilter filter);
1390+
1391+/** @} */
1392+
1393+/**
1394+ * @defgroup utouch_geis_filter_internals Filter Internals
1395+ * @{
1396+ */
1397+
1398+/**
1399+ * Increments the reference count on a filter.
1400+ *
1401+ * @param[in] filter The filter.
1402+ */
1403+void geis_filter_ref(GeisFilter filter);
1404+
1405+/**
1406+ * Decrements and returns the referemce count on a filter.
1407+ *
1408+ * @param[in] filter The filter.
1409+ */
1410+GeisSize geis_filter_unref(GeisFilter filter);
1411+
1412+/**
1413+ * Gets the number of terms in the filter grouped by facility.
1414+ *
1415+ * @param[in] filter The filter.
1416+ * @param[in] facility The facility.
1417+ */
1418+GeisSize geis_filter_term_by_facility_count(GeisFilter filter,
1419+ GeisFilterFacility facility);
1420+
1421+/**
1422+ * Gets the indicated term in the filter by facility.
1423+ *
1424+ * @param[in] filter The filter.
1425+ * @param[in] facility The facility.
1426+ * @param[in] index Indicates which term.
1427+ */
1428+GeisFilterTerm geis_filter_term_by_facility(GeisFilter filter,
1429+ GeisFilterFacility facility,
1430+ GeisSize index);
1431+
1432+/** @} */
1433+
1434+#endif /* GEIS_FILTER_H_ */
1435
1436=== added file 'libutouch-geis/geis_filter_term.c'
1437--- libutouch-geis/geis_filter_term.c 1970-01-01 00:00:00 +0000
1438+++ libutouch-geis/geis_filter_term.c 2011-01-06 00:59:08 +0000
1439@@ -0,0 +1,206 @@
1440+/**
1441+ * @file libutouch-geis/geis_filter_term.c
1442+ * @brief implementation of the uTouch GEIS v2.0 API filter term module
1443+ *
1444+ * Copyright 2011 Canonical Ltd.
1445+ *
1446+ * This library is free software; you can redistribute it and/or modify it under
1447+ * the terms of the GNU Lesser General Public License as published by the Free
1448+ * Software Foundation; either version 3 of the License, or (at your option) any
1449+ * later version.
1450+ *
1451+ * This library is distributed in the hope that it will be useful, but WITHOUT
1452+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1453+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1454+ * details.
1455+ *
1456+ * You should have received a copy of the GNU Lesser General Public License
1457+ * along with this program; if not, write to the Free Software Foundation, Inc.,
1458+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1459+ */
1460+#include "geis_config.h"
1461+#include "geis_filter_term.h"
1462+
1463+#include "geis_attr.h"
1464+#include "geis_error.h"
1465+#include "geis_logging.h"
1466+#include <stdlib.h>
1467+
1468+
1469+/*
1470+ * One of the terms of a filter.
1471+ */
1472+struct _GeisFilterTerm
1473+{
1474+ GeisFilterFacility facility;
1475+ GeisFilterOperation op;
1476+ GeisAttr attr;
1477+};
1478+
1479+
1480+/*
1481+ * All of the terms of a filter.
1482+ */
1483+struct _GeisFilterTermBag
1484+{
1485+ GeisFilterTerm *store;
1486+ GeisSize store_size;
1487+ GeisSize count;
1488+};
1489+
1490+static const GeisSize term_bag_growth_constant = 2;
1491+
1492+
1493+GeisFilterTermBag
1494+geis_filter_term_bag_new()
1495+{
1496+ GeisFilterTermBag bag = calloc(1, sizeof(struct _GeisFilterTermBag));
1497+ if (!bag)
1498+ {
1499+ geis_error("failed to allocate filter termbag");
1500+ goto final_exit;
1501+ }
1502+
1503+ bag->store_size = 3;
1504+ bag->count = 0;
1505+ bag->store = calloc(bag->store_size, sizeof(GeisFilterTerm));
1506+ if (!bag->store)
1507+ {
1508+ geis_error("failed to allocate filter bag store");
1509+ goto unwind_bag;
1510+ }
1511+ goto final_exit;
1512+
1513+unwind_bag:
1514+ free(bag);
1515+ bag = NULL;
1516+final_exit:
1517+ return bag;
1518+}
1519+
1520+
1521+void
1522+geis_filter_term_bag_delete(GeisFilterTermBag bag)
1523+{
1524+ free(bag);
1525+}
1526+
1527+
1528+GeisSize
1529+geis_filter_term_bag_count(GeisFilterTermBag bag, GeisFilterFacility facility)
1530+{
1531+ GeisSize count = 0;
1532+ GeisSize i = 0;
1533+ while (i < bag->count)
1534+ {
1535+ if (bag->store[i]->facility == facility)
1536+ ++count;
1537+ ++i;
1538+ }
1539+ return count;
1540+}
1541+
1542+
1543+GeisFilterTerm
1544+geis_filter_term_bag_filter(GeisFilterTermBag bag,
1545+ GeisFilterFacility facility,
1546+ GeisSize index)
1547+{
1548+ GeisFilterTerm term = NULL;
1549+ GeisSize count = 0;
1550+ GeisSize i = 0;
1551+ while (i < bag->count)
1552+ {
1553+ if (bag->store[i]->facility == facility)
1554+ {
1555+ if (count == index)
1556+ {
1557+ term = bag->store[i];
1558+ break;
1559+ }
1560+ ++count;
1561+ }
1562+ ++i;
1563+ }
1564+ return term;
1565+}
1566+
1567+
1568+GeisStatus
1569+geis_filter_term_bag_insert(GeisFilterTermBag bag,
1570+ GeisFilterTerm term)
1571+{
1572+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
1573+ if (bag->count >= bag->store_size)
1574+ {
1575+ GeisSize new_store_size = bag->store_size * term_bag_growth_constant;
1576+ GeisFilterTerm *new_store = realloc(bag->store,
1577+ new_store_size * sizeof(struct _GeisFilterTerm));
1578+ if (!new_store)
1579+ {
1580+ geis_error("failed to reallocate filter term bag");
1581+ goto error_exit;
1582+ }
1583+ bag->store = new_store;
1584+ bag->store_size = new_store_size;
1585+ }
1586+ bag->store[bag->count++] = term;
1587+ status = GEIS_STATUS_SUCCESS;
1588+ goto final_exit;
1589+
1590+error_exit:
1591+final_exit:
1592+ return status;
1593+}
1594+
1595+
1596+GeisFilterTerm
1597+geis_filter_term_new(GeisFilterFacility facility,
1598+ GeisFilterOperation operation,
1599+ GeisAttr attr)
1600+{
1601+ GeisFilterTerm term = calloc(1, sizeof(struct _GeisFilterTerm));
1602+ if (!term)
1603+ {
1604+ geis_error("failed to allocate filter termbag");
1605+ goto final_exit;
1606+ }
1607+ term->facility = facility;
1608+ term->op = operation;
1609+ term->attr = attr;
1610+
1611+final_exit:
1612+ return term;
1613+}
1614+
1615+
1616+void
1617+geis_filter_term_delete(GeisFilterTerm term)
1618+{
1619+ geis_attr_delete(term->attr);
1620+ free(term);
1621+}
1622+
1623+
1624+GeisFilterFacility
1625+geis_filter_term_facility(GeisFilterTerm term)
1626+{
1627+ return term->facility;
1628+}
1629+
1630+
1631+GeisFilterOperation
1632+geis_filter_term_operation(GeisFilterTerm term)
1633+{
1634+ return term->op;
1635+}
1636+
1637+
1638+GeisAttr
1639+geis_filter_term_attr(GeisFilterTerm term)
1640+{
1641+ return term->attr;
1642+}
1643+
1644+
1645+
1646
1647=== added file 'libutouch-geis/geis_filter_term.h'
1648--- libutouch-geis/geis_filter_term.h 1970-01-01 00:00:00 +0000
1649+++ libutouch-geis/geis_filter_term.h 2011-01-06 00:59:08 +0000
1650@@ -0,0 +1,139 @@
1651+/**
1652+ * @file geis_filter_term.h
1653+ * @brief internal uTouch Geis filter term module private interface
1654+ *
1655+ * Copyright 2011 Canonical Ltd.
1656+ *
1657+ * This library is free software; you can redistribute it and/or modify it under
1658+ * the terms of the GNU Lesser General Public License as published by the Free
1659+ * Software Foundation; either version 3 of the License, or (at your option) any
1660+ * later version.
1661+ *
1662+ * This library is distributed in the hope that it will be useful, but WITHOUT
1663+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1664+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1665+ * details.
1666+ *
1667+ * You should have received a copy of the GNU Lesser General Public License
1668+ * along with this program; if not, write to the Free Software Foundation, Inc.,
1669+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1670+ */
1671+#ifndef GEIS_FILTER_TERM_H_
1672+#define GEIS_FILTER_TERM_H_
1673+
1674+#include "geis/geis.h"
1675+
1676+/**
1677+ * @defgroup utouch_geis_filter_term Filter Terms.
1678+ * @{
1679+ */
1680+
1681+/**
1682+ * One of the terms of a filter.
1683+ *
1684+ * A term belong to a facility (eg. device, gesture type, region) and is used to
1685+ * compare (using an operation) a named attribute with a given value.
1686+ */
1687+typedef struct _GeisFilterTerm *GeisFilterTerm;
1688+
1689+/**
1690+ * Creates a new filter term.
1691+ *
1692+ * @param[in] facility The term's facility.
1693+ * @param[in] operation The term's operation.
1694+ * @param[in] attr The term's attr name, type, and value
1695+ */
1696+GeisFilterTerm geis_filter_term_new(GeisFilterFacility facility,
1697+ GeisFilterOperation operation,
1698+ GeisAttr attr);
1699+
1700+/**
1701+ * Destroys a filter term.
1702+ *
1703+ * @param[in] term The filter term.
1704+ */
1705+void geis_filter_term_delete(GeisFilterTerm term);
1706+
1707+/**
1708+ * Gets a filter term's facility.
1709+ *
1710+ * @param[in] term The filter term.
1711+ */
1712+GeisFilterFacility geis_filter_term_facility(GeisFilterTerm term);
1713+
1714+/**
1715+ * Gets a filter term's operation.
1716+ *
1717+ * @param[in] term The filter term.
1718+ */
1719+GeisFilterOperation geis_filter_term_operation(GeisFilterTerm term);
1720+
1721+/**
1722+ * Gets a filter term's attributes.
1723+ *
1724+ * @param[in] term The filter term.
1725+ */
1726+GeisAttr geis_filter_term_attr(GeisFilterTerm term);
1727+
1728+/** @} */
1729+
1730+/**
1731+ * @defgroup utouch_geis_filter_term_container A Filter Term Container
1732+ * @{
1733+ */
1734+
1735+/**
1736+ * An unsorted container for holding filter terms.
1737+ *
1738+ * This implementation is physically unsorted, but terms are logically grouped
1739+ * by facility.
1740+ *
1741+ * This is a purely internal structure, as is the filter term. The bag "owns"
1742+ * the term.
1743+ */
1744+typedef struct _GeisFilterTermBag *GeisFilterTermBag;
1745+
1746+/**
1747+ * Creates a new filter term bag,
1748+ */
1749+GeisFilterTermBag geis_filter_term_bag_new();
1750+
1751+/**
1752+ * Destroys a filter term bag.
1753+ *
1754+ * @param[in] bag The filter term bag.
1755+ */
1756+void geis_filter_term_bag_delete(GeisFilterTermBag bag);
1757+
1758+/**
1759+ * Gets the number of filter terms in the bag for a given facility.
1760+ *
1761+ * @param[in] bag The filter term bag.
1762+ * @param[in] facility The facility.
1763+ */
1764+GeisSize geis_filter_term_bag_count(GeisFilterTermBag bag,
1765+ GeisFilterFacility facility);
1766+
1767+/**
1768+ * Gets an indicated filter term from a bag.
1769+ *
1770+ * @param[in] bag The filter bag.
1771+ * @param[in] facility The facility.
1772+ * @param[in] index The index.
1773+ */
1774+GeisFilterTerm geis_filter_term_bag_filter(GeisFilterTermBag bag,
1775+ GeisFilterFacility facility,
1776+ GeisSize index);
1777+
1778+/**
1779+ * Inserts a filter in the bag.
1780+ *
1781+ * @param[in] bag The filter bag.
1782+ * @param[in] term The filter to insert.
1783+ */
1784+GeisStatus geis_filter_term_bag_insert(GeisFilterTermBag bag,
1785+ GeisFilterTerm term);
1786+
1787+/** @} */
1788+
1789+#endif /* GEIS_FILTER_TERM_H_ */
1790
1791=== modified file 'libutouch-geis/geis_private.h'
1792--- libutouch-geis/geis_private.h 2010-12-15 01:48:35 +0000
1793+++ libutouch-geis/geis_private.h 2011-01-06 00:59:08 +0000
1794@@ -5,7 +5,7 @@
1795 * This file is the internal interface to the GEIS API object. It provides the
1796 * implementation hooks for back ends to pass information through the API.
1797 *
1798- * Copyright 2010 Canonical Ltd.
1799+ * Copyright 2010, 2011 Canonical Ltd.
1800 *
1801 * This library is free software; you can redistribute it and/or modify it under
1802 * the terms of the GNU Lesser General Public License as published by the Free
1803@@ -90,4 +90,19 @@
1804 */
1805 GeisStatus geis_deactivate_subscription(Geis geis, GeisSubscription sub);
1806
1807+/**
1808+ * Gets the type of a named device attr.
1809+ *
1810+ * @param[in] geis The API instance.
1811+ * @param[in] attr_name The name of the device attr.
1812+ *
1813+ * Gets the type of a device attr by name, assuming the attr is known.
1814+ *
1815+ * There is a basic assumption that all device attrs of the same name are of the
1816+ * same type.
1817+ *
1818+ * @returns the type of the attr, GEIS_ATTR_TYPE_UNKNOWN if the attr is unknown.
1819+ */
1820+GeisAttrType geis_get_device_attr_type(Geis geis, GeisString attr_name);
1821+
1822 #endif /* GEIS_PRIVATE_H_ */
1823
1824=== modified file 'libutouch-geis/geis_subscription.c'
1825--- libutouch-geis/geis_subscription.c 2010-12-15 01:48:35 +0000
1826+++ libutouch-geis/geis_subscription.c 2011-01-06 00:59:08 +0000
1827@@ -2,7 +2,7 @@
1828 * @file libutouch-geis/geis_subscription.c
1829 * @brief implementation of the uTouch GEIS v2.0 API subscription module
1830 *
1831- * Copyright 2010 Canonical Ltd.
1832+ * Copyright 2010, 2011 Canonical Ltd.
1833 *
1834 * This library is free software; you can redistribute it and/or modify it under
1835 * the terms of the GNU Lesser General Public License as published by the Free
1836@@ -22,8 +22,9 @@
1837 #include "geis_subscription.h"
1838
1839 #include "geis/geis.h"
1840+#include "geis_filter.h"
1841+#include "geis_logging.h"
1842 #include "geis_private.h"
1843-#include "geis_logging.h"
1844 #include <math.h>
1845 #include <stdlib.h>
1846 #include <string.h>
1847@@ -35,6 +36,7 @@
1848 GeisInteger sub_id;
1849 GeisString sub_name;
1850 GeisSubscriptionFlags sub_flags;
1851+ GeisFilterBag sub_filters;
1852 };
1853
1854 struct _GeisSubBag
1855@@ -126,12 +128,12 @@
1856 }
1857
1858 GeisSize new_store_size = ceilf(bag->sub_store_size * sub_bag_growth_constant);
1859- geis_debug(". new_store_size=%ld", new_store_size);
1860 GeisSubscription *new_store = realloc(bag->sub_store,
1861 new_store_size * sizeof(struct _GeisSubBag));
1862 if (!new_store)
1863 {
1864 geis_error("failed to reallocate sub bag");
1865+ index = -1;
1866 goto final_exit;
1867 }
1868 index = bag->sub_store_size;
1869@@ -208,26 +210,54 @@
1870 if (!sub)
1871 {
1872 geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR);
1873- geis_error("calloc failed");
1874- goto error_exit;
1875+ geis_error("error allocating subscription");
1876+ goto final_exit;
1877+ }
1878+
1879+ if (sub_name)
1880+ {
1881+ sub->sub_name = strdup(sub_name);
1882 }
1883 else
1884 {
1885- if (sub_name)
1886- {
1887- sub->sub_name = strdup(sub_name);
1888- }
1889- else
1890- {
1891- sub->sub_name = strdup("");
1892- }
1893- sub->sub_geis = geis;
1894- sub->sub_id = geis_subscription_bag_insert(geis_subscription_bag(geis), sub);
1895- sub->sub_flags = sub_flags;
1896- geis_debug("created subscription \"%s\" id %d", sub->sub_name, sub->sub_id);
1897- }
1898-
1899-error_exit:
1900+ sub->sub_name = strdup("");
1901+ }
1902+ if (!sub->sub_name)
1903+ {
1904+ geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR);
1905+ geis_error("error allocating subscription name");
1906+ goto unwind_sub;
1907+ }
1908+
1909+ sub->sub_filters = geis_filter_bag_new();
1910+ if (!sub->sub_filters)
1911+ {
1912+ geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR);
1913+ geis_error("error allocating subscription filters");
1914+ goto unwind_name;
1915+ }
1916+
1917+ sub->sub_id = geis_subscription_bag_insert(geis_subscription_bag(geis), sub);
1918+ if (sub->sub_id < 0)
1919+ {
1920+ geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR);
1921+ geis_error("error storing subscription");
1922+ goto unwind_filters;
1923+ }
1924+
1925+ sub->sub_geis = geis;
1926+ sub->sub_flags = sub_flags;
1927+ geis_debug("created subscription \"%s\" id %d", sub->sub_name, sub->sub_id);
1928+ goto final_exit;
1929+
1930+unwind_filters:
1931+ geis_filter_bag_delete(sub->sub_filters);
1932+unwind_name:
1933+ free((char *)sub->sub_name);
1934+unwind_sub:
1935+ free(sub);
1936+ sub = NULL;
1937+final_exit:
1938 return sub;
1939 }
1940
1941@@ -289,7 +319,7 @@
1942 */
1943 GeisStatus
1944 geis_subscription_add_filter(GeisSubscription sub,
1945- GeisFilter filter __attribute__((unused)))
1946+ GeisFilter filter)
1947 {
1948 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
1949 if (!sub)
1950@@ -298,6 +328,14 @@
1951 goto error_exit;
1952 }
1953
1954+ status = geis_filter_bag_insert(sub->sub_filters, filter);
1955+ if (status != GEIS_STATUS_SUCCESS)
1956+ {
1957+ geis_error_push(sub->sub_geis, GEIS_STATUS_UNKNOWN_ERROR);
1958+ geis_error("error adding filter to subscription");
1959+ goto error_exit;
1960+ }
1961+
1962 error_exit:
1963 return status;
1964 }
1965@@ -310,7 +348,7 @@
1966 */
1967 GeisStatus
1968 geis_subscription_remove_filter(GeisSubscription sub,
1969- GeisFilter filter __attribute__((unused)))
1970+ GeisFilter filter)
1971 {
1972 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
1973 if (!sub)
1974@@ -319,8 +357,36 @@
1975 goto error_exit;
1976 }
1977
1978+ status = geis_filter_bag_remove(sub->sub_filters, filter);
1979+ if (status != GEIS_STATUS_SUCCESS)
1980+ {
1981+ geis_error_push(sub->sub_geis, GEIS_STATUS_UNKNOWN_ERROR);
1982+ geis_error("error removing filter from subscription");
1983+ goto error_exit;
1984+ }
1985+
1986 error_exit:
1987 return status;
1988 }
1989
1990
1991+/*
1992+ * Gets the numvber of filters in a subscirption.
1993+ */
1994+GeisSize
1995+geis_subscription_filter_count(GeisSubscription sub)
1996+{
1997+ return geis_filter_bag_count(sub->sub_filters);
1998+}
1999+
2000+
2001+/*
2002+ * Gets an indicated filter from a subscription.
2003+ */
2004+GeisFilter
2005+geis_subscription_filter(GeisSubscription sub, GeisSize index)
2006+{
2007+ return geis_filter_bag_filter(sub->sub_filters, index);
2008+}
2009+
2010+
2011
2012=== modified file 'libutouch-geis/geis_subscription.h'
2013--- libutouch-geis/geis_subscription.h 2010-12-15 01:48:35 +0000
2014+++ libutouch-geis/geis_subscription.h 2011-01-06 00:59:08 +0000
2015@@ -2,7 +2,7 @@
2016 * @file geis_subscription.h
2017 * @brief internal uTouch Geis subscription modul private interface
2018 *
2019- * Copyright 2010 Canonical Ltd.
2020+ * Copyright 2010, 2011 Canonical Ltd.
2021 *
2022 * This library is free software; you can redistribute it and/or modify it under
2023 * the terms of the GNU Lesser General Public License as published by the Free
2024@@ -25,6 +25,11 @@
2025
2026
2027 /**
2028+ * @defgroup utouch_geis_sub_container A Subscription Container
2029+ * @{
2030+ */
2031+
2032+/**
2033 * A container for subscriptions.
2034 */
2035 typedef struct _GeisSubBag *GeisSubBag;
2036@@ -79,5 +84,21 @@
2037 */
2038 GeisSubscription geis_subscription_bag_find(GeisSubBag bag, GeisInteger sub_id);
2039
2040+/* @} */
2041+
2042+/**
2043+ * Gets the numvber of filters in a subscirption.
2044+ *
2045+ * @param[in] sub The subscription.
2046+ */
2047+GeisSize geis_subscription_filter_count(GeisSubscription sub);
2048+
2049+/**
2050+ * Gets an indicated filter from a subscription.
2051+ *
2052+ * @param[in] sub The subscription.
2053+ * @param[in] index Indicates which filter to retrieve.
2054+ */
2055+GeisFilter geis_subscription_filter(GeisSubscription sub, GeisSize index);
2056
2057 #endif /* GEIS_SUBSCRIPTION_H_ */
2058
2059=== modified file 'libutouch-geis/libutouch-geis.ver'
2060--- libutouch-geis/libutouch-geis.ver 2010-12-21 01:47:05 +0000
2061+++ libutouch-geis/libutouch-geis.ver 2011-01-06 00:59:08 +0000
2062@@ -31,6 +31,15 @@
2063 geis_error_code;
2064 geis_error_count;
2065 geis_error_message;
2066+ geis_event_attr;
2067+ geis_event_attr_by_name;
2068+ geis_event_attr_count;
2069+ geis_event_delete;
2070+ geis_event_type;
2071+ geis_filter_add_term;
2072+ geis_filter_delete;
2073+ geis_filter_name;
2074+ geis_filter_new;
2075 geis_get_configuration;
2076 geis_new;
2077 geis_next_event;
2078
2079=== modified file 'testsuite/geis2/Makefile.am'
2080--- testsuite/geis2/Makefile.am 2010-12-29 20:23:01 +0000
2081+++ testsuite/geis2/Makefile.am 2011-01-06 00:59:08 +0000
2082@@ -19,6 +19,7 @@
2083 check_device.c \
2084 check_error_codes.c \
2085 check_event.c \
2086+ check_filter.c \
2087 check_geis_new.c \
2088 check_general_types.c \
2089 check_region.c \
2090
2091=== modified file 'testsuite/geis2/check_device.c'
2092--- testsuite/geis2/check_device.c 2010-12-21 01:47:05 +0000
2093+++ testsuite/geis2/check_device.c 2011-01-06 00:59:08 +0000
2094@@ -5,6 +5,24 @@
2095
2096 #include <geis/geis.h>
2097
2098+/* fixtures */
2099+static Geis g_geis;
2100+
2101+/* fixture setup */
2102+static void
2103+construct_geis()
2104+{
2105+ g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, GEIS_INIT_TRACK_DEVICES, NULL);
2106+}
2107+
2108+/* fixture teardown */
2109+static void
2110+destroy_geis()
2111+{
2112+ geis_delete(g_geis);
2113+}
2114+
2115+
2116 /* Compile-time test to ensure types are defined */
2117 START_TEST(geis_device_types)
2118 {
2119@@ -29,6 +47,23 @@
2120 }
2121 END_TEST
2122
2123+START_TEST(receive_events)
2124+{
2125+ GeisStatus status;
2126+ GeisEvent event_out;
2127+
2128+ status = geis_dispatch_events(g_geis);
2129+ fail_unless(status == GEIS_STATUS_SUCCESS,
2130+ "unexpected status from geis_dispatch_events");
2131+ status = geis_next_event(g_geis, &event_out);
2132+ fail_unless(status == GEIS_STATUS_SUCCESS,
2133+ "unexpected status from geis_dispatch_events");
2134+ fail_unless(geis_event_type(event_out) == GEIS_EVENT_DEVICE_AVAILABLE,
2135+ "unexpected event type received");
2136+
2137+}
2138+END_TEST
2139+
2140
2141 /* boilerplate */
2142 Suite *
2143@@ -36,10 +71,15 @@
2144 {
2145 Suite *s = suite_create("geis2_device");
2146
2147- TCase *device = tcase_create("geis2_device");
2148+ TCase *device = tcase_create("device-api");
2149 tcase_add_test(device, geis_device_types);
2150 suite_add_tcase(s, device);
2151
2152+ TCase *usage = tcase_create("device-usage");
2153+ tcase_add_checked_fixture(usage, construct_geis, destroy_geis);
2154+ tcase_add_test(usage, receive_events);
2155+ suite_add_tcase(s, usage);
2156+
2157 return s;
2158 }
2159
2160
2161=== added file 'testsuite/geis2/check_filter.c'
2162--- testsuite/geis2/check_filter.c 1970-01-01 00:00:00 +0000
2163+++ testsuite/geis2/check_filter.c 2011-01-06 00:59:08 +0000
2164@@ -0,0 +1,41 @@
2165+/**
2166+ * Unit tests for GEIS v2.0 Filter Module.
2167+ */
2168+#include <check.h>
2169+
2170+#include <geis/geis.h>
2171+
2172+/* Compile-time test to ensure types are defined */
2173+START_TEST(geis_filter_types)
2174+{
2175+ GeisFilter type;
2176+}
2177+END_TEST
2178+
2179+/* Compile-and-link-time test to verify required functions exist */
2180+START_TEST(geis_filter_functions)
2181+{
2182+ Geis geis;
2183+ GeisFilter filter = geis_filter_new(geis, "filter");
2184+ GeisString name = geis_filter_name(filter);
2185+ GeisStatus status = geis_filter_add_term(filter, GEIS_FILTER_GESTURE_TYPE,
2186+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1,
2187+ NULL);
2188+ geis_filter_delete(filter);
2189+}
2190+END_TEST
2191+
2192+
2193+/* boilerplate */
2194+Suite *
2195+geis2_filter_suite_new()
2196+{
2197+ Suite *s = suite_create("geis2_filter");
2198+
2199+ TCase *filter = tcase_create("geis2_filter");
2200+ tcase_add_test(filter, geis_filter_types);
2201+ suite_add_tcase(s, filter);
2202+
2203+ return s;
2204+}
2205+
2206
2207=== modified file 'testsuite/geis2/check_geis2_api.c'
2208--- testsuite/geis2/check_geis2_api.c 2010-12-21 01:47:05 +0000
2209+++ testsuite/geis2/check_geis2_api.c 2011-01-06 00:59:08 +0000
2210@@ -12,6 +12,7 @@
2211 extern Suite *geis2_config_suite_new();
2212 extern Suite *geis2_attr_suite_new();
2213 extern Suite *geis2_region_suite_new();
2214+extern Suite *geis2_filter_suite_new();
2215 extern Suite *geis2_subscription_suite_new();
2216 extern Suite *geis2_event_suite_new();
2217
2218@@ -31,6 +32,7 @@
2219 srunner_add_suite(sr, geis2_attr_suite_new());
2220 srunner_add_suite(sr, geis2_region_suite_new());
2221 srunner_add_suite(sr, geis2_device_suite_new());
2222+ srunner_add_suite(sr, geis2_filter_suite_new());
2223 srunner_add_suite(sr, geis2_subscription_suite_new());
2224 srunner_add_suite(sr, geis2_event_suite_new());
2225
2226
2227=== modified file 'testsuite/geis2/check_subscription.c'
2228--- testsuite/geis2/check_subscription.c 2010-12-15 01:48:35 +0000
2229+++ testsuite/geis2/check_subscription.c 2011-01-06 00:59:08 +0000
2230@@ -14,7 +14,7 @@
2231 static void
2232 construct_geis()
2233 {
2234- g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, NULL);
2235+ g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, GEIS_INIT_TRACK_DEVICES, NULL);
2236 }
2237
2238 /* fixture teardown */
2239@@ -51,6 +51,69 @@
2240 }
2241 END_TEST
2242
2243+
2244+START_TEST(filter)
2245+{
2246+ GeisFilter filter = geis_filter_new(g_geis, "filter");
2247+ GeisSubscription sub = geis_subscription_new(g_geis,
2248+ "name",
2249+ GEIS_SUBSCRIPTION_NONE);
2250+ fail_unless(GEIS_STATUS_SUCCESS == geis_subscription_add_filter(sub, filter));
2251+ fail_unless(GEIS_STATUS_SUCCESS == geis_subscription_remove_filter(sub, filter));
2252+}
2253+END_TEST
2254+
2255+
2256+START_TEST(device_filter)
2257+{
2258+ GeisStatus status;
2259+ GeisEvent event;
2260+
2261+ GeisSubscription sub = geis_subscription_new(g_geis,
2262+ "devices",
2263+ GEIS_SUBSCRIPTION_NONE);
2264+
2265+ while (geis_dispatch_events(g_geis) == GEIS_STATUS_CONTINUE)
2266+ ;
2267+ status = geis_next_event(g_geis, &event);
2268+ while (status == GEIS_STATUS_SUCCESS || status == GEIS_STATUS_CONTINUE)
2269+ {
2270+ if (geis_event_type(event) == GEIS_EVENT_DEVICE_AVAILABLE)
2271+ {
2272+ GeisAttr attr = geis_event_attr_by_name(event, "geis-device");
2273+ fail_if (!attr, "geis-device attr not found in device event");
2274+
2275+ GeisDevice device = geis_attr_value_to_pointer(attr);
2276+ fail_if (!device, "geis device not found in device event");
2277+
2278+ GeisFilter filter = geis_filter_new(g_geis, "device filter");
2279+ fail_if(!filter, "can not create filter");
2280+
2281+ GeisStatus fs = geis_filter_add_term(filter, GEIS_FILTER_DEVICE,
2282+ GEIS_DEVICE_ATTRIBUTE_NAME, GEIS_FILTER_OP_NE, geis_device_name(device),
2283+ NULL);
2284+ fail_if(fs != GEIS_STATUS_SUCCESS, "can not add device to filter");
2285+
2286+ fs = geis_subscription_add_filter(sub, filter);
2287+ fail_if(fs != GEIS_STATUS_SUCCESS, "can not subscribe filter");
2288+
2289+ if (status == GEIS_STATUS_CONTINUE)
2290+ {
2291+ status = geis_next_event(g_geis, &event);
2292+ }
2293+ else
2294+ {
2295+ break;
2296+ }
2297+ }
2298+ }
2299+
2300+ fail_unless(GEIS_STATUS_SUCCESS == geis_subscription_activate(sub),
2301+ "unable to activate subscription");
2302+}
2303+END_TEST
2304+
2305+
2306 /* boilerplate */
2307 Suite *
2308 geis2_subscription_suite_new()
2309@@ -64,6 +127,8 @@
2310 TCase *usage = tcase_create("subscription-usage");
2311 tcase_add_checked_fixture(usage, construct_geis, destroy_geis);
2312 tcase_add_test(usage, construction);
2313+ tcase_add_test(usage, filter);
2314+ tcase_add_test(usage, device_filter);
2315 suite_add_tcase(s, usage);
2316
2317 return s;
2318
2319=== modified file 'testsuite/libutouch-geis/Makefile.am'
2320--- testsuite/libutouch-geis/Makefile.am 2010-12-29 20:23:01 +0000
2321+++ testsuite/libutouch-geis/Makefile.am 2011-01-06 00:59:08 +0000
2322@@ -36,6 +36,7 @@
2323 check_device.c \
2324 check_error_reporting.c \
2325 check_event_queue.c \
2326+ check_filter.c \
2327 check_geis_private.c \
2328 check_region.c \
2329 check_subscription.c \
2330
2331=== added file 'testsuite/libutouch-geis/check_filter.c'
2332--- testsuite/libutouch-geis/check_filter.c 1970-01-01 00:00:00 +0000
2333+++ testsuite/libutouch-geis/check_filter.c 2011-01-06 00:59:08 +0000
2334@@ -0,0 +1,101 @@
2335+/**
2336+ * unit tests for the geis filter module
2337+ */
2338+#include <check.h>
2339+
2340+#include "libutouch-geis/geis_filter.h"
2341+
2342+
2343+/* fixtures */
2344+static Geis g_geis;
2345+static GeisFilterBag g_filter_bag;
2346+static GeisString g_filter_name = "filter";
2347+
2348+/* fixture setup */
2349+static void
2350+construct_bag()
2351+{
2352+ g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, NULL);
2353+ g_filter_bag = geis_filter_bag_new();
2354+}
2355+
2356+/* fixture teardown */
2357+static void
2358+destroy_bag()
2359+{
2360+ geis_filter_bag_delete(g_filter_bag);
2361+ geis_delete(g_geis);
2362+}
2363+
2364+/* verify bag construction/destruction */
2365+START_TEST(construct)
2366+{
2367+ GeisFilterBag bag = geis_filter_bag_new();
2368+ fail_unless(bag != NULL, "failed to create filter bag");
2369+ geis_filter_bag_delete(bag);
2370+}
2371+END_TEST
2372+
2373+/* verify bag insertion */
2374+START_TEST(insert)
2375+{
2376+ GeisFilter filter = geis_filter_new(g_geis, g_filter_name);
2377+ geis_filter_bag_insert(g_filter_bag, filter);
2378+ fail_unless(geis_filter_bag_count(g_filter_bag) == 1,
2379+ "unexpected bag size after insertion");
2380+}
2381+END_TEST
2382+
2383+/* verify bag removal */
2384+START_TEST(remove)
2385+{
2386+ GeisFilter filter = geis_filter_new(g_geis, g_filter_name);
2387+ geis_filter_bag_insert(g_filter_bag, filter);
2388+ fail_unless(geis_filter_bag_count(g_filter_bag) == 1,
2389+ "unexpected bag size after insertion");
2390+ geis_filter_bag_remove(g_filter_bag, filter);
2391+ fail_unless(geis_filter_bag_count(g_filter_bag) == 0,
2392+ "unexpected bag size after removal");
2393+}
2394+END_TEST
2395+
2396+START_TEST(expand)
2397+{
2398+ int i;
2399+ for (i = 0; i < 24; ++i)
2400+ {
2401+ GeisSize count;
2402+ char name[32];
2403+ sprintf(name, "%04d", i);
2404+ GeisFilter filter = geis_filter_new(g_geis, name);
2405+ geis_filter_bag_insert(g_filter_bag, filter);
2406+ count = geis_filter_bag_count(g_filter_bag);
2407+ fail_unless(count == (i+1),
2408+ "unexpected bag size %ld after insertion, expected %d",
2409+ count, i+1);
2410+ }
2411+}
2412+END_TEST
2413+
2414+
2415+
2416+/* boilerplate */
2417+Suite *
2418+make_filter_suite()
2419+{
2420+ Suite *s = suite_create("utouch-geis2-filter");
2421+
2422+ TCase *create = tcase_create("filter-bag-creation");
2423+ tcase_add_test(create, construct);
2424+ suite_add_tcase(s, create);
2425+
2426+ TCase *usage = tcase_create("filter-bag-usage");
2427+ tcase_add_checked_fixture(usage, construct_bag, destroy_bag);
2428+ tcase_add_test(usage, insert);
2429+ tcase_add_test(usage, remove);
2430+ tcase_add_test(usage, expand);
2431+ suite_add_tcase(s, usage);
2432+
2433+ return s;
2434+}
2435+
2436
2437=== modified file 'testsuite/libutouch-geis/check_geis2_internals.c'
2438--- testsuite/libutouch-geis/check_geis2_internals.c 2010-12-21 13:59:31 +0000
2439+++ testsuite/libutouch-geis/check_geis2_internals.c 2011-01-06 00:59:08 +0000
2440@@ -11,6 +11,7 @@
2441 extern Suite *make_device_suite();
2442 extern Suite *make_error_reporting_suite();
2443 extern Suite *make_event_queue_suite();
2444+extern Suite *make_filter_suite();
2445 extern Suite *make_region_suite();
2446 extern Suite *make_subscription_suite();
2447
2448@@ -30,6 +31,7 @@
2449 srunner_add_suite(sr, make_backend_event_posting_suite());
2450 srunner_add_suite(sr, make_device_suite());
2451 srunner_add_suite(sr, make_region_suite());
2452+ srunner_add_suite(sr, make_filter_suite());
2453 srunner_add_suite(sr, make_subscription_suite());
2454
2455 srunner_set_log(sr, LOGFILE_PREFIX".log");

Subscribers

People subscribed via source and target branches

to all changes: