Merge lp:geis/client-arch into lp:geis

Proposed by Stephen M. Webb
Status: Superseded
Proposed branch: lp:geis/client-arch
Merge into: lp:geis
Diff against target: 9682 lines (+7292/-647)
88 files modified
.bzrignore (+7/-1)
Makefile.am (+1/-0)
configure.ac (+4/-1)
include/geis/geis.h (+11/-8)
libs/Makefile.am (+1/-1)
libs/geis-dbus/Makefile.am (+41/-0)
libs/geis-dbus/geis_dbus.h (+37/-8)
libs/geis-dbus/geis_dbus_attr.c (+178/-0)
libs/geis-dbus/geis_dbus_attr.h (+57/-0)
libs/geis-dbus/geis_dbus_class.c (+126/-0)
libs/geis-dbus/geis_dbus_class.h (+45/-0)
libs/geis-dbus/geis_dbus_device.c (+152/-0)
libs/geis-dbus/geis_dbus_device.h (+61/-0)
libs/geis-dbus/geis_dbus_dispatcher.c (+486/-0)
libs/geis-dbus/geis_dbus_dispatcher.h (+116/-0)
libs/geis-dbus/geis_dbus_gesture_event.c (+516/-0)
libs/geis-dbus/geis_dbus_gesture_event.h (+55/-0)
libs/geis-dbus/geis_dbus_region.c (+91/-0)
libs/geis-dbus/geis_dbus_region.h (+47/-0)
libs/geis-dbus/geis_dbus_subscription.c (+506/-0)
libs/geis-dbus/geis_dbus_subscription.h (+206/-0)
libutouch-geis/Makefile.am (+5/-0)
libutouch-geis/backend/Makefile.am (+1/-1)
libutouch-geis/backend/dbus/Makefile.am (+34/-0)
libutouch-geis/backend/dbus/geis_dbus_backend.c (+248/-0)
libutouch-geis/backend/dbus/geis_dbus_client.c (+685/-0)
libutouch-geis/backend/dbus/geis_dbus_client.h (+97/-0)
libutouch-geis/backend/dbus/geis_dbus_locator.c (+268/-0)
libutouch-geis/backend/dbus/geis_dbus_locator.h (+62/-0)
libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c (+7/-5)
libutouch-geis/backend/xcb/geis_xcb_backend.c (+10/-8)
libutouch-geis/backend/xcb/geis_xcb_backend_token.c (+4/-4)
libutouch-geis/backend/xcb/grail_gestures.c (+1/-1)
libutouch-geis/geis.c (+166/-158)
libutouch-geis/geis_attr.c (+143/-0)
libutouch-geis/geis_attr.h (+16/-0)
libutouch-geis/geis_backend.c (+2/-0)
libutouch-geis/geis_backend_multiplexor.c (+183/-74)
libutouch-geis/geis_backend_multiplexor.h (+51/-15)
libutouch-geis/geis_backend_protected.h (+2/-2)
libutouch-geis/geis_backend_token.c (+6/-4)
libutouch-geis/geis_backend_token.h (+32/-9)
libutouch-geis/geis_class.c (+2/-2)
libutouch-geis/geis_class.h (+1/-1)
libutouch-geis/geis_device.h (+1/-1)
libutouch-geis/geis_filter.c (+83/-0)
libutouch-geis/geis_filter.h (+51/-0)
libutouch-geis/geis_filter_term.c (+120/-0)
libutouch-geis/geis_filter_term.h (+8/-0)
libutouch-geis/geis_filterable.c (+151/-0)
libutouch-geis/geis_filterable.h (+116/-0)
libutouch-geis/geis_gesture_flick.c (+1/-1)
libutouch-geis/geis_private.h (+65/-59)
libutouch-geis/geis_subscription.c (+73/-10)
libutouch-geis/geis_subscription.h (+53/-0)
libutouch-geis/geis_timer.c (+5/-4)
libutouch-geis/geis_v1.c (+104/-45)
libutouch-geis/server/Makefile.am (+5/-2)
libutouch-geis/server/geis_dbus_announcer.c (+233/-0)
libutouch-geis/server/geis_dbus_announcer.h (+54/-0)
libutouch-geis/server/geis_dbus_client_proxy.c (+486/-0)
libutouch-geis/server/geis_dbus_client_proxy.h (+60/-0)
libutouch-geis/server/geis_dbus_proxy_box.c (+199/-0)
libutouch-geis/server/geis_dbus_proxy_box.h (+115/-0)
libutouch-geis/server/geis_dbus_server.c (+278/-154)
libutouch-geis/server/geis_dbus_server.h (+70/-30)
python/_geis_bindings/_geis_bindings.c (+3/-2)
python/geis/__init__.py (+6/-4)
testsuite/geis2/check_class.c (+1/-1)
testsuite/geis2/check_config.c (+1/-1)
testsuite/geis2/check_device.c (+1/-1)
testsuite/geis2/check_filter.c (+1/-1)
testsuite/geis2/check_frame.c (+1/-1)
testsuite/geis2/check_geis_new.c (+1/-1)
testsuite/geis2/check_region.c (+1/-1)
testsuite/geis2/check_subscription.c (+1/-1)
testsuite/libutouch-geis/Makefile.am (+1/-0)
testsuite/libutouch-geis/check_backend_multiplexor.c (+6/-2)
testsuite/libutouch-geis/check_backend_token.c (+1/-1)
testsuite/libutouch-geis/check_filter.c (+1/-1)
testsuite/libutouch-geis/check_geis_private.c (+4/-3)
testsuite/libutouch-geis/check_region.c (+1/-1)
testsuite/libutouch-geis/check_subscription.c (+1/-1)
testsuite/libutouch-geis/check_timer.c (+1/-1)
tools/Makefile.am (+1/-1)
tools/geis-server/Makefile.am (+33/-0)
tools/geis-server/geis-server.c (+85/-0)
tools/geisview/geisview (+39/-13)
To merge this branch: bzr merge lp:geis/client-arch
Reviewer Review Type Date Requested Status
Chase Douglas (community) Needs Information
Review via email: mp+79329@code.launchpad.net

This proposal has been superseded by a proposal from 2011-10-17.

Description of the change

Adds selectable client-server architecture using a private DBus.

I think at this point (most) functionality is there. May need some polish over the next cycle.

To post a comment you must log in.
Revision history for this message
Stephen M. Webb (bregma) wrote :

Added a trunk synch to resolve some merge conflicts.

lp:geis/client-arch updated
196. By Stephen M. Webb

Synched to lp:utouch-geis.

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

A ton of code that looks very clean. I really like the changes from an aesthetic point of view. It's obvious that you put a lot of thought into how things should be structured!

Here's what I'm looking for in reviewing this code:

1. Are there any "black box" changes?
2. Does the code look clean? Does it appear to do what is stated in the merge request?
3. Does it work?
4. Are there any issues highlighted by the merge proposal description?

Note that I'm not doing a line by line review. There's too much code to review for that level of detail, and you're a trusted member of the development team.

For item 1, there are no changes in include/. Since there are no api changes, and it's assumed there are no abi changes, this criteria is fulfilled.

For item 2, the code is definitely clean. It does appear to do what is stated in the merge request in whole.

However, I don't see any change in the default backend choice, and I don't see any change in geisview that would cause it to use the new client-server backend. Am I missing something, or was this lost in a merge or rebase? I would prefer to see the default backend change to the client-server backend with a fallback to the xcb backend.

The geis server is under tools/. Is this implementation merely an example, or is it the defacto server that should be used? If it's the latter, I would prefer to move it to the top level. I feel putting it in tools/ gives the wrong impression that it is not an essential part of the project.

For item 3, I'm not ready to give an answer yet since I don't know that geisview is using the new architecture. (On IRC, Stephen explained how to test: tools/geis-server/geis-server and then tools/geisview/geisview).

For item 4, I would like to know what is left out by the statement in the merge proposal: "I think at this point (most) functionality is there." Please detail which functionality is missing?

Overall, I'm extremely happy with the changes, assuming the testing shows it works :). I look forward to merging the branch once these issues are resolved!

review: Needs Information
Revision history for this message
Stephen M. Webb (bregma) wrote :

On 10/13/2011 04:53 PM, Chase Douglas wrote:
> For item 1, there are no changes in include/. Since there are no api changes, and it's assumed there are no abi changes, this criteria is fulfilled.

There is a backwards-compatible API change in include/geis/geis.h with
the addition of the GEIS_INIT_UTOUCH_DBUS_BACKEND defined constant.

> For item 2, the code is definitely clean. It does appear to do what is stated in the merge request in whole.
>
> However, I don't see any change in the default backend choice, and I don't see any change in geisview that would cause it to use the new client-server backend. Am I missing something, or was this lost in a merge or rebase? I would prefer to see the default backend change to the client-server backend with a fallback to the xcb backend.

This was apparently clobbered by a last-minute merge from trunk with
manual conflict resolution. I will re-add the back end selection to the
geisview tool and make it command-line configurable, and resubmit.

Changing the default back end to the dbus-client is a little premature
until a proper daemon is set up complete with launch scripts (dbus
service?). This should wait until after the round of plugin
refactoring. Changing the default back-end is a one-line change.

> The geis server is under tools/. Is this implementation merely an example, or is it the defacto server that should be used? If it's the latter, I would prefer to move it to the top level. I feel putting it in tools/ gives the wrong impression that it is not an essential part of the project.

The program under tools is a test driver tool. Writing a proper daemon
application with attendant start and stop scripts, logging, and control
options should be a separate task not a part of the internal library
changes designed to enable that task.

All of the changes made under this merge request were made under the
original assumption that the geis server would run as a compiz plugin.
None of them are incompatible with running a standalone server and
neither do they require it.

We should consider making a "utouchd" daemon a separate project from the
utouch-geis library.

> For item 3, I'm not ready to give an answer yet since I don't know that geisview is using the new architecture. (On IRC, Stephen explained how to test: tools/geis-server/geis-server and then tools/geisview/geisview).

I will provide better instructions with the above-mentioned changes to
geisview.

> For item 4, I would like to know what is left out by the statement in the merge proposal: "I think at this point (most) functionality is there." Please detail which functionality is missing?

Yes, quite. The only known functional deficit is proper reconnection
from the client when the server has disconnected and then reconnected
again. After verbal discussions we decided to defer this functionality
to later in the interest of getting the client-server merge completed.

Revision history for this message
Chase Douglas (chasedouglas) wrote :
Download full text (3.5 KiB)

> On 10/13/2011 04:53 PM, Chase Douglas wrote:
> > For item 1, there are no changes in include/. Since there are no api
> changes, and it's assumed there are no abi changes, this criteria is
> fulfilled.
>
> There is a backwards-compatible API change in include/geis/geis.h with
> the addition of the GEIS_INIT_UTOUCH_DBUS_BACKEND defined constant.

Argh... I see now that although the unmerged revisions list below starts at commit 187, the client-arch commits really start at commit 159. I will need to re-review to include those commits as well.

> > For item 2, the code is definitely clean. It does appear to do what is
> stated in the merge request in whole.
> >
> > However, I don't see any change in the default backend choice, and I don't
> see any change in geisview that would cause it to use the new client-server
> backend. Am I missing something, or was this lost in a merge or rebase? I
> would prefer to see the default backend change to the client-server backend
> with a fallback to the xcb backend.
>
> This was apparently clobbered by a last-minute merge from trunk with
> manual conflict resolution. I will re-add the back end selection to the
> geisview tool and make it command-line configurable, and resubmit.
>
> Changing the default back end to the dbus-client is a little premature
> until a proper daemon is set up complete with launch scripts (dbus
> service?). This should wait until after the round of plugin
> refactoring. Changing the default back-end is a one-line change.

I'm not sure it's premature. The client-arch won't be used unless you have a server running, in which case we can probably assume the user knows what they are doing. The main reason I would like to switch the default is so we can test current clients of geis without having to recompile them. And, it would be switchable merely by running or killing the geis server. I will probably run the tools/ server by default in my installs just so we have some good testing.

> > The geis server is under tools/. Is this implementation merely an example,
> or is it the defacto server that should be used? If it's the latter, I would
> prefer to move it to the top level. I feel putting it in tools/ gives the
> wrong impression that it is not an essential part of the project.
>
> The program under tools is a test driver tool. Writing a proper daemon
> application with attendant start and stop scripts, logging, and control
> options should be a separate task not a part of the internal library
> changes designed to enable that task.
>
> All of the changes made under this merge request were made under the
> original assumption that the geis server would run as a compiz plugin.
> None of them are incompatible with running a standalone server and
> neither do they require it.
>
> We should consider making a "utouchd" daemon a separate project from the
> utouch-geis library.

Ok, that sounds reasonable.

> > For item 4, I would like to know what is left out by the statement in the
> merge proposal: "I think at this point (most) functionality is there." Please
> detail which functionality is missing?
>
> Yes, quite. The only known functional deficit is proper reconnection
> fr...

Read more...

Revision history for this message
Stephen M. Webb (bregma) wrote :

On 10/13/2011 09:03 PM, Chase Douglas wrote:
>
> Argh... I see now that although the unmerged revisions list below starts at commit 187, the client-arch commits really start at commit 159. I will need to re-review to include those commits as well.

Yeah, it was a big set of changes with a number of synchs with trunk
along the way.

> I'm not sure it's premature. The client-arch won't be used unless you have a server running, in which case we can probably assume the user knows what they are doing. The main reason I would like to switch the default is so we can test current clients of geis without having to recompile them. And, it would be switchable merely by running or killing the geis server. I will probably run the tools/ server by default in my installs just so we have some good testing.

So you're suggesting autodiscovery with fallback. OK, I can do that.
Would like that as part of this merge or should we open a bug to track
that work?

Note that clients would not need any kind of recompile regardless.

>> The only known functional deficit is proper reconnection
>> from the client when the server has disconnected and then reconnected
>> again. After verbal discussions we decided to defer this functionality
>> to later in the interest of getting the client-server merge completed.
>
> Ok, that's reasonable for now. If we merge the branch like this, we should open a bug to track this missing functionality.

Absolutely.

lp:geis/client-arch updated
197. By Stephen M. Webb

Added a command-line switch to select a back end in geisview.

198. By Stephen M. Webb

Added back-end autodiscovery and failover.

The default back end is now DBus, with a fallback to XCB if the DBus server is not detected.

199. By Stephen M. Webb

Added full support for filtering by gesture class name with DBus server back end.

200. By Stephen M. Webb

Fixed a couple of invalid deallocations on exit.

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 2011-04-18 13:48:35 +0000
3+++ .bzrignore 2011-10-17 21:56:23 +0000
4@@ -6,13 +6,13 @@
5 **/xcb_gesture.[ch]
6 *.deps
7 *.libs
8+*.log
9 *Makefile.in
10 aclocal.m4
11 autom4te.cache
12 config.*
13 configure
14 debian/*.debhelper
15-debian/*.log
16 debian/*.substvars
17 debian/files
18 debian/libutouch-geis-dev
19@@ -28,8 +28,13 @@
20 examples/geis2
21 geis_config.*
22 libtool
23+libtool.m4
24 libutouch-geis.pc
25+ltoptions.m4
26+ltversion.m4
27+lt~obsolete.m4
28 stamp-*
29+TAGS
30 testsuite/geis1/*.log
31 testsuite/geis1/check_geis1_api
32 testsuite/geis2/*.log
33@@ -38,3 +43,4 @@
34 testsuite/libutouch-geis/*.log
35 testsuite/libutouch-geis/*.xml
36 testsuite/libutouch-geis/check_geis2_internals
37+tools/geis-server/geis-server
38
39=== modified file 'Makefile.am'
40--- Makefile.am 2011-04-18 13:47:57 +0000
41+++ Makefile.am 2011-10-17 21:56:23 +0000
42@@ -20,6 +20,7 @@
43
44
45 ACLOCAL_MFLAGS = -I m4
46+AM_MAKEFLAGS = --no-print-directory
47
48 SUBDIRS = include libs libutouch-geis testsuite python tools examples doc
49
50
51=== modified file 'configure.ac'
52--- configure.ac 2011-08-31 19:53:52 +0000
53+++ configure.ac 2011-10-17 21:56:23 +0000
54@@ -95,12 +95,14 @@
55 doc/Makefile
56 include/Makefile
57 libs/Makefile
58+ libs/geis-dbus/Makefile
59 libs/xcb/Makefile
60 libs/xcb/xcb_gesture.xml
61 libutouch-geis/Makefile
62 libutouch-geis/backend/Makefile
63 libutouch-geis/backend/test_fixture/Makefile
64 libutouch-geis/backend/xcb/Makefile
65+ libutouch-geis/backend/dbus/Makefile
66 libutouch-geis/server/Makefile
67 testsuite/Makefile
68 testsuite/libutouch-geis/Makefile
69@@ -110,5 +112,6 @@
70 examples/Makefile
71 python/Makefile
72 tools/Makefile
73- tools/geisview/Makefile])
74+ tools/geisview/Makefile
75+ tools/geis-server/Makefile])
76 AC_OUTPUT
77
78=== modified file 'include/geis/geis.h'
79--- include/geis/geis.h 2011-08-17 04:26:54 +0000
80+++ include/geis/geis.h 2011-10-17 21:56:23 +0000
81@@ -459,18 +459,21 @@
82 * @name Vendor-defined Initialization Arguments
83 *
84 * @par
85- * These initialization arguments are not a part of te GEIS specification and
86+ * These initialization arguments are not a part of the GEIS specification and
87 * may change.
88 *
89 * @{
90 *
91- * @def GEIS_INIT_UTOUCH_MOCK_ENGINE
92- *
93- * @def GEIS_INIT_UTOUCH_XCB
94+ * @def GEIS_INIT_UTOUCH_MOCK_BACKEND
95+ *
96+ * @def GEIS_INIT_UTOUCH_DBUS_BACKEND
97+ *
98+ * @def GEIS_INIT_UTOUCH_XCB_BACKEND
99 */
100
101-#define GEIS_INIT_UTOUCH_MOCK_ENGINE "com.canonical.utouch.mock.engine"
102-#define GEIS_INIT_UTOUCH_XCB "com.canonical.utouch.xcb"
103+#define GEIS_INIT_UTOUCH_MOCK_BACKEND "com.canonical.utouch.backend.mock"
104+#define GEIS_INIT_UTOUCH_DBUS_BACKEND "com.canonical.utouch.backend.dbus"
105+#define GEIS_INIT_UTOUCH_XCB_BACKEND "com.canonical.utouch.backend.xcb"
106
107 /* @} */
108
109@@ -1302,7 +1305,7 @@
110 *
111 * @param[in] gesture_class The gesture class object.
112 *
113- * The reference count of teh object is decremented and, if it reaches zero, the
114+ * The reference count of the object is decremented and, if it reaches zero, the
115 * object is destroyed.
116 */
117 GEIS_API void geis_gesture_class_unref(GeisGestureClass gesture_class);
118@@ -1332,7 +1335,7 @@
119 GEIS_API GeisSize geis_gesture_class_attr_count(GeisGestureClass gesture_class);
120
121 /**
122- * Gets the indicated attribute of teh gesture class.
123+ * Gets the indicated attribute of the gesture class.
124 * @memberof GeisGestureClass
125 *
126 * @param[in] gesture_class The gesture class object.
127
128=== modified file 'libs/Makefile.am'
129--- libs/Makefile.am 2011-01-17 15:03:18 +0000
130+++ libs/Makefile.am 2011-10-17 21:56:23 +0000
131@@ -19,5 +19,5 @@
132 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
133 #
134
135-SUBDIRS = xcb
136+SUBDIRS = xcb geis-dbus
137
138
139=== added directory 'libs/geis-dbus'
140=== added file 'libs/geis-dbus/Makefile.am'
141--- libs/geis-dbus/Makefile.am 1970-01-01 00:00:00 +0000
142+++ libs/geis-dbus/Makefile.am 2011-10-17 21:56:23 +0000
143@@ -0,0 +1,41 @@
144+#
145+# @file libs/geis-dbus/Makefile.am
146+# @brief automake recipe for the uTouch GEIS v2.0 DBus helper library
147+#
148+# Copyright 2011 Canonical, Ltd.
149+#
150+# This file is part of the utouch-geis library. This library is free software;
151+# you can redistribute it and/or modify it under the terms of the GNU Lesser
152+# General Public License as published by the Free Software Foundation; either
153+# version 3 of the License, or (at your option) any later version.
154+#
155+# This library is distributed in the hope that it will be useful, but WITHOUT
156+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
157+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
158+# details.
159+#
160+# You should have received a copy of the GNU Lesser General Public License
161+# along with this program; if not, write to the Free Software Foundation, Inc.,
162+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
163+#
164+
165+noinst_LTLIBRARIES = libgeis-dbus.la
166+
167+dist_libgeis_dbus_la_SOURCES = \
168+ geis_dbus.h \
169+ geis_dbus_attr.h geis_dbus_attr.c \
170+ geis_dbus_class.h geis_dbus_class.c \
171+ geis_dbus_device.h geis_dbus_device.c \
172+ geis_dbus_dispatcher.h geis_dbus_dispatcher.c \
173+ geis_dbus_gesture_event.h geis_dbus_gesture_event.c \
174+ geis_dbus_region.h geis_dbus_region.c \
175+ geis_dbus_subscription.h geis_dbus_subscription.c
176+
177+libgeis_dbus_la_CPPFLAGS = \
178+ -I$(top_srcdir)/libutouch-geis \
179+ $(DBUS_CFLAGS)
180+
181+libgeis_dbus_la_LIBADD = \
182+ $(DBUS_LIBS)
183+
184+
185
186=== renamed file 'libutouch-geis/server/geis_dbus.h' => 'libs/geis-dbus/geis_dbus.h'
187--- libutouch-geis/server/geis_dbus.h 2011-01-31 12:25:35 +0000
188+++ libs/geis-dbus/geis_dbus.h 2011-10-17 21:56:23 +0000
189@@ -1,4 +1,9 @@
190 /**
191+ * @file geis_dbus.h
192+ * @brief Common definitions for the GEIS DBus module(s).
193+ */
194+
195+/*
196 * Copyright 2011 Canonical Ltd.
197 *
198 * This library is free software; you can redistribute it and/or modify it under
199@@ -11,12 +16,36 @@
200 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
201 * details.
202 *
203- * You should have received a copy of the GNU Lesser General Public License
204- * along with this program; if not, write to the Free Software Foundation, Inc.,
205- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
206+ * You should have received a copy of the GNU General Public License
207+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
208 */
209-
210-
211-#define GEIS_DBUS_BUS_NAME "com.canonical.utouch"
212-#define GEIS_REMOTE_FUNCTION "getAddress"
213-
214+#ifndef GEIS_DBUS_H_
215+#define GEIS_DBUS_H_
216+
217+#define GEIS_DBUS_SERVICE_PATH "/com/canonical/utouch/Geis"
218+#define GEIS_DBUS_SERVICE_INTERFACE "com.canonical.utouch.Geis"
219+
220+#define GEIS_DBUS_GET_SERVER_ADDRESS "GetServerAddress"
221+
222+#define GEIS_DBUS_INIT_COMPLETE "InitComplete"
223+
224+#define GEIS_DBUS_DEVICE_AVAILABLE "DeviceAvailable"
225+#define GEIS_DBUS_DEVICE_UNAVAILABLE "DeviceUnavailable"
226+
227+#define GEIS_DBUS_CLASS_AVAILABLE "ClassAvailable"
228+#define GEIS_DBUS_CLASS_UNAVAILABLE "ClassUnavailable"
229+
230+#define GEIS_DBUS_REGION_AVAILABLE "RegionAvailable"
231+#define GEIS_DBUS_REGION_UNAVAILABLE "RegionUnavailable"
232+
233+#define GEIS_DBUS_SUBSCRIPTION_CREATE "SubscriptionCreate"
234+#define GEIS_DBUS_SUBSCRIPTION_ACTIVATE "SubscriptionActivate"
235+#define GEIS_DBUS_SUBSCRIPTION_DEACTIVATE "SubscriptionDeactivate"
236+#define GEIS_DBUS_SUBSCRIPTION_DESTROY "SubscriptionDestroy"
237+
238+#define GEIS_DBUS_GESTURE_EVENT "GestureEvent"
239+
240+#define GEIS_DBUS_ERROR_SUBSCRIPTION_FAIL GEIS_DBUS_SERVICE_INTERFACE \
241+ ".SubscriptionFail"
242+
243+#endif /* GEIS_DBUS_H_ */
244
245=== added file 'libs/geis-dbus/geis_dbus_attr.c'
246--- libs/geis-dbus/geis_dbus_attr.c 1970-01-01 00:00:00 +0000
247+++ libs/geis-dbus/geis_dbus_attr.c 2011-10-17 21:56:23 +0000
248@@ -0,0 +1,178 @@
249+/**
250+ * @file geis_dbus_attr.c
251+ * @brief Implementation of the GEIS DBus attr transport.
252+ */
253+
254+/*
255+ * Copyright 2011 Canonical Ltd.
256+ *
257+ * This library is free software; you can redistribute it and/or modify it under
258+ * the terms of the GNU Lesser General Public License as published by the Free
259+ * Software Foundation; either version 3 of the License, or (at your option) any
260+ * later version.
261+ *
262+ * This library is distributed in the hope that it will be useful, but WITHOUT
263+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
264+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
265+ * details.
266+ *
267+ * You should have received a copy of the GNU General Public License
268+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
269+ */
270+#include "geis_config.h"
271+#include "geis_dbus_attr.h"
272+
273+#include "geis_attr.h"
274+#include "geis_logging.h"
275+
276+
277+/*
278+ * Marshalls a single GEIS attr to an open DBus message container iterator.
279+ */
280+void
281+geis_dbus_attr_marshall(GeisAttr attr, DBusMessageIter *iter)
282+{
283+ DBusMessageIter dict_iter;
284+ GeisString attr_name = geis_attr_name(attr);
285+
286+ dbus_message_iter_open_container(iter,
287+ DBUS_TYPE_STRUCT,
288+ NULL,
289+ &dict_iter);
290+ dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_STRING, &attr_name);
291+ switch (geis_attr_type(attr))
292+ {
293+ case GEIS_ATTR_TYPE_BOOLEAN:
294+ {
295+ DBusMessageIter variant_iter;
296+ dbus_bool_t val = geis_attr_value_to_boolean(attr);
297+ dbus_message_iter_open_container(&dict_iter,
298+ DBUS_TYPE_VARIANT,
299+ DBUS_TYPE_BOOLEAN_AS_STRING,
300+ &variant_iter);
301+ dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_BOOLEAN, &val);
302+ dbus_message_iter_close_container(&dict_iter, &variant_iter);
303+ break;
304+ }
305+
306+ case GEIS_ATTR_TYPE_FLOAT:
307+ {
308+ DBusMessageIter variant_iter;
309+ double val = geis_attr_value_to_float(attr);
310+ dbus_message_iter_open_container(&dict_iter,
311+ DBUS_TYPE_VARIANT,
312+ DBUS_TYPE_DOUBLE_AS_STRING,
313+ &variant_iter);
314+ dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_DOUBLE, &val);
315+ dbus_message_iter_close_container(&dict_iter, &variant_iter);
316+ break;
317+ }
318+
319+ case GEIS_ATTR_TYPE_INTEGER:
320+ {
321+ DBusMessageIter variant_iter;
322+ dbus_int32_t val = geis_attr_value_to_integer(attr);
323+ dbus_message_iter_open_container(&dict_iter,
324+ DBUS_TYPE_VARIANT,
325+ DBUS_TYPE_INT32_AS_STRING,
326+ &variant_iter);
327+ dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_INT32, &val);
328+ dbus_message_iter_close_container(&dict_iter, &variant_iter);
329+ break;
330+ }
331+
332+ case GEIS_ATTR_TYPE_STRING:
333+ {
334+ DBusMessageIter variant_iter;
335+ GeisString val = geis_attr_value_to_string(attr);
336+ dbus_message_iter_open_container(&dict_iter,
337+ DBUS_TYPE_VARIANT,
338+ DBUS_TYPE_STRING_AS_STRING,
339+ &variant_iter);
340+ dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &val);
341+ dbus_message_iter_close_container(&dict_iter, &variant_iter);
342+ break;
343+ }
344+
345+ default:
346+ geis_error("invalid attribute type for DBus");
347+ }
348+ dbus_message_iter_close_container(iter, &dict_iter);
349+}
350+
351+
352+/*
353+ * Unmarshalls a single GEIS attr from a DBus message iterator.
354+ */
355+GeisAttr
356+geis_dbus_attr_unmarshall(DBusMessageIter *iter)
357+{
358+ GeisAttr attr = NULL;
359+ DBusMessageIter dict_iter;
360+
361+ dbus_message_iter_recurse(iter, &dict_iter);
362+ int dtype = dbus_message_iter_get_arg_type(&dict_iter);
363+ if (dtype != DBUS_TYPE_STRING)
364+ {
365+ geis_error("error getting attr name from DBus message");
366+ goto final_exit;
367+ }
368+
369+ char *attr_name;
370+ dbus_message_iter_get_basic(&dict_iter, &attr_name);
371+
372+ dbus_message_iter_next(&dict_iter);
373+ dtype = dbus_message_iter_get_arg_type(&dict_iter);
374+ if (dtype != DBUS_TYPE_VARIANT)
375+ {
376+ geis_error("error getting attr variant from DBus message");
377+ goto final_exit;
378+ }
379+
380+ DBusMessageIter variant_iter;
381+ dbus_message_iter_recurse(&dict_iter, &variant_iter);
382+ int vtype = dbus_message_iter_get_arg_type(&variant_iter);
383+ switch (vtype)
384+ {
385+ case DBUS_TYPE_BOOLEAN:
386+ {
387+ dbus_bool_t val;
388+ dbus_message_iter_get_basic(&variant_iter, &val);
389+ attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_BOOLEAN, &val);
390+ break;
391+ }
392+
393+ case DBUS_TYPE_DOUBLE:
394+ {
395+ double dval;
396+ dbus_message_iter_get_basic(&variant_iter, &dval);
397+ float fval = dval;
398+ attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_FLOAT, &fval);
399+ break;
400+ }
401+
402+ case DBUS_TYPE_INT32:
403+ {
404+ dbus_int32_t val;
405+ dbus_message_iter_get_basic(&variant_iter, &val);
406+ attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_INTEGER, &val);
407+ break;
408+ }
409+
410+ case DBUS_TYPE_STRING:
411+ {
412+ GeisString val;
413+ dbus_message_iter_get_basic(&variant_iter, &val);
414+ attr = geis_attr_new(attr_name, GEIS_ATTR_TYPE_STRING, (void *)val);
415+ break;
416+ }
417+
418+ default:
419+ geis_error("unexpected attr data type from DBus");
420+ break;
421+ }
422+
423+final_exit:
424+ return attr;
425+}
426+
427
428=== added file 'libs/geis-dbus/geis_dbus_attr.h'
429--- libs/geis-dbus/geis_dbus_attr.h 1970-01-01 00:00:00 +0000
430+++ libs/geis-dbus/geis_dbus_attr.h 2011-10-17 21:56:23 +0000
431@@ -0,0 +1,57 @@
432+/**
433+ * @file geis_dbus_attr.h
434+ * @brief Interface for the GEIS DBus attr transport.
435+ */
436+
437+/*
438+ * Copyright 2011 Canonical Ltd.
439+ *
440+ * This library is free software; you can redistribute it and/or modify it under
441+ * the terms of the GNU Lesser General Public License as published by the Free
442+ * Software Foundation; either version 3 of the License, or (at your option) any
443+ * later version.
444+ *
445+ * This library is distributed in the hope that it will be useful, but WITHOUT
446+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
447+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
448+ * details.
449+ *
450+ * You should have received a copy of the GNU General Public License
451+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
452+ */
453+#ifndef GEIS_DBUS_ATTR_H_
454+#define GEIS_DBUS_ATTR_H_
455+
456+#include <dbus/dbus.h>
457+#include "geis/geis.h"
458+
459+
460+/**
461+ * The DBus type signature for a GEIS attrlist entry.
462+ */
463+#define GEIS_DBUS_TYPE_SIGNATURE_ATTR \
464+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
465+ DBUS_TYPE_STRING_AS_STRING \
466+ DBUS_TYPE_VARIANT_AS_STRING \
467+ DBUS_STRUCT_END_CHAR_AS_STRING
468+
469+/**
470+ * Marshalls a single GEIS attr to an open DBus message container iterator.
471+ *
472+ * @param[in] attr The GEIS attr.
473+ * @param[in] iter The DBus message iterator.
474+ */
475+void
476+geis_dbus_attr_marshall(GeisAttr attr, DBusMessageIter *iter);
477+
478+/**
479+ * Unmarshalls a single GEIS attr from a DBus message iterator.
480+ *
481+ * @param[in] iter The DBus message iterator.
482+ *
483+ * @returns a GEIS attribute or NULL on error.
484+ */
485+GeisAttr
486+geis_dbus_attr_unmarshall(DBusMessageIter *iter);
487+
488+#endif /* GEIS_DBUS_ATTR_H_ */
489
490=== added file 'libs/geis-dbus/geis_dbus_class.c'
491--- libs/geis-dbus/geis_dbus_class.c 1970-01-01 00:00:00 +0000
492+++ libs/geis-dbus/geis_dbus_class.c 2011-10-17 21:56:23 +0000
493@@ -0,0 +1,126 @@
494+/**
495+ * @file geis_dbus_gesture_class.c
496+ * @brief Implementations of the GEIS DBus gesture_class transport.
497+ */
498+
499+/*
500+ * Copyright 2011 Canonical Ltd.
501+ *
502+ * This library is free software; you can redistribute it and/or modify it under
503+ * the terms of the GNU Lesser General Public License as published by the Free
504+ * Software Foundation; either version 3 of the License, or (at your option) any
505+ * later version.
506+ *
507+ * This library is distributed in the hope that it will be useful, but WITHOUT
508+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
509+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
510+ * details.
511+ *
512+ * You should have received a copy of the GNU Lesser General Public License
513+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
514+ */
515+#include "geis_config.h"
516+#include "geis_dbus_class.h"
517+
518+#include "geis_dbus.h"
519+#include "geis_dbus_attr.h"
520+#include "geis_class.h"
521+#include "geis_logging.h"
522+
523+
524+/*
525+ * Creates a Dbus "gesture_class available" message from a GEIS gesture_class.
526+ *
527+ * The Wire protocol for this message is class_id and class_name followed by
528+ * the list of class attributes.
529+ */
530+DBusMessage *
531+geis_dbus_class_available_message_from_class(GeisGestureClass gesture_class)
532+{
533+ DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH,
534+ GEIS_DBUS_SERVICE_INTERFACE,
535+ GEIS_DBUS_CLASS_AVAILABLE);
536+ DBusMessageIter iter;
537+ dbus_message_iter_init_append(message, &iter);
538+
539+ dbus_int32_t gesture_class_id = geis_gesture_class_id(gesture_class);
540+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &gesture_class_id);
541+
542+ const char *gesture_class_name = geis_gesture_class_name(gesture_class);
543+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &gesture_class_name);
544+
545+ DBusMessageIter array_iter;
546+ dbus_message_iter_open_container(&iter,
547+ DBUS_TYPE_ARRAY,
548+ GEIS_DBUS_TYPE_SIGNATURE_ATTR,
549+ &array_iter);
550+ GeisSize attr_count = geis_gesture_class_attr_count(gesture_class);
551+ for (GeisSize i = 0; i < attr_count; ++i)
552+ {
553+ geis_dbus_attr_marshall(geis_gesture_class_attr(gesture_class, i),
554+ &array_iter);
555+ }
556+ dbus_message_iter_close_container(&iter, &array_iter);
557+ return message;
558+}
559+
560+
561+/*
562+ * Creates GEIS gesture_class from a DBus "gesture_class available" message.
563+ */
564+GeisGestureClass
565+geis_dbus_class_class_from_available_message(DBusMessage *message)
566+{
567+ GeisGestureClass gesture_class = NULL;
568+ DBusMessageIter iter;
569+ dbus_message_iter_init(message, &iter);
570+
571+ int type = dbus_message_iter_get_arg_type(&iter);
572+ if (type != DBUS_TYPE_INT32)
573+ {
574+ geis_error("error getting gesture_class ID from DBus message.");
575+ goto final_exit;
576+ }
577+ dbus_int32_t gesture_class_id;
578+ dbus_message_iter_get_basic(&iter, &gesture_class_id);
579+
580+ dbus_message_iter_next(&iter);
581+ type = dbus_message_iter_get_arg_type(&iter);
582+ if (type != DBUS_TYPE_STRING)
583+ {
584+ geis_error("error getting gesture_class name from DBus message.");
585+ goto final_exit;
586+ }
587+
588+ char *gesture_class_name;
589+ dbus_message_iter_get_basic(&iter, &gesture_class_name);
590+ gesture_class = geis_gesture_class_new(gesture_class_name, gesture_class_id);
591+
592+ dbus_message_iter_next(&iter);
593+ type = dbus_message_iter_get_arg_type(&iter);
594+ if (type != DBUS_TYPE_ARRAY)
595+ {
596+ geis_error("error getting gesture_class attr list from DBus message.");
597+ goto final_exit;
598+ }
599+
600+ DBusMessageIter array_iter;
601+ dbus_message_iter_recurse(&iter, &array_iter);
602+ int atype = dbus_message_iter_get_arg_type(&array_iter);
603+ while (atype == DBUS_TYPE_DICT_ENTRY)
604+ {
605+ GeisAttr attr = geis_dbus_attr_unmarshall(&array_iter);
606+ if (attr)
607+ {
608+ geis_gesture_class_add_attr(gesture_class, attr);
609+ }
610+
611+ dbus_message_iter_next(&array_iter);
612+ atype = dbus_message_iter_get_arg_type(&array_iter);
613+ }
614+
615+final_exit:
616+ return gesture_class;
617+}
618+
619+
620
621=== added file 'libs/geis-dbus/geis_dbus_class.h'
622--- libs/geis-dbus/geis_dbus_class.h 1970-01-01 00:00:00 +0000
623+++ libs/geis-dbus/geis_dbus_class.h 2011-10-17 21:56:23 +0000
624@@ -0,0 +1,45 @@
625+/**
626+ * @file geis_dbus_class.h
627+ * @brief Interface for the GEIS DBus gesture class transport.
628+ */
629+
630+/*
631+ * Copyright 2011 Canonical Ltd.
632+ *
633+ * This library is free software; you can redistribute it and/or modify it under
634+ * the terms of the GNU Lesser General Public License as published by the Free
635+ * Software Foundation; either version 3 of the License, or (at your option) any
636+ * later version.
637+ *
638+ * This library is distributed in the hope that it will be useful, but WITHOUT
639+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
640+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
641+ * details.
642+ *
643+ * You should have received a copy of the GNU General Public License
644+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
645+ */
646+#ifndef GEIS_DBUS_GESTURE_CLASS_H_
647+#define GEIS_DBUS_GESTURE_CLASS_H_
648+
649+#include <dbus/dbus.h>
650+#include "geis/geis.h"
651+
652+
653+/**
654+ * Creates a Dbus "class available" message from a GEIS class.
655+ *
656+ * @param[in] class A GEIS gesture class.
657+ */
658+DBusMessage *
659+geis_dbus_class_available_message_from_class(GeisGestureClass gesture_class);
660+
661+/**
662+ * Creates GEIS class from a DBus "class available" message.
663+ *
664+ * @param[in] message A DBus message.
665+ */
666+GeisGestureClass
667+geis_dbus_class_class_from_available_message(DBusMessage *message);
668+
669+#endif /* GEIS_DBUS_GESTURE_CLASS_H_ */
670
671=== added file 'libs/geis-dbus/geis_dbus_device.c'
672--- libs/geis-dbus/geis_dbus_device.c 1970-01-01 00:00:00 +0000
673+++ libs/geis-dbus/geis_dbus_device.c 2011-10-17 21:56:23 +0000
674@@ -0,0 +1,152 @@
675+/**
676+ * @file geis_dbus_device.c
677+ * @brief Implementations of the GEIS DBus device transport.
678+ */
679+
680+/*
681+ * Copyright 2011 Canonical Ltd.
682+ *
683+ * This library is free software; you can redistribute it and/or modify it under
684+ * the terms of the GNU Lesser General Public License as published by the Free
685+ * Software Foundation; either version 3 of the License, or (at your option) any
686+ * later version.
687+ *
688+ * This library is distributed in the hope that it will be useful, but WITHOUT
689+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
690+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
691+ * details.
692+ *
693+ * You should have received a copy of the GNU Lesser General Public License
694+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
695+ */
696+#include "geis_config.h"
697+#include "geis_dbus_device.h"
698+
699+#include "geis_dbus.h"
700+#include "geis_dbus_attr.h"
701+#include "geis_device.h"
702+#include "geis_logging.h"
703+
704+
705+/*
706+ * Creates a Dbus "device available" message from a GEIS device.
707+ *
708+ * The Wire protocol for this message is device_id and device_name followed by
709+ * the list of device attributes.
710+ */
711+DBusMessage *
712+geis_dbus_device_available_message_from_device(GeisDevice device)
713+{
714+ DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH,
715+ GEIS_DBUS_SERVICE_INTERFACE,
716+ GEIS_DBUS_DEVICE_AVAILABLE);
717+ DBusMessageIter iter;
718+ dbus_message_iter_init_append(message, &iter);
719+
720+ dbus_int32_t device_id = geis_device_id(device);
721+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &device_id);
722+
723+ const char *device_name = geis_device_name(device);
724+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device_name);
725+
726+ DBusMessageIter array_iter;
727+ dbus_message_iter_open_container(&iter,
728+ DBUS_TYPE_ARRAY,
729+ GEIS_DBUS_TYPE_SIGNATURE_ATTR,
730+ &array_iter);
731+ GeisSize attr_count = geis_device_attr_count(device);
732+ for (GeisSize i = 0; i < attr_count; ++i)
733+ {
734+ geis_dbus_attr_marshall(geis_device_attr(device, i), &array_iter);
735+ }
736+ dbus_message_iter_close_container(&iter, &array_iter);
737+ return message;
738+}
739+
740+
741+/*
742+ * Creates GEIS device from a DBus "device available" message.
743+ */
744+GeisDevice
745+geis_dbus_device_device_from_available_message(DBusMessage *message)
746+{
747+ geis_debug("begins");
748+ GeisDevice device = NULL;
749+ DBusMessageIter iter;
750+ dbus_message_iter_init(message, &iter);
751+
752+ int type = dbus_message_iter_get_arg_type(&iter);
753+ if (type != DBUS_TYPE_INT32)
754+ {
755+ geis_error("error getting device ID from DBus message.");
756+ goto final_exit;
757+ }
758+ dbus_int32_t device_id;
759+ dbus_message_iter_get_basic(&iter, &device_id);
760+
761+ dbus_message_iter_next(&iter);
762+ type = dbus_message_iter_get_arg_type(&iter);
763+ if (type != DBUS_TYPE_STRING)
764+ {
765+ geis_error("error getting device name from DBus message.");
766+ goto final_exit;
767+ }
768+
769+ char *device_name;
770+ dbus_message_iter_get_basic(&iter, &device_name);
771+ device = geis_device_new(device_name, device_id);
772+
773+ dbus_message_iter_next(&iter);
774+ type = dbus_message_iter_get_arg_type(&iter);
775+ if (type != DBUS_TYPE_ARRAY)
776+ {
777+ geis_error("error getting device attr list from DBus message.");
778+ goto final_exit;
779+ }
780+
781+ DBusMessageIter array_iter;
782+ dbus_message_iter_recurse(&iter, &array_iter);
783+ int atype = dbus_message_iter_get_arg_type(&array_iter);
784+ while (atype == DBUS_TYPE_DICT_ENTRY)
785+ {
786+ GeisAttr attr = geis_dbus_attr_unmarshall(&array_iter);
787+ if (attr)
788+ {
789+ geis_device_add_attr(device, attr);
790+ }
791+
792+ dbus_message_iter_next(&array_iter);
793+ atype = dbus_message_iter_get_arg_type(&array_iter);
794+ }
795+
796+final_exit:
797+ geis_debug("ends");
798+ return device;
799+}
800+
801+
802+/*
803+ * Creates a Dbus "device unavailable" message from a GEIS device.
804+ */
805+DBusMessage *
806+geis_dbus_device_unavailable_message_from_device(GeisDevice device GEIS_UNUSED)
807+{
808+ geis_debug("begins");
809+ DBusMessage *message = NULL;
810+ geis_debug("ends");
811+ return message;
812+}
813+
814+
815+/*
816+ * Creates GEIS device from a DBus "device unavailable" message.
817+ */
818+GeisDevice
819+geis_dbus_device_device_from_unavailable_message(DBusMessage *message GEIS_UNUSED)
820+{
821+ geis_debug("begins");
822+ GeisDevice device = NULL;
823+ geis_debug("ends");
824+ return device;
825+}
826+
827
828=== added file 'libs/geis-dbus/geis_dbus_device.h'
829--- libs/geis-dbus/geis_dbus_device.h 1970-01-01 00:00:00 +0000
830+++ libs/geis-dbus/geis_dbus_device.h 2011-10-17 21:56:23 +0000
831@@ -0,0 +1,61 @@
832+/**
833+ * @file geis_dbus_device.h
834+ * @brief Interface for the GEIS DBus device transport.
835+ */
836+
837+/*
838+ * Copyright 2011 Canonical Ltd.
839+ *
840+ * This library is free software; you can redistribute it and/or modify it under
841+ * the terms of the GNU Lesser General Public License as published by the Free
842+ * Software Foundation; either version 3 of the License, or (at your option) any
843+ * later version.
844+ *
845+ * This library is distributed in the hope that it will be useful, but WITHOUT
846+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
847+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
848+ * details.
849+ *
850+ * You should have received a copy of the GNU General Public License
851+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
852+ */
853+#ifndef GEIS_DBUS_DEVICE_H_
854+#define GEIS_DBUS_DEVICE_H_
855+
856+#include <dbus/dbus.h>
857+#include "geis/geis.h"
858+
859+
860+/**
861+ * Creates a Dbus "device available" message from a GEIS device.
862+ *
863+ * @param[in] device A GEIS device.
864+ */
865+DBusMessage *
866+geis_dbus_device_available_message_from_device(GeisDevice device);
867+
868+/**
869+ * Creates GEIS device from a DBus "device available" message.
870+ *
871+ * @param[in] message A DBus message.
872+ */
873+GeisDevice
874+geis_dbus_device_device_from_available_message(DBusMessage *message);
875+
876+/**
877+ * Creates a Dbus "device unavailable" message from a GEIS device.
878+ *
879+ * @param[in] device A GEIS device.
880+ */
881+DBusMessage *
882+geis_dbus_device_unavailable_message_from_device(GeisDevice device);
883+
884+/**
885+ * Creates GEIS device from a DBus "device unavailable" message.
886+ *
887+ * @param[in] message A DBus message.
888+ */
889+GeisDevice
890+geis_dbus_device_device_from_unavailable_message(DBusMessage *message);
891+
892+#endif /* GEIS_DBUS_DEVICE_H_ */
893
894=== added file 'libs/geis-dbus/geis_dbus_dispatcher.c'
895--- libs/geis-dbus/geis_dbus_dispatcher.c 1970-01-01 00:00:00 +0000
896+++ libs/geis-dbus/geis_dbus_dispatcher.c 2011-10-17 21:56:23 +0000
897@@ -0,0 +1,486 @@
898+/**
899+ * @file geis_dbus_dispatcher.c
900+ * @brief Implementation of the GEIS DBus dispatcher.
901+ */
902+
903+/*
904+ * Copyright 2011 Canonical Ltd.
905+ *
906+ * This library is free software; you can redistribute it and/or modify it under
907+ * the terms of the GNU Lesser General Public License as published by the Free
908+ * Software Foundation; either version 3 of the License, or (at your option) any
909+ * later version.
910+ *
911+ * This library is distributed in the hope that it will be useful, but WITHOUT
912+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
913+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
914+ * details.
915+ *
916+ * You should have received a copy of the GNU General Public License
917+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
918+ */
919+#include "geis_config.h"
920+#include "geis_dbus_dispatcher.h"
921+
922+#include "geis_logging.h"
923+#include "geis_private.h"
924+#include <stdio.h>
925+#include <stdlib.h>
926+
927+
928+typedef struct GeisDBusWatch *GeisDBusWatch;
929+typedef struct GeisDBusWatchBag *GeisDBusWatchBag;
930+
931+/*
932+ * Connects a DBusWatch back to a DBusConnection.
933+ *
934+ * This is an intrusive linked list node. See GeisDBusWatchBag.
935+ */
936+struct GeisDBusWatch
937+{
938+ DBusConnection *connection;
939+ DBusWatch *watch;
940+ GeisDBusWatch next;
941+};
942+
943+
944+/*
945+ * Maps file descriptors to watches and connections.
946+ *
947+ * A DBusWatch is assciated with a single file descriptor, but each file
948+ * descriptor may be associated with more than one DBusWatch.
949+ *
950+ * Each DBusConnection has one or more DBusWatch. The DBusWatches are passed
951+ * around without reference to the connection itself, but we often need the
952+ * connection when all we have is the watch.
953+ *
954+ * To make things more complex, the DBusServer does not have a connection
955+ * associated with its watches.
956+ *
957+ * This is a linked list with a free pool.
958+ */
959+struct GeisDBusWatchBag
960+{
961+ GeisDBusWatch front;
962+ GeisDBusWatch back;
963+ GeisDBusWatch pool;
964+};
965+
966+static const int _geis_dbus_watch_bag_initial_size = 4;
967+
968+
969+struct GeisDBusDispatcher
970+{
971+ Geis geis;
972+ GeisDBusWatchBag watches;
973+};
974+
975+
976+/*
977+ * Creates a new empty collection of watches.
978+ *
979+ * The pool is primed with a few empty watches to save time later, on the
980+ * assumption that if you're creating a bag you're going to use it.
981+ */
982+static GeisDBusWatchBag
983+_geis_dbus_watch_bag_new()
984+{
985+ GeisDBusWatchBag bag = calloc(1, sizeof(struct GeisDBusWatchBag));
986+ if (!bag)
987+ {
988+ geis_error("error allocating GeisDBusWatchBag");
989+ goto final_exit;
990+ }
991+
992+ /* Prime the free pool. */
993+ for (int i = 0; i < _geis_dbus_watch_bag_initial_size; ++i)
994+ {
995+ GeisDBusWatch gdbw = calloc(1, sizeof(struct GeisDBusWatch));
996+ if (!gdbw)
997+ {
998+ geis_error("error allocating GeisDBusWatchBag");
999+ goto unwind_pool;
1000+ }
1001+ gdbw->next = bag->pool;
1002+ bag->pool = gdbw;
1003+ }
1004+ goto final_exit;
1005+
1006+unwind_pool:
1007+final_exit:
1008+ return bag;
1009+}
1010+
1011+
1012+/*
1013+ * Destroys a collection of watches.
1014+ *
1015+ * @param[in] bag A collection of %GeisDBusWatches.
1016+ *
1017+ * There should be no need to unref any of the contents of the bag, they can
1018+ * just be freed without consequence.
1019+ */
1020+static void
1021+_geis_dbus_watch_bag_delete(GeisDBusWatchBag bag)
1022+{
1023+ /* Free the pool. */
1024+ GeisDBusWatch gdbw = bag->pool;
1025+ while (gdbw)
1026+ {
1027+ GeisDBusWatch next = gdbw->next;
1028+ free(gdbw);
1029+ gdbw = next;
1030+ }
1031+
1032+ /* Free the in-use watches. */
1033+ gdbw = bag->front;
1034+ while (gdbw)
1035+ {
1036+ GeisDBusWatch next = gdbw->next;
1037+ free(gdbw);
1038+ gdbw = next;
1039+ }
1040+
1041+ free(bag);
1042+}
1043+
1044+
1045+/*
1046+ * Gets an allocated watch from the bag.
1047+ *
1048+ * @param[in] bag A collection of %GeisDBusWatches.
1049+ * @param[in] connection A DBusConnection.
1050+ * @param[in] watch A DBusWatch.
1051+ *
1052+ * A factory function to create a new watch in the collection and return a
1053+ * pointer to it.
1054+ */
1055+static GeisDBusWatch
1056+_geis_dbus_watch_bag_alloc_watch(GeisDBusWatchBag bag,
1057+ DBusConnection *connection,
1058+ DBusWatch *watch)
1059+{
1060+ GeisDBusWatch gdbw = NULL;
1061+
1062+ /* Either pull a free watch off the pool or allocate a new one. */
1063+ if (bag->pool)
1064+ {
1065+ gdbw = bag->pool;
1066+ bag->pool = bag->pool->next;
1067+ }
1068+ else
1069+ {
1070+ gdbw = calloc(1, sizeof(struct GeisDBusWatch));
1071+ if (!gdbw)
1072+ {
1073+ geis_error("error allocating GeisDBusWatchBag");
1074+ goto final_exit;
1075+ }
1076+ }
1077+
1078+ /* Fill in the data bits. */
1079+ gdbw->connection = connection;
1080+ gdbw->watch = watch;
1081+ gdbw->next = NULL;
1082+
1083+ /* Add it to the in-use list. */
1084+ if (!bag->front)
1085+ {
1086+ bag->front = gdbw;
1087+ }
1088+ if (bag->back)
1089+ {
1090+ bag->back->next = gdbw;
1091+ }
1092+ bag->back = gdbw;
1093+
1094+final_exit:
1095+ return gdbw;
1096+}
1097+
1098+
1099+/*
1100+ * Removes a watch from a collection of such beasts.
1101+ *
1102+ * @param[in] bag A collection of %GeisDBusWatches.
1103+ * @param[in] watch The watch to remove.
1104+ */
1105+static void
1106+_geis_dbus_watch_bag_remove_watch(GeisDBusWatchBag bag,
1107+ DBusWatch *watch)
1108+{
1109+ for (GeisDBusWatch gdbw = bag->front, prev = NULL; gdbw; gdbw = gdbw->next)
1110+ {
1111+ if (gdbw->watch == watch)
1112+ {
1113+ if (gdbw == bag->front)
1114+ {
1115+ bag->front = gdbw->next;
1116+ }
1117+ else
1118+ {
1119+ prev->next = gdbw->next;
1120+ }
1121+ if (gdbw == bag->back)
1122+ {
1123+ bag->back = prev;
1124+ }
1125+
1126+ gdbw->next = bag->pool;
1127+ bag->pool = gdbw;
1128+
1129+ break;
1130+ }
1131+ prev = gdbw;
1132+ }
1133+}
1134+
1135+
1136+/*
1137+ * Indicates if a file descriptor is already held in the watch bag.
1138+ *
1139+ * @param[in] bag A collection of %GeisDBusWatches.
1140+ * @param[in] fd A file descriptor.
1141+ * @param[out] flags The DBus watch flags for any enabled watches found.
1142+ *
1143+ * @returns zero if the file descriptor is not in the bag, non-zero otherwise.
1144+ */
1145+static int
1146+_geis_dbus_watch_bag_has_fd(GeisDBusWatchBag bag, int fd, unsigned int *flags)
1147+{
1148+ int has_fd = 0;
1149+ for (GeisDBusWatch gdbw = bag->front; gdbw; gdbw = gdbw->next)
1150+ {
1151+ if (dbus_watch_get_unix_fd(gdbw->watch) == fd)
1152+ {
1153+ has_fd |= ~0;
1154+ if (dbus_watch_get_enabled(gdbw->watch))
1155+ {
1156+ *flags |= dbus_watch_get_flags(gdbw->watch);
1157+ }
1158+ }
1159+ }
1160+ return has_fd;
1161+}
1162+
1163+
1164+/*
1165+ * Finds a DBusWatch in the bag that matches the fd and current activity.
1166+ *
1167+ * @param[in] bag A collection of %GeisDBusWatches.
1168+ * @param[in] fd The file descriptor on which an activity has been detected.
1169+ * @param[in] activity The bitmask of currently detected activity on the fd.
1170+ *
1171+ * A DBusWatch will match if it has the same file descriptor and is watching for
1172+ * (one of) the activity(ies) that has just occurred.
1173+ *
1174+ * Note that writers are implicitly looking for hangups or errors but the DBus
1175+ * library goes into an infinite loop when a hangup has occurred no a write
1176+ * watch, so defer that to a read watch.
1177+ *
1178+ * @returns a GeisDBusWatch or NULL if no matching watch was found.
1179+ */
1180+static GeisDBusWatch
1181+_geis_dbus_watch_bag_find_fd_activity(GeisDBusWatchBag bag,
1182+ int fd,
1183+ GeisBackendMultiplexorActivity activity)
1184+{
1185+ GeisDBusWatch gdbw = NULL;
1186+ for (gdbw = bag->front; gdbw; gdbw = gdbw->next)
1187+ {
1188+ if (dbus_watch_get_unix_fd(gdbw->watch) == fd)
1189+ {
1190+ unsigned int flags = dbus_watch_get_flags(gdbw->watch);
1191+ if ((activity & GEIS_BE_MX_READ_AVAILABLE && flags & DBUS_WATCH_READABLE)
1192+ || (activity & GEIS_BE_MX_WRITE_AVAILABLE && flags & DBUS_WATCH_WRITABLE)
1193+ || (activity & GEIS_BE_MX_HANGUP_DETECTED && flags & DBUS_WATCH_READABLE)
1194+ || (activity & GEIS_BE_MX_ERROR_DETECTED))
1195+ {
1196+ break;
1197+ }
1198+ }
1199+ }
1200+ return gdbw;
1201+}
1202+
1203+
1204+/*
1205+ * A callback function passed to the Geis multiplexor.
1206+ *
1207+ * @param[in] fd The file descriptor on which an activity has been detected.
1208+ * @param[in] activity The bitmask of currently detected activity on the fd.
1209+ * @param[in] context The %GeisDBusDispatcher passed through the multiplexor.
1210+ *
1211+ * This callback gets invoked whenever a requested activity is detected on a
1212+ * regostered DBusWatch file descriptor. It translates the GEIS Multiplexor
1213+ * activity to DBus activity.
1214+ */
1215+static void
1216+_geis_dbus_dispatcher_callback(int fd,
1217+ GeisBackendMultiplexorActivity activity,
1218+ void *context)
1219+{
1220+ GeisDBusDispatcher dispatcher = (GeisDBusDispatcher)context;
1221+ GeisDBusWatch gdb = _geis_dbus_watch_bag_find_fd_activity(dispatcher->watches,
1222+ fd,
1223+ activity);
1224+ if (gdb)
1225+ {
1226+ /* Translate GEIS multiplexor activity to DBus watch flags. */
1227+ unsigned int flags = 0;
1228+ if (activity & GEIS_BE_MX_READ_AVAILABLE) flags |= DBUS_WATCH_READABLE;
1229+ if (activity & GEIS_BE_MX_WRITE_AVAILABLE) flags |= DBUS_WATCH_WRITABLE;
1230+ if (activity & GEIS_BE_MX_HANGUP_DETECTED) flags |= DBUS_WATCH_HANGUP;
1231+ if (activity & GEIS_BE_MX_ERROR_DETECTED) flags |= DBUS_WATCH_ERROR;
1232+ dbus_watch_handle(gdb->watch, flags);
1233+
1234+ if (gdb->connection)
1235+ {
1236+ if (activity & GEIS_BE_MX_HANGUP_DETECTED)
1237+ {
1238+ dbus_connection_close(gdb->connection);
1239+ }
1240+ else
1241+ {
1242+ DBusDispatchStatus s;
1243+ s = dbus_connection_get_dispatch_status(gdb->connection);
1244+ while (DBUS_DISPATCH_DATA_REMAINS == s)
1245+ {
1246+ s = dbus_connection_dispatch(gdb->connection);
1247+ }
1248+ }
1249+ }
1250+ }
1251+}
1252+
1253+
1254+/*
1255+ * Creates a new GEIS DBus dispatcher.
1256+ */
1257+GeisDBusDispatcher
1258+geis_dbus_dispatcher_new(Geis geis)
1259+{
1260+ GeisDBusDispatcher dispatcher = calloc(1, sizeof(struct GeisDBusDispatcher));
1261+ if (!dispatcher)
1262+ {
1263+ geis_error("error allocating GEIS DBus dispatcher.");
1264+ goto final_exit;
1265+ }
1266+
1267+ dispatcher->geis = geis;
1268+ dispatcher->watches = _geis_dbus_watch_bag_new();
1269+ if (!dispatcher->watches)
1270+ {
1271+ geis_error("error creating GEIS DBus dispatcher watches.");
1272+ goto unwind_dispatcher;
1273+ }
1274+
1275+ goto final_exit;
1276+
1277+unwind_dispatcher:
1278+ free(dispatcher);
1279+final_exit:
1280+ return dispatcher;
1281+}
1282+
1283+
1284+/*
1285+ * Destroys an existing %GeisDBusDispatcher object.
1286+ */
1287+void
1288+geis_dbus_dispatcher_delete(GeisDBusDispatcher dispatcher)
1289+{
1290+ _geis_dbus_watch_bag_delete(dispatcher->watches);
1291+ free(dispatcher);
1292+ }
1293+
1294+
1295+/*
1296+ * Registers a new DBusWatch with a %GeisDBusDispatcher object.
1297+ */
1298+void
1299+geis_dbus_dispatcher_register(GeisDBusDispatcher dispatcher,
1300+ DBusConnection *connection,
1301+ DBusWatch *watch)
1302+{
1303+ int watch_fd = dbus_watch_get_unix_fd(watch);
1304+
1305+ /* Calculate all the enabled flags on the fd for all watches. */
1306+ unsigned int flags = 0;
1307+ int has_fd = _geis_dbus_watch_bag_has_fd(dispatcher->watches, watch_fd, &flags);
1308+ _geis_dbus_watch_bag_alloc_watch(dispatcher->watches, connection, watch);
1309+ if (dbus_watch_get_enabled(watch))
1310+ {
1311+ flags |= dbus_watch_get_flags(watch);
1312+ }
1313+
1314+ /* Convert the watch flags to multiplexor activities. */
1315+ GeisBackendMultiplexorActivity activity = 0;
1316+ if (flags & DBUS_WATCH_READABLE) activity |= GEIS_BE_MX_READ_AVAILABLE;
1317+ if (flags & DBUS_WATCH_WRITABLE) activity |= GEIS_BE_MX_WRITE_AVAILABLE;
1318+
1319+ /* Set or adjust the multiplexor seubscription. */
1320+ if (has_fd)
1321+ {
1322+ geis_remultiplex_fd(dispatcher->geis, watch_fd, activity);
1323+ }
1324+ else
1325+ {
1326+ geis_multiplex_fd(dispatcher->geis,
1327+ watch_fd,
1328+ activity,
1329+ _geis_dbus_dispatcher_callback,
1330+ dispatcher);
1331+ }
1332+}
1333+
1334+
1335+/*
1336+ * Unregisters a DBusWatch for events.
1337+ */
1338+void
1339+geis_dbus_dispatcher_unregister(GeisDBusDispatcher dispatcher,
1340+ DBusWatch *watch)
1341+{
1342+ int watch_fd = dbus_watch_get_unix_fd(watch);
1343+ unsigned int flags = 0;
1344+ _geis_dbus_watch_bag_remove_watch(dispatcher->watches, watch);
1345+ if (!_geis_dbus_watch_bag_has_fd(dispatcher->watches, watch_fd, &flags))
1346+ {
1347+ geis_demultiplex_fd(dispatcher->geis, watch_fd);
1348+ }
1349+}
1350+
1351+
1352+/*
1353+ * Marks a DBusWatch as active, maybe.
1354+ */
1355+void
1356+geis_dbus_dispatcher_toggle_watch(GeisDBusDispatcher dispatcher,
1357+ DBusWatch *watch)
1358+{
1359+ int watch_fd = dbus_watch_get_unix_fd(watch);
1360+
1361+ /* Calculate all the enabled flags on the fd for all watches. */
1362+ unsigned int flags = 0;
1363+ _geis_dbus_watch_bag_has_fd(dispatcher->watches, watch_fd, &flags);
1364+ if (dbus_watch_get_enabled(watch))
1365+ {
1366+ flags |= dbus_watch_get_flags(watch);
1367+ }
1368+ else
1369+ {
1370+ flags &= ~dbus_watch_get_flags(watch);
1371+ }
1372+
1373+ /* Convert the watch flags to multiplexor activities. */
1374+ GeisBackendMultiplexorActivity activity = 0;
1375+ if (flags & DBUS_WATCH_READABLE) activity |= GEIS_BE_MX_READ_AVAILABLE;
1376+ if (flags & DBUS_WATCH_WRITABLE) activity |= GEIS_BE_MX_WRITE_AVAILABLE;
1377+
1378+ /* Set or adjust the multiplexor seubscription. */
1379+ geis_remultiplex_fd(dispatcher->geis, watch_fd, activity);
1380+
1381+}
1382+
1383+
1384
1385=== added file 'libs/geis-dbus/geis_dbus_dispatcher.h'
1386--- libs/geis-dbus/geis_dbus_dispatcher.h 1970-01-01 00:00:00 +0000
1387+++ libs/geis-dbus/geis_dbus_dispatcher.h 2011-10-17 21:56:23 +0000
1388@@ -0,0 +1,116 @@
1389+/**
1390+ * @file geis_dbus_dispatcher.h
1391+ * @brief Interface for the GEIS DBus dispatcher.
1392+ *
1393+ * The GEIS DBus dispatcher provides a central dispatch point for all DBus
1394+ * events used internally by GEIS.
1395+ *
1396+ * This header is for internal GEIS use only and contains no client
1397+ * (externally-visible) symbols.
1398+ */
1399+
1400+/*
1401+ * Copyright 2011 Canonical Ltd.
1402+ *
1403+ * This library is free software; you can redistribute it and/or modify it under
1404+ * the terms of the GNU Lesser General Public License as published by the Free
1405+ * Software Foundation; either version 3 of the License, or (at your option) any
1406+ * later version.
1407+ *
1408+ * This library is distributed in the hope that it will be useful, but WITHOUT
1409+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1410+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1411+ * details.
1412+ *
1413+ * You should have received a copy of the GNU General Public License
1414+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1415+ */
1416+#ifndef GEIS_DBUS_DISPATCHER_H_
1417+#define GEIS_DBUS_DISPATCHER_H_
1418+
1419+#include <dbus/dbus.h>
1420+#include "geis/geis.h"
1421+
1422+
1423+/**
1424+ * The %GeisDBusDispatcher centralizes all dispatch for all DBus events used
1425+ * internally by the GEIS client-server mechanism.
1426+ *
1427+ * Geis implements single-threaded ansynchronous dispatch for DBus events, in
1428+ * case a single-threaded client is making use of GEIS. This also simplifies a
1429+ * lot of the internal design of the GEIS DBus service, since no locking or
1430+ * other forms of synchronization are required.
1431+ */
1432+typedef struct GeisDBusDispatcher *GeisDBusDispatcher;
1433+
1434+/**
1435+ * A callback type for the handler function dispatched on DBus events.
1436+ *
1437+ * @todo the parameters of the GeisDispatchCallback must be defined.
1438+ */
1439+typedef void (*GeisDispatchCallback)(void *context);
1440+
1441+
1442+/**
1443+ * Creates a new GEIS DBus dispatcher.
1444+ *
1445+ * @param[in] geis A GEIS instance.
1446+ *
1447+ * Creates a new %GeisDBusDispatcher and registers it with the GEIS API instance
1448+ * so it will be multiplexed and receive event notification.
1449+ *
1450+ * @returns a new %GeisDBusDispatcher object or NULL on failure.
1451+ */
1452+GeisDBusDispatcher
1453+geis_dbus_dispatcher_new(Geis geis);
1454+
1455+/**
1456+ * Destroys an existing %GeisDBusDispatcher object.
1457+ *
1458+ * @param[in] dispatcher A %GeisDBusDispatcher object.
1459+ */
1460+void
1461+geis_dbus_dispatcher_delete(GeisDBusDispatcher dispatcher);
1462+
1463+/**
1464+ * Registers a new DBusWatch with a %GeisDBusDispatcher object.
1465+ *
1466+ * @param[in] dispatcher A %GeisDBusDispatcher object.
1467+ * @param[in] connection A DBus connection.
1468+ * @param[in] watch A DBusWatch om the connection.
1469+ *
1470+ * The @p watch will be registered with the @p dispatcher for future DBus
1471+ * events. The @p watch may or may not be activated, depending on its @a
1472+ * enabled state at the time of registration.
1473+ */
1474+void
1475+geis_dbus_dispatcher_register(GeisDBusDispatcher dispatcher,
1476+ DBusConnection *connection,
1477+ DBusWatch *watch);
1478+
1479+/**
1480+ * Unregisters a DBusWatch for events.
1481+ *
1482+ * @param[in] dispatcher A %GeisDBusDispatcher object.
1483+ * @param[in] watch A DBusWatch.
1484+ */
1485+void
1486+geis_dbus_dispatcher_unregister(GeisDBusDispatcher dispatcher,
1487+ DBusWatch *watch);
1488+
1489+/**
1490+ * Marks a DBusWatch as active or not, depending on its state.
1491+ *
1492+ * @param[in] dispatcher A %GeisDBusDispatcher object.
1493+ * @param[in] watch A pointer to a DBusWatch object.
1494+ *
1495+ * The @p dispatcher will listen for events on the @p watch if its @a is_enabled
1496+ * state is true or not.
1497+ */
1498+void
1499+geis_dbus_dispatcher_toggle_watch(GeisDBusDispatcher dispatcher,
1500+ DBusWatch *watch);
1501+
1502+
1503+
1504+#endif /* GEIS_DBUS_DISPATCHER_H_ */
1505
1506=== added file 'libs/geis-dbus/geis_dbus_gesture_event.c'
1507--- libs/geis-dbus/geis_dbus_gesture_event.c 1970-01-01 00:00:00 +0000
1508+++ libs/geis-dbus/geis_dbus_gesture_event.c 2011-10-17 21:56:23 +0000
1509@@ -0,0 +1,516 @@
1510+/**
1511+ * @file geis_dbus_gesture_event.c
1512+ * @brief Implementation of the GEIS DBus gesture event transport.
1513+ */
1514+
1515+/*
1516+ * Copyright 2011 Canonical Ltd.
1517+ *
1518+ * This library is free software; you can redistribute it and/or modify it under
1519+ * the terms of the GNU Lesser General Public License as published by the Free
1520+ * Software Foundation; either version 3 of the License, or (at your option) any
1521+ * later version.
1522+ *
1523+ * This library is distributed in the hope that it will be useful, but WITHOUT
1524+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1525+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1526+ * details.
1527+ *
1528+ * You should have received a copy of the GNU General Public License
1529+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1530+ */
1531+#include "geis_config.h"
1532+#include "geis_dbus_gesture_event.h"
1533+
1534+#include "geis_attr.h"
1535+#include "geis_dbus.h"
1536+#include "geis_dbus_attr.h"
1537+#include "geis_event.h"
1538+#include "geis_group.h"
1539+#include "geis_logging.h"
1540+#include "geis_touch.h"
1541+
1542+/**
1543+ * A frame is marshalled as a dict entry of
1544+ * {id: [array of attrs, array of touch ids]}, which is {i(a(sv)ai))} in
1545+ * DBus terminaology.
1546+ */
1547+#define GEIS_DBUS_TYPE_SIGNATURE_FRAME \
1548+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \
1549+ DBUS_TYPE_INT32_AS_STRING \
1550+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
1551+ DBUS_TYPE_ARRAY_AS_STRING \
1552+ GEIS_DBUS_TYPE_SIGNATURE_ATTR \
1553+ DBUS_TYPE_ARRAY_AS_STRING \
1554+ DBUS_TYPE_INT32_AS_STRING \
1555+ DBUS_STRUCT_END_CHAR_AS_STRING \
1556+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING \
1557+
1558+#define GEIS_DBUS_TYPE_SIGNATURE_FRAMESET \
1559+ DBUS_TYPE_ARRAY_AS_STRING \
1560+ GEIS_DBUS_TYPE_SIGNATURE_FRAME
1561+
1562+
1563+static void
1564+_marshall_touchset(GeisTouchSet touchset, DBusMessageIter *iter)
1565+{
1566+ DBusMessageIter touchset_iter;
1567+ dbus_message_iter_open_container(iter,
1568+ DBUS_TYPE_ARRAY,
1569+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1570+ DBUS_TYPE_INT32_AS_STRING
1571+ DBUS_TYPE_ARRAY_AS_STRING
1572+ GEIS_DBUS_TYPE_SIGNATURE_ATTR
1573+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1574+ &touchset_iter);
1575+ for (GeisSize t = 0; t < geis_touchset_touch_count(touchset); ++t)
1576+ {
1577+ DBusMessageIter touch_iter;
1578+ dbus_message_iter_open_container(&touchset_iter,
1579+ DBUS_TYPE_DICT_ENTRY,
1580+ NULL,
1581+ &touch_iter);
1582+ GeisTouch touch = geis_touchset_touch(touchset, t);
1583+ dbus_int32_t touch_id = geis_touch_id(touch);
1584+
1585+ dbus_message_iter_append_basic(&touch_iter, DBUS_TYPE_INT32, &touch_id);
1586+ DBusMessageIter attr_iter;
1587+ dbus_message_iter_open_container(&touch_iter,
1588+ DBUS_TYPE_ARRAY,
1589+ GEIS_DBUS_TYPE_SIGNATURE_ATTR,
1590+ &attr_iter);
1591+ for (GeisSize a = 0; a < geis_touch_attr_count(touch); ++a)
1592+ {
1593+ geis_dbus_attr_marshall(geis_touch_attr(touch, a), &attr_iter);
1594+ }
1595+ dbus_message_iter_close_container(&touch_iter, &attr_iter);
1596+ dbus_message_iter_close_container(&touchset_iter, &touch_iter);
1597+ }
1598+ dbus_message_iter_close_container(iter, &touchset_iter);
1599+}
1600+
1601+
1602+static void
1603+_unmarshall_touchset(DBusMessageIter *iter, GeisTouchSet touchset)
1604+{
1605+ int dtype = dbus_message_iter_get_arg_type(iter);
1606+ if (dtype != DBUS_TYPE_ARRAY)
1607+ {
1608+ geis_error("malformed GeisEvent touchset");
1609+ }
1610+
1611+ DBusMessageIter touch_iter;
1612+ dbus_message_iter_recurse(iter, &touch_iter);
1613+ for (dtype = dbus_message_iter_get_arg_type(&touch_iter);
1614+ dtype != DBUS_TYPE_INVALID;
1615+ dbus_message_iter_next(&touch_iter),
1616+ dtype = dbus_message_iter_get_arg_type(&touch_iter))
1617+ {
1618+ DBusMessageIter dict_iter;
1619+ dbus_message_iter_recurse(&touch_iter, &dict_iter);
1620+ int type = dbus_message_iter_get_arg_type(&dict_iter);
1621+ if (type != DBUS_TYPE_INT32)
1622+ {
1623+ geis_error("malformed GeisEvent touchset");
1624+ continue;
1625+ }
1626+ dbus_int32_t touch_id;
1627+ dbus_message_iter_get_basic(&dict_iter, &touch_id);
1628+ dbus_message_iter_next(&dict_iter);
1629+ GeisTouch touch = geis_touch_new(touch_id);
1630+
1631+ type = dbus_message_iter_get_arg_type(&dict_iter);
1632+ if (type != DBUS_TYPE_ARRAY)
1633+ {
1634+ geis_error("malformed GeisEvent touchset");
1635+ continue;
1636+ }
1637+
1638+ DBusMessageIter attr_iter;
1639+ dbus_message_iter_recurse(&dict_iter, &attr_iter);
1640+ for (int type = dbus_message_iter_get_arg_type(&attr_iter);
1641+ type != DBUS_TYPE_INVALID;
1642+ dbus_message_iter_next(&attr_iter),
1643+ type = dbus_message_iter_get_arg_type(&attr_iter))
1644+ {
1645+ GeisAttr attr = geis_dbus_attr_unmarshall(&attr_iter);
1646+ geis_touch_add_attr(touch, attr);
1647+ }
1648+ geis_touchset_insert(touchset, touch);
1649+ }
1650+}
1651+
1652+
1653+/**
1654+ * Marshalls a GEIS frame to a DBus message via a message iterator.
1655+ * @param[in] frame The GEIS frame to marshall.
1656+ * @param[in] iter The DBus message iterator.
1657+ *
1658+ * @todo The class set and matrix need to be added.
1659+ */
1660+static void
1661+_marshall_frame(GeisFrame frame, DBusMessageIter *frame_iter)
1662+{
1663+ DBusMessageIter dict_iter;
1664+ dbus_message_iter_open_container(frame_iter,
1665+ DBUS_TYPE_DICT_ENTRY,
1666+ NULL,
1667+ &dict_iter);
1668+
1669+ dbus_int32_t frame_id = geis_frame_id(frame);
1670+ dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_INT32, &frame_id);
1671+
1672+ {
1673+ DBusMessageIter struct_iter;
1674+ dbus_message_iter_open_container(&dict_iter,
1675+ DBUS_TYPE_STRUCT,
1676+ NULL,
1677+ &struct_iter);
1678+ {
1679+ DBusMessageIter attr_iter;
1680+ dbus_message_iter_open_container(&struct_iter,
1681+ DBUS_TYPE_ARRAY,
1682+ GEIS_DBUS_TYPE_SIGNATURE_ATTR,
1683+ &attr_iter);
1684+ for (GeisSize a = 0; a < geis_frame_attr_count(frame); ++a)
1685+ {
1686+ geis_dbus_attr_marshall(geis_frame_attr(frame, a), &attr_iter);
1687+ }
1688+ dbus_message_iter_close_container(&struct_iter, &attr_iter);
1689+ }
1690+ {
1691+ DBusMessageIter touch_iter;
1692+ dbus_message_iter_open_container(&struct_iter,
1693+ DBUS_TYPE_ARRAY,
1694+ DBUS_TYPE_INT32_AS_STRING,
1695+ &touch_iter);
1696+ for (GeisSize t = 0; t < geis_frame_touchid_count(frame); ++t)
1697+ {
1698+ dbus_int32_t touch_id = geis_frame_touchid(frame, t);
1699+ dbus_message_iter_append_basic(&touch_iter, DBUS_TYPE_INT32, &touch_id);
1700+ }
1701+ dbus_message_iter_close_container(&struct_iter, &touch_iter);
1702+ }
1703+ dbus_message_iter_close_container(&dict_iter, &struct_iter);
1704+ }
1705+ dbus_message_iter_close_container(frame_iter, &dict_iter);
1706+}
1707+
1708+
1709+/**
1710+ * Unmarshalls a GEIS frame from a DBus message via a message iterator.
1711+ * @param[in] frame_iter The DBus message iterator.
1712+ * @param[in] group The group the unmarshalled frame will belong to.
1713+ */
1714+static void
1715+_unmarshall_frame(DBusMessageIter *frame_iter, GeisGroup group)
1716+{
1717+ int type = dbus_message_iter_get_arg_type(frame_iter);
1718+ if (type != DBUS_TYPE_DICT_ENTRY)
1719+ {
1720+ geis_error("malformed GeisEvent frame: expected %c, received %c",
1721+ DBUS_TYPE_DICT_ENTRY, type);
1722+ goto final_exit;
1723+ }
1724+ DBusMessageIter dict_iter;
1725+ dbus_message_iter_recurse(frame_iter, &dict_iter);
1726+
1727+ type = dbus_message_iter_get_arg_type(&dict_iter);
1728+ if (type != DBUS_TYPE_INT32)
1729+ {
1730+ geis_error("malformed GeisEvent frame: expected %c, received %c",
1731+ DBUS_TYPE_INT32, type);
1732+ goto final_exit;
1733+ }
1734+ dbus_int32_t frame_id;
1735+ dbus_message_iter_get_basic(&dict_iter, &frame_id);
1736+ GeisFrame frame = geis_frame_new(frame_id);
1737+ geis_group_insert_frame(group, frame);
1738+
1739+ dbus_message_iter_next(&dict_iter);
1740+ type = dbus_message_iter_get_arg_type(&dict_iter);
1741+ if (type != DBUS_TYPE_STRUCT)
1742+ {
1743+ geis_error("malformed GeisEvent frame: expected %c, received %c",
1744+ DBUS_TYPE_STRUCT, type);
1745+ }
1746+ else
1747+ {
1748+ DBusMessageIter struct_iter;
1749+ dbus_message_iter_recurse(&dict_iter, &struct_iter);
1750+
1751+ type = dbus_message_iter_get_arg_type(&struct_iter);
1752+ if (type != DBUS_TYPE_ARRAY)
1753+ {
1754+ geis_error("malformed GeisEvent frame: expected %c, received %c",
1755+ DBUS_TYPE_ARRAY, type);
1756+ }
1757+ else
1758+ {
1759+ DBusMessageIter attr_iter;
1760+ dbus_message_iter_recurse(&struct_iter, &attr_iter);
1761+ for (int type = dbus_message_iter_get_arg_type(&attr_iter);
1762+ type != DBUS_TYPE_INVALID;
1763+ dbus_message_iter_next(&attr_iter),
1764+ type = dbus_message_iter_get_arg_type(&attr_iter))
1765+ {
1766+ GeisAttr attr = geis_dbus_attr_unmarshall(&attr_iter);
1767+ geis_frame_add_attr(frame, attr);
1768+ }
1769+ }
1770+
1771+ dbus_message_iter_next(&struct_iter),
1772+ type = dbus_message_iter_get_arg_type(&struct_iter);
1773+ if (type != DBUS_TYPE_ARRAY)
1774+ {
1775+ geis_error("malformed GeisEvent frame: expected %c, received %c",
1776+ DBUS_TYPE_ARRAY, type);
1777+ }
1778+ else
1779+ {
1780+ DBusMessageIter touch_iter;
1781+ dbus_message_iter_recurse(&struct_iter, &touch_iter);
1782+ for (int type = dbus_message_iter_get_arg_type(&touch_iter);
1783+ type != DBUS_TYPE_INVALID;
1784+ dbus_message_iter_next(&touch_iter),
1785+ type = dbus_message_iter_get_arg_type(&touch_iter))
1786+ {
1787+ type = dbus_message_iter_get_arg_type(&touch_iter);
1788+ if (type != DBUS_TYPE_INT32)
1789+ {
1790+ geis_error("malformed GeisEvent frame: expected %c, received %c",
1791+ DBUS_TYPE_INT32, type);
1792+ break;
1793+ }
1794+
1795+ dbus_int32_t touch_id;
1796+ dbus_message_iter_get_basic(&touch_iter, &touch_id);
1797+ geis_frame_add_touchid(frame, touch_id);
1798+ }
1799+ }
1800+ }
1801+
1802+final_exit:
1803+ return;
1804+}
1805+
1806+
1807+/**
1808+ * Marshalls a GEIS groupset to a DBus message via a message iterator.
1809+ * @param[in] groupset The GEIS groupset.
1810+ * @param[in] iter A DBus message iterator.
1811+ */
1812+static void
1813+_marshall_groupset(GeisGroupSet groupset, DBusMessageIter *iter)
1814+{
1815+ DBusMessageIter groupset_iter;
1816+ dbus_message_iter_open_container(iter,
1817+ DBUS_TYPE_ARRAY,
1818+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1819+ DBUS_TYPE_INT32_AS_STRING
1820+ GEIS_DBUS_TYPE_SIGNATURE_FRAMESET
1821+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1822+ &groupset_iter);
1823+ for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i)
1824+ {
1825+ GeisGroup group = geis_groupset_group(groupset, i);
1826+ if (!group)
1827+ {
1828+ geis_warning("can not extract group %zu from groupset", i);
1829+ goto final_exit;
1830+ }
1831+ DBusMessageIter group_iter;
1832+ dbus_message_iter_open_container(&groupset_iter,
1833+ DBUS_TYPE_DICT_ENTRY,
1834+ NULL,
1835+ &group_iter);
1836+ dbus_int32_t group_id = geis_group_id(group);
1837+ dbus_message_iter_append_basic(&group_iter, DBUS_TYPE_INT32, &group_id);
1838+ DBusMessageIter frameset_iter;
1839+ dbus_message_iter_open_container(&group_iter,
1840+ DBUS_TYPE_ARRAY,
1841+ GEIS_DBUS_TYPE_SIGNATURE_FRAME,
1842+ &frameset_iter);
1843+ for (GeisSize j = 0; j < geis_group_frame_count(group); ++j)
1844+ {
1845+ GeisFrame frame = geis_group_frame(group, j);
1846+ if (!frame)
1847+ {
1848+ geis_warning("can not extract frame %zu from group", j);
1849+ goto final_exit;
1850+ }
1851+ _marshall_frame(frame, &frameset_iter);
1852+ }
1853+ dbus_message_iter_close_container(&group_iter, &frameset_iter);
1854+ dbus_message_iter_close_container(&groupset_iter, &group_iter);
1855+ }
1856+ dbus_message_iter_close_container(iter, &groupset_iter);
1857+
1858+final_exit:
1859+ return;
1860+}
1861+
1862+
1863+static void
1864+_unmarshall_groupset(DBusMessageIter *iter, GeisGroupSet groupset)
1865+{
1866+ int dtype = dbus_message_iter_get_arg_type(iter);
1867+ if (dtype != DBUS_TYPE_ARRAY)
1868+ {
1869+ geis_error("malformed GeisEvent groupset");
1870+ }
1871+
1872+ DBusMessageIter groupset_iter;
1873+ dbus_message_iter_recurse(iter, &groupset_iter);
1874+ for (dtype = dbus_message_iter_get_arg_type(&groupset_iter);
1875+ dtype != DBUS_TYPE_INVALID;
1876+ dbus_message_iter_next(&groupset_iter),
1877+ dtype = dbus_message_iter_get_arg_type(&groupset_iter))
1878+ {
1879+ DBusMessageIter group_iter;
1880+ dbus_message_iter_recurse(&groupset_iter, &group_iter);
1881+
1882+ int type = dbus_message_iter_get_arg_type(&group_iter);
1883+ if (type != DBUS_TYPE_INT32)
1884+ {
1885+ geis_error("malformed GeisEvent group");
1886+ continue;
1887+ }
1888+ dbus_int32_t group_id;
1889+ dbus_message_iter_get_basic(&group_iter, &group_id);
1890+ GeisGroup group = geis_group_new(group_id);
1891+ geis_groupset_insert(groupset, group);
1892+ dbus_message_iter_next(&group_iter);
1893+
1894+ DBusMessageIter frameset_iter;
1895+ dbus_message_iter_recurse(&group_iter, &frameset_iter);
1896+ for (int ftype = dbus_message_iter_get_arg_type(&frameset_iter);
1897+ ftype != DBUS_TYPE_INVALID;
1898+ dbus_message_iter_next(&frameset_iter),
1899+ ftype = dbus_message_iter_get_arg_type(&frameset_iter))
1900+ {
1901+ _unmarshall_frame(&frameset_iter, group);
1902+ }
1903+ }
1904+}
1905+
1906+
1907+/*
1908+ * Creates a Dbus "gesture event" message from a GEIS gesture event.
1909+ *
1910+ * A gesture event has the following structure.
1911+ * - a numeric event type (begin/update/end)
1912+ * - a set of one or more touches, where each touch has
1913+ * - a touch ID
1914+ * - a set of one or more attrs
1915+ * - a set of one or more gesture groups, where is group has
1916+ * - a group ID
1917+ * - a set of one or more gesture frames, where each frame has
1918+ * - a set of one or more gesture classes
1919+ * - a set of one or more gesture attrs
1920+ * - a zet of one or more touch indexes
1921+ *
1922+ * @todo add the gesture classes
1923+ */
1924+DBusMessage *
1925+geis_dbus_gesture_event_message_from_geis_event(GeisEvent event)
1926+{
1927+ DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH,
1928+ GEIS_DBUS_SERVICE_INTERFACE,
1929+ GEIS_DBUS_GESTURE_EVENT);
1930+ DBusMessageIter iter;
1931+ dbus_message_iter_init_append(message, &iter);
1932+
1933+ dbus_uint32_t event_type = geis_event_type(event);
1934+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &event_type);
1935+
1936+ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET);
1937+ if (!attr)
1938+ {
1939+ geis_error("no touchset for gesture event");
1940+ goto final_exit;
1941+ }
1942+
1943+ GeisTouchSet touchset = geis_attr_value_to_pointer(attr);
1944+ if (!touchset)
1945+ {
1946+ geis_warning("can not convert attr to touchset");
1947+ goto final_exit;
1948+ }
1949+
1950+ _marshall_touchset(touchset, &iter);
1951+
1952+ attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
1953+ if (!attr)
1954+ {
1955+ geis_error("no groupset for gesture event");
1956+ goto final_exit;
1957+ }
1958+
1959+ GeisGroupSet groupset = geis_attr_value_to_pointer(attr);
1960+ if (!groupset)
1961+ {
1962+ geis_warning("can not convert attr to groupset");
1963+ goto final_exit;
1964+ }
1965+
1966+ _marshall_groupset(groupset, &iter);
1967+
1968+final_exit:
1969+ return message;
1970+}
1971+
1972+
1973+/*
1974+ * Indicates if a DBus message is a "gesture event" message.
1975+ */
1976+GeisBoolean
1977+geis_dbus_message_is_gesture_event(DBusMessage *message)
1978+{
1979+ GeisBoolean is_gesture_event_message = GEIS_FALSE;
1980+ if (dbus_message_is_signal(message,
1981+ GEIS_DBUS_SERVICE_INTERFACE,
1982+ GEIS_DBUS_GESTURE_EVENT))
1983+ {
1984+ is_gesture_event_message = GEIS_TRUE;
1985+ }
1986+
1987+ return is_gesture_event_message;
1988+}
1989+
1990+
1991+/*
1992+ * Creates GEIS event from a DBus "gesture_event" message.
1993+ */
1994+GeisEvent
1995+geis_dbus_gesture_event_from_message(DBusMessage *message)
1996+{
1997+ DBusMessageIter iter;
1998+ dbus_message_iter_init(message, &iter);
1999+
2000+ dbus_uint32_t event_type;
2001+ dbus_message_iter_get_basic(&iter, &event_type);
2002+ GeisEvent event = geis_event_new(event_type);
2003+
2004+ dbus_message_iter_next(&iter);
2005+ GeisTouchSet touchset = geis_touchset_new();
2006+ _unmarshall_touchset(&iter, touchset);
2007+ GeisAttr touch_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_TOUCHSET,
2008+ GEIS_ATTR_TYPE_POINTER,
2009+ touchset);
2010+ geis_attr_set_destructor(touch_attr, (GeisAttrDestructor)geis_touchset_delete);
2011+ geis_event_add_attr(event, touch_attr);
2012+
2013+ dbus_message_iter_next(&iter);
2014+ GeisGroupSet groupset = geis_groupset_new();
2015+ _unmarshall_groupset(&iter, groupset);
2016+ GeisAttr group_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_GROUPSET,
2017+ GEIS_ATTR_TYPE_POINTER,
2018+ groupset);
2019+ geis_attr_set_destructor(group_attr, (GeisAttrDestructor)geis_groupset_delete);
2020+ geis_event_add_attr(event, group_attr);
2021+
2022+ return event;
2023+}
2024+
2025+
2026
2027=== added file 'libs/geis-dbus/geis_dbus_gesture_event.h'
2028--- libs/geis-dbus/geis_dbus_gesture_event.h 1970-01-01 00:00:00 +0000
2029+++ libs/geis-dbus/geis_dbus_gesture_event.h 2011-10-17 21:56:23 +0000
2030@@ -0,0 +1,55 @@
2031+/**
2032+ * @file geis_dbus_gesture_event.h
2033+ * @brief Interface for the GEIS DBus gesture event transport.
2034+ */
2035+
2036+/*
2037+ * Copyright 2011 Canonical Ltd.
2038+ *
2039+ * This library is free software; you can redistribute it and/or modify it under
2040+ * the terms of the GNU Lesser General Public License as published by the Free
2041+ * Software Foundation; either version 3 of the License, or (at your option) any
2042+ * later version.
2043+ *
2044+ * This library is distributed in the hope that it will be useful, but WITHOUT
2045+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2046+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2047+ * details.
2048+ *
2049+ * You should have received a copy of the GNU General Public License
2050+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2051+ */
2052+#ifndef GEIS_DBUS_GESTURE_EVENT_H_
2053+#define GEIS_DBUS_GESTURE_EVENT_H_
2054+
2055+#include <dbus/dbus.h>
2056+#include "geis/geis.h"
2057+
2058+
2059+/**
2060+ * Creates a Dbus "gesture event" message from a GEIS gesture event.
2061+ *
2062+ * @param[in] event A GEIS event.
2063+ */
2064+DBusMessage *
2065+geis_dbus_gesture_event_message_from_geis_event(GeisEvent event);
2066+
2067+/**
2068+ * Indicates if a DBus message is a "gesture event" message.
2069+ *
2070+ * @param[in] message A DBus message.
2071+ */
2072+GeisBoolean
2073+geis_dbus_message_is_gesture_event(DBusMessage *message);
2074+
2075+/**
2076+ * Creates GEIS event from a DBus "gesture_event" message.
2077+ *
2078+ * @param[in] message A DBus message.
2079+ */
2080+GeisEvent
2081+geis_dbus_gesture_event_from_message(DBusMessage *message);
2082+
2083+
2084+#endif /* GEIS_DBUS_GESTURE_EVENT_H_ */
2085+
2086
2087=== added file 'libs/geis-dbus/geis_dbus_region.c'
2088--- libs/geis-dbus/geis_dbus_region.c 1970-01-01 00:00:00 +0000
2089+++ libs/geis-dbus/geis_dbus_region.c 2011-10-17 21:56:23 +0000
2090@@ -0,0 +1,91 @@
2091+/**
2092+ * @file geis_dbus_region.c
2093+ * @brief Implementations of the GEIS DBus region transport.
2094+ */
2095+
2096+/*
2097+ * Copyright 2011 Canonical Ltd.
2098+ *
2099+ * This library is free software; you can redistribute it and/or modify it under
2100+ * the terms of the GNU Lesser General Public License as published by the Free
2101+ * Software Foundation; either version 3 of the License, or (at your option) any
2102+ * later version.
2103+ *
2104+ * This library is distributed in the hope that it will be useful, but WITHOUT
2105+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2106+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2107+ * details.
2108+ *
2109+ * You should have received a copy of the GNU Lesser General Public License
2110+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2111+ */
2112+#include "geis_config.h"
2113+#include "geis_dbus_region.h"
2114+
2115+#include "geis_dbus.h"
2116+#include "geis_logging.h"
2117+
2118+
2119+/*
2120+ * Creates a Dbus "region available" message from a GEIS region.
2121+ */
2122+DBusMessage *
2123+geis_dbus_region_available_message_from_region(GeisFilterableAttribute fa)
2124+{
2125+ DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH,
2126+ GEIS_DBUS_SERVICE_INTERFACE,
2127+ GEIS_DBUS_REGION_AVAILABLE);
2128+ DBusMessageIter iter;
2129+ dbus_message_iter_init_append(message, &iter);
2130+
2131+ const char *attr_name = fa->name;
2132+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &attr_name);
2133+
2134+ dbus_int32_t attr_type = fa->type;
2135+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &attr_type);
2136+
2137+
2138+ return message;
2139+}
2140+
2141+
2142+/*
2143+ * Creates GEIS region filterable attribute from a DBus "region available"
2144+ * message.
2145+ */
2146+GeisFilterableAttribute
2147+geis_dbus_region_from_region_available_message(DBusMessage *message)
2148+{
2149+ geis_debug("begins");
2150+ static struct GeisFilterableAttribute attr;
2151+ DBusMessageIter iter;
2152+ dbus_message_iter_init(message, &iter);
2153+
2154+ int type = dbus_message_iter_get_arg_type(&iter);
2155+ if (type != DBUS_TYPE_STRING)
2156+ {
2157+ geis_error("error getting attr name name from DBus message.");
2158+ goto final_exit;
2159+ }
2160+ char *attr_name;
2161+ dbus_message_iter_get_basic(&iter, &attr_name);
2162+ dbus_message_iter_next(&iter);
2163+
2164+ type = dbus_message_iter_get_arg_type(&iter);
2165+ if (type != DBUS_TYPE_INT32)
2166+ {
2167+ geis_error("error getting attr type from DBus message.");
2168+ goto final_exit;
2169+ }
2170+ dbus_int32_t attr_type;
2171+ dbus_message_iter_get_basic(&iter, &attr_type);
2172+
2173+ attr.name = attr_name;
2174+ attr.type = attr_type;
2175+
2176+final_exit:
2177+ geis_debug("ends");
2178+ return &attr;
2179+}
2180+
2181+
2182
2183=== added file 'libs/geis-dbus/geis_dbus_region.h'
2184--- libs/geis-dbus/geis_dbus_region.h 1970-01-01 00:00:00 +0000
2185+++ libs/geis-dbus/geis_dbus_region.h 2011-10-17 21:56:23 +0000
2186@@ -0,0 +1,47 @@
2187+/**
2188+ * @file geis_dbus_region.h
2189+ * @brief Interface for the GEIS DBus region transport.
2190+ */
2191+
2192+/*
2193+ * Copyright 2011 Canonical Ltd.
2194+ *
2195+ * This library is free software; you can redistribute it and/or modify it under
2196+ * the terms of the GNU Lesser General Public License as published by the Free
2197+ * Software Foundation; either version 3 of the License, or (at your option) any
2198+ * later version.
2199+ *
2200+ * This library is distributed in the hope that it will be useful, but WITHOUT
2201+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2202+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2203+ * details.
2204+ *
2205+ * You should have received a copy of the GNU General Public License
2206+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2207+ */
2208+#ifndef GEIS_DBUS_REGION_H_
2209+#define GEIS_DBUS_REGION_H_
2210+
2211+#include <dbus/dbus.h>
2212+#include "geis/geis.h"
2213+#include "geis_filterable.h"
2214+
2215+
2216+/**
2217+ * Creates a Dbus "region available" message from a GEIS region.
2218+ *
2219+ * @param[in] fa A GEIS region filterable attribute.
2220+ */
2221+DBusMessage *
2222+geis_dbus_region_available_message_from_region(GeisFilterableAttribute fa);
2223+
2224+/**
2225+ * Creates GEIS region filterable attribute from a DBus "region available"
2226+ * message.
2227+ *
2228+ * @param[in] message A DBus message.
2229+ */
2230+GeisFilterableAttribute
2231+geis_dbus_region_from_region_available_message(DBusMessage *message);
2232+
2233+#endif /* GEIS_DBUS_REGION_H_ */
2234
2235=== added file 'libs/geis-dbus/geis_dbus_subscription.c'
2236--- libs/geis-dbus/geis_dbus_subscription.c 1970-01-01 00:00:00 +0000
2237+++ libs/geis-dbus/geis_dbus_subscription.c 2011-10-17 21:56:23 +0000
2238@@ -0,0 +1,506 @@
2239+/**
2240+ * @file geis_dbus_subscription.c
2241+ * @brief Implementation of the GEIS DBus subscription transport.
2242+ */
2243+
2244+/*
2245+ * Copyright 2011 Canonical Ltd.
2246+ *
2247+ * This library is free software; you can redistribute it and/or modify it under
2248+ * the terms of the GNU Lesser General Public License as published by the Free
2249+ * Software Foundation; either version 3 of the License, or (at your option) any
2250+ * later version.
2251+ *
2252+ * This library is distributed in the hope that it will be useful, but WITHOUT
2253+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2254+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2255+ * details.
2256+ *
2257+ * You should have received a copy of the GNU General Public License
2258+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2259+ */
2260+#include "geis_config.h"
2261+#include "geis_dbus_subscription.h"
2262+
2263+#include "geis_dbus.h"
2264+#include "geis_dbus_attr.h"
2265+#include "geis_filter_term.h"
2266+#include "geis_logging.h"
2267+#include "geis_subscription.h"
2268+#include <stdint.h>
2269+
2270+
2271+/*
2272+ * A filter term is marshalled as a (facility, operation, value) tuple.
2273+ * That would be a (ii(sv)) in DBusspeak.
2274+ */
2275+#define GEIS_DBUS_TYPE_SIGNATURE_TERM \
2276+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
2277+ DBUS_TYPE_INT32_AS_STRING \
2278+ DBUS_TYPE_INT32_AS_STRING \
2279+ GEIS_DBUS_TYPE_SIGNATURE_ATTR \
2280+ DBUS_STRUCT_END_CHAR_AS_STRING
2281+
2282+/*
2283+ * A term list is an array of terms, as in a(ii(sv)).
2284+ */
2285+#define GEIS_DBUS_TYPE_SIGNATURE_TERM_LIST \
2286+ DBUS_TYPE_ARRAY_AS_STRING \
2287+ GEIS_DBUS_TYPE_SIGNATURE_TERM
2288+
2289+/*
2290+ * A filter is a named array of filter terms.
2291+ * That's a {sa(ii(sv))} in the DBus tongue.
2292+ */
2293+#define GEIS_DBUS_TYPE_SIGNATURE_FILTER \
2294+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \
2295+ DBUS_TYPE_STRING_AS_STRING \
2296+ GEIS_DBUS_TYPE_SIGNATURE_TERM_LIST \
2297+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
2298+
2299+
2300+/**
2301+ * Adds filter terms to a DBus message.
2302+ *
2303+ * @param[in] filter The filter for which terms will be marshalled.
2304+ * @param[in] filter_iter A DBus message output iterator.
2305+ */
2306+static void
2307+_geis_dbus_marshall_subscription_filter_terms(GeisFilter filter,
2308+ DBusMessageIter *filter_iter)
2309+{
2310+ DBusMessageIter term_list_iter;
2311+ dbus_message_iter_open_container(filter_iter,
2312+ DBUS_TYPE_ARRAY,
2313+ GEIS_DBUS_TYPE_SIGNATURE_TERM,
2314+ &term_list_iter);
2315+ for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i)
2316+ {
2317+ GeisFilterTerm term = geis_filter_term(filter, i);
2318+ dbus_int32_t facility = geis_filter_term_facility(term);
2319+ dbus_int32_t operation = geis_filter_term_operation(term);
2320+ GeisAttr attr = geis_filter_term_attr(term);
2321+
2322+ DBusMessageIter term_iter;
2323+ dbus_message_iter_open_container(&term_list_iter,
2324+ DBUS_TYPE_STRUCT,
2325+ NULL,
2326+ &term_iter);
2327+ dbus_message_iter_append_basic(&term_iter, DBUS_TYPE_INT32, &facility);
2328+ dbus_message_iter_append_basic(&term_iter, DBUS_TYPE_INT32, &operation);
2329+ geis_dbus_attr_marshall(attr, &term_iter);
2330+ dbus_message_iter_close_container(&term_list_iter, &term_iter);
2331+ }
2332+ dbus_message_iter_close_container(filter_iter, &term_list_iter);
2333+}
2334+
2335+
2336+/**
2337+ * Squeezes the filters on a subscription into the DBus wire protocol.
2338+ *
2339+ * @param[in] sub A %GeisSubscription
2340+ * @param[in] msg_iter The open output iterator for a DBus message.
2341+ *
2342+ * The filters are marshalled as an array of DBus dict entries.
2343+ */
2344+static void
2345+_geis_dbus_marshall_subscription_filters(GeisSubscription subscription,
2346+ DBusMessageIter *msg_iter)
2347+{
2348+ DBusMessageIter filter_list_iter;
2349+
2350+ dbus_message_iter_open_container(msg_iter,
2351+ DBUS_TYPE_ARRAY,
2352+ GEIS_DBUS_TYPE_SIGNATURE_FILTER,
2353+ &filter_list_iter);
2354+
2355+ for (GeisFilterIterator it = geis_subscription_filter_begin(subscription);
2356+ it != geis_subscription_filter_end(subscription);
2357+ it = geis_subscription_filter_next(subscription, it))
2358+ {
2359+ const char *filter_name = geis_filter_name(*it);
2360+
2361+ DBusMessageIter filter_iter;
2362+ dbus_message_iter_open_container(&filter_list_iter,
2363+ DBUS_TYPE_DICT_ENTRY,
2364+ NULL,
2365+ &filter_iter);
2366+ dbus_message_iter_append_basic(&filter_iter, DBUS_TYPE_STRING, &filter_name);
2367+ _geis_dbus_marshall_subscription_filter_terms(*it, &filter_iter);
2368+ dbus_message_iter_close_container(&filter_list_iter, &filter_iter);
2369+ }
2370+ dbus_message_iter_close_container(msg_iter, &filter_list_iter);
2371+}
2372+
2373+
2374+static void
2375+_geis_dbus_unmarshall_filter_terms(GeisFilter filter,
2376+ DBusMessageIter *filter_iter)
2377+{
2378+ DBusMessageIter term_list_iter;
2379+ dbus_message_iter_recurse(filter_iter, &term_list_iter);
2380+ for (int dtype = dbus_message_iter_get_arg_type(&term_list_iter);
2381+ dtype != DBUS_TYPE_INVALID;
2382+ dbus_message_iter_next(&term_list_iter),
2383+ dtype = dbus_message_iter_get_arg_type(&term_list_iter))
2384+ {
2385+ int ttype = dbus_message_iter_get_arg_type(&term_list_iter);
2386+ if (ttype != DBUS_TYPE_STRUCT)
2387+ {
2388+ geis_error("malformed GeisSubscription term");
2389+ goto final_exit;
2390+ }
2391+
2392+ DBusMessageIter term_iter;
2393+ dbus_message_iter_recurse(&term_list_iter, &term_iter);
2394+
2395+ dbus_int32_t facility;
2396+ dbus_message_iter_get_basic(&term_iter, &facility);
2397+ dbus_message_iter_next(&term_iter);
2398+
2399+ dbus_int32_t operation;
2400+ dbus_message_iter_get_basic(&term_iter, &operation);
2401+ dbus_message_iter_next(&term_iter);
2402+
2403+ GeisAttr attr = geis_dbus_attr_unmarshall(&term_iter);
2404+ GeisFilterTerm term = geis_filter_term_new(facility, operation, attr);
2405+ geis_filter_add_term_internal(filter, term);
2406+ }
2407+
2408+final_exit:
2409+ return;
2410+}
2411+
2412+
2413+/**
2414+ * Unmarshalls a filter from a DBus message.
2415+ *
2416+ * @param[in] geis A GEIS instance.
2417+ * @param[in] filter_iter A DBus message iterator pointing to the filter.
2418+ */
2419+static GeisFilter
2420+_geis_dbus_unmarshall_filter(Geis geis, DBusMessageIter *filter_iter)
2421+{
2422+ GeisFilter filter = NULL;
2423+
2424+ int ftype = dbus_message_iter_get_arg_type(filter_iter);
2425+ if (ftype != DBUS_TYPE_DICT_ENTRY)
2426+ {
2427+ geis_error("malformed GeisSubscription filter");
2428+ goto final_exit;
2429+ }
2430+
2431+ DBusMessageIter dict_iter;
2432+ dbus_message_iter_recurse(filter_iter, &dict_iter);
2433+
2434+ ftype = dbus_message_iter_get_arg_type(&dict_iter);
2435+ if (ftype != DBUS_TYPE_STRING)
2436+ {
2437+ geis_error("malformed GeisSubscription filter");
2438+ goto final_exit;
2439+ }
2440+ GeisString filter_name;
2441+ dbus_message_iter_get_basic(&dict_iter, &filter_name);
2442+ dbus_message_iter_next(&dict_iter);
2443+
2444+ filter = geis_filter_new(geis, filter_name);
2445+
2446+ ftype = dbus_message_iter_get_arg_type(&dict_iter);
2447+ if (ftype != DBUS_TYPE_ARRAY)
2448+ {
2449+ geis_error("malformed GeisSubscription filter");
2450+ goto final_exit;
2451+ }
2452+ _geis_dbus_unmarshall_filter_terms(filter, &dict_iter);
2453+
2454+final_exit:
2455+ return filter;
2456+}
2457+
2458+
2459+/**
2460+ * Unmarshalls a list of filters from a DBus message.
2461+ *
2462+ * @param[in] geis A GEIS instance.
2463+ * @param[in] subscription_iter A DBus message iterator for the subscription.
2464+ * @param[in] subscription A GEIS subsccription.
2465+ *
2466+ * This function unmarshalls filters from a GEIS DBus subscription message and
2467+ * adds them to a existing GEIS subscription.
2468+ */
2469+static void
2470+_geis_dbus_unmarshall_subscription_filters(Geis geis,
2471+ DBusMessageIter *subscription_iter,
2472+ GeisSubscription subscription)
2473+{
2474+ DBusMessageIter filter_list_iter;
2475+ dbus_message_iter_recurse(subscription_iter, &filter_list_iter);
2476+ for (int dtype = dbus_message_iter_get_arg_type(&filter_list_iter);
2477+ dtype != DBUS_TYPE_INVALID;
2478+ dbus_message_iter_next(&filter_list_iter),
2479+ dtype = dbus_message_iter_get_arg_type(&filter_list_iter))
2480+ {
2481+ GeisFilter filter = _geis_dbus_unmarshall_filter(geis, &filter_list_iter);
2482+ if (filter)
2483+ {
2484+ geis_subscription_add_filter(subscription, filter);
2485+ }
2486+ }
2487+}
2488+
2489+
2490+/*
2491+ * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_CREATE method call.
2492+ */
2493+GeisBoolean
2494+geis_dbus_message_is_subscription_create_call(DBusMessage *message)
2495+{
2496+ return dbus_message_is_method_call(message,
2497+ GEIS_DBUS_SERVICE_INTERFACE,
2498+ GEIS_DBUS_SUBSCRIPTION_CREATE);
2499+}
2500+
2501+
2502+/*
2503+ * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method call message.
2504+ */
2505+DBusMessage *
2506+geis_dbus_subscription_create_call_message(GeisSubscription subscription)
2507+{
2508+ DBusMessage *message = NULL;
2509+ GeisString sub_name = "dummy";
2510+ dbus_int32_t sub_id = -1;
2511+ dbus_uint32_t sub_flags = 0;
2512+ DBusMessageIter iter;
2513+
2514+ message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
2515+ GEIS_DBUS_SERVICE_PATH,
2516+ GEIS_DBUS_SERVICE_INTERFACE,
2517+ GEIS_DBUS_SUBSCRIPTION_CREATE);
2518+
2519+ if (subscription)
2520+ {
2521+ sub_name = geis_subscription_name(subscription);
2522+ sub_id = geis_subscription_id(subscription);
2523+ sub_flags = geis_subscription_flags(subscription);
2524+ }
2525+ dbus_message_iter_init_append(message, &iter);
2526+
2527+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &sub_name);
2528+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &sub_id);
2529+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &sub_flags);
2530+ _geis_dbus_marshall_subscription_filters(subscription, &iter);
2531+
2532+ return message;
2533+}
2534+
2535+
2536+/*
2537+ * Creates a %GeisSubscription from a method call message.
2538+ */
2539+GeisSubscription
2540+geis_dbus_subscription_from_create_call_message(Geis geis, DBusMessage *message)
2541+{
2542+ DBusMessageIter message_iter;
2543+ dbus_message_iter_init(message, &message_iter);
2544+
2545+ GeisString client_sub_name;
2546+ dbus_message_iter_get_basic(&message_iter, &client_sub_name);
2547+ dbus_message_iter_next(&message_iter);
2548+
2549+ dbus_int32_t client_sub_id;
2550+ dbus_message_iter_get_basic(&message_iter, &client_sub_id);
2551+ dbus_message_iter_next(&message_iter);
2552+
2553+ dbus_uint32_t client_sub_flags;
2554+ dbus_message_iter_get_basic(&message_iter, &client_sub_flags);
2555+ dbus_message_iter_next(&message_iter);
2556+
2557+ GeisSubscription subscription = NULL;
2558+ subscription = geis_subscription_new(geis, client_sub_name, client_sub_flags);
2559+ if (!subscription)
2560+ {
2561+ geis_error("error creating proxy subscription");
2562+ goto final_exit;
2563+ }
2564+ intptr_t fudge = client_sub_id;
2565+ geis_subscription_set_pdata(subscription, (GeisPointer)fudge);
2566+
2567+ int dtype = dbus_message_iter_get_arg_type(&message_iter);
2568+ if (dtype != DBUS_TYPE_ARRAY)
2569+ {
2570+ geis_error("malformed GeisSubscription message"
2571+ " (expected type %c, received type %c)",
2572+ DBUS_TYPE_ARRAY, dtype);
2573+ goto final_exit;
2574+ }
2575+
2576+ _geis_dbus_unmarshall_subscription_filters(geis, &message_iter, subscription);
2577+
2578+final_exit:
2579+ return subscription;
2580+}
2581+
2582+
2583+/*
2584+ * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method return message.
2585+ */
2586+DBusMessage *
2587+geis_dbus_subscription_create_return_message(DBusMessage *message,
2588+ GeisSubscription subscription)
2589+{
2590+ DBusMessage *reply = dbus_message_new_method_return(message);
2591+ intptr_t fudge = (intptr_t)geis_subscription_pdata(subscription);
2592+ dbus_int32_t client_sub_id = fudge;
2593+ dbus_int32_t server_sub_id = geis_subscription_id(subscription);
2594+ dbus_message_append_args(reply,
2595+ DBUS_TYPE_INT32, &client_sub_id,
2596+ DBUS_TYPE_INT32, &server_sub_id,
2597+ DBUS_TYPE_INVALID);
2598+
2599+ return reply;
2600+}
2601+
2602+
2603+/*
2604+ * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_ACTIVATE message.
2605+ */
2606+GeisBoolean
2607+geis_dbus_message_is_subscription_activate_call(DBusMessage *message)
2608+{
2609+ return dbus_message_is_method_call(message,
2610+ GEIS_DBUS_SERVICE_INTERFACE,
2611+ GEIS_DBUS_SUBSCRIPTION_ACTIVATE);
2612+}
2613+
2614+
2615+/*
2616+ * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message.
2617+ */
2618+DBusMessage *
2619+geis_dbus_subscription_activate_call_message(GeisSubscription subscription)
2620+{
2621+ DBusMessage *message = NULL;
2622+ DBusMessageIter iter;
2623+
2624+ message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
2625+ GEIS_DBUS_SERVICE_PATH,
2626+ GEIS_DBUS_SERVICE_INTERFACE,
2627+ GEIS_DBUS_SUBSCRIPTION_ACTIVATE);
2628+ dbus_message_iter_init_append(message, &iter);
2629+
2630+ dbus_int32_t subscription_id = geis_subscription_id(subscription);
2631+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &subscription_id);
2632+ _geis_dbus_marshall_subscription_filters(subscription, &iter);
2633+ return message;
2634+}
2635+
2636+
2637+/*
2638+ * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method return message.
2639+ */
2640+DBusMessage *
2641+geis_dbus_subscription_activate_return_message(DBusMessage *message,
2642+ GeisSubscription subscription)
2643+{
2644+ DBusMessage *reply = NULL;
2645+ reply = dbus_message_new_method_return(message);
2646+ dbus_int32_t subscription_id = -1;
2647+
2648+ if (subscription)
2649+ {
2650+ subscription_id = geis_subscription_id(subscription);
2651+ }
2652+ dbus_message_append_args(reply,
2653+ DBUS_TYPE_INT32, &subscription_id,
2654+ DBUS_TYPE_INVALID);
2655+ return reply;
2656+}
2657+
2658+
2659+/*
2660+ * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE message.
2661+ */
2662+GeisBoolean
2663+geis_dbus_message_is_subscription_deactivate_call(DBusMessage *message)
2664+{
2665+ return dbus_message_is_method_call(message,
2666+ GEIS_DBUS_SERVICE_INTERFACE,
2667+ GEIS_DBUS_SUBSCRIPTION_DEACTIVATE);
2668+}
2669+
2670+
2671+/*
2672+ * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message.
2673+ */
2674+DBusMessage *
2675+geis_dbus_subscription_deactivate_call_message(GeisSubscription subscription GEIS_UNUSED)
2676+{
2677+ DBusMessage *message = NULL;
2678+ message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
2679+ GEIS_DBUS_SERVICE_PATH,
2680+ GEIS_DBUS_SERVICE_INTERFACE,
2681+ GEIS_DBUS_SUBSCRIPTION_DEACTIVATE);
2682+ return message;
2683+}
2684+
2685+
2686+/**
2687+ */
2688+DBusMessage *
2689+geis_dbus_subscription_deactivate_return_message(DBusMessage *message,
2690+ GeisSubscription subscription)
2691+{
2692+ DBusMessage *reply = NULL;
2693+ reply = dbus_message_new_method_return(message);
2694+ dbus_int32_t subscription_id = geis_subscription_id(subscription);
2695+ dbus_message_append_args(reply,
2696+ DBUS_TYPE_INT32, &subscription_id,
2697+ DBUS_TYPE_INVALID);
2698+ return reply;
2699+}
2700+
2701+
2702+/*
2703+ * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DESTROY message.
2704+ */
2705+GeisBoolean
2706+geis_dbus_message_is_subscription_destroy_call(DBusMessage *message)
2707+{
2708+ return dbus_message_is_method_call(message,
2709+ GEIS_DBUS_SERVICE_INTERFACE,
2710+ GEIS_DBUS_SUBSCRIPTION_DESTROY);
2711+}
2712+
2713+
2714+/*
2715+ * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method call message.
2716+ */
2717+DBusMessage *
2718+geis_dbus_subscription_destroy_call_message(GeisSubscription subscription)
2719+{
2720+ DBusMessage *message = NULL;
2721+ message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
2722+ GEIS_DBUS_SERVICE_PATH,
2723+ GEIS_DBUS_SERVICE_INTERFACE,
2724+ GEIS_DBUS_SUBSCRIPTION_DESTROY);
2725+
2726+ dbus_int32_t server_sub_id = (intptr_t)geis_subscription_pdata(subscription);
2727+ dbus_message_append_args(message,
2728+ DBUS_TYPE_INT32, &server_sub_id,
2729+ DBUS_TYPE_INVALID);
2730+
2731+ return message;
2732+}
2733+
2734+
2735+/*
2736+ * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method return message.
2737+ */
2738+DBusMessage *
2739+geis_dbus_subscription_destroy_return_message(DBusMessage *message)
2740+{
2741+ return dbus_message_new_method_return(message);
2742+}
2743+
2744+
2745
2746=== added file 'libs/geis-dbus/geis_dbus_subscription.h'
2747--- libs/geis-dbus/geis_dbus_subscription.h 1970-01-01 00:00:00 +0000
2748+++ libs/geis-dbus/geis_dbus_subscription.h 2011-10-17 21:56:23 +0000
2749@@ -0,0 +1,206 @@
2750+/**
2751+ * @file geis_dbus_subscription.h
2752+ * @brief Interface for the GEIS DBus subscription transport.
2753+ */
2754+
2755+/*
2756+ * Copyright 2011 Canonical Ltd.
2757+ *
2758+ * This library is free software; you can redistribute it and/or modify it under
2759+ * the terms of the GNU Lesser General Public License as published by the Free
2760+ * Software Foundation; either version 3 of the License, or (at your option) any
2761+ * later version.
2762+ *
2763+ * This library is distributed in the hope that it will be useful, but WITHOUT
2764+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2765+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2766+ * details.
2767+ *
2768+ * You should have received a copy of the GNU General Public License
2769+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2770+ */
2771+#ifndef GEIS_DBUS_SUBSCRIPTION_H_
2772+#define GEIS_DBUS_SUBSCRIPTION_H_
2773+
2774+#include <dbus/dbus.h>
2775+#include "geis/geis.h"
2776+
2777+
2778+/**
2779+ * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_CREATE method call.
2780+ *
2781+ * @param[in] message A DBus message.
2782+ *
2783+ * This function is used on the server side to identify if a received message is
2784+ * a GEIS_DBUS_SUBSCRIPTION_CREATE method call.
2785+ *
2786+ * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_CREATE,
2787+ * GEIS_FALSE otherwise.
2788+ */
2789+GeisBoolean
2790+geis_dbus_message_is_subscription_create_call(DBusMessage *message);
2791+
2792+/**
2793+ * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method call message.
2794+ *
2795+ * @param[in] subscription A GEIS subscription.
2796+ *
2797+ * This function is used on the client side to create a
2798+ * GEIS_DBUS_SUBSCRIPTION_CREATE method call message from a local
2799+ * %GeisSubscription object.
2800+ *
2801+ * @returns A DBus message object.
2802+ */
2803+DBusMessage *
2804+geis_dbus_subscription_create_call_message(GeisSubscription subscription);
2805+
2806+/**
2807+ * Creates a %GeisSubscription from a GEIS_DBUS_SUBSCRIPTION_CREATE method call
2808+ * message.
2809+ *
2810+ * @param[in] geis A %Geis instance.
2811+ * @param[in] message A DBus message.
2812+ *
2813+ * This function is used on the server side to create a subscription object to
2814+ * proxy the client-side subscription object.
2815+ *
2816+ * @returns a %GeisSubscription or NULL on failure.
2817+ */
2818+GeisSubscription
2819+geis_dbus_subscription_from_create_call_message(Geis geis, DBusMessage *message);
2820+
2821+/**
2822+ * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method return message.
2823+ *
2824+ * @param[in] message The DBUs method_call message to reply to.
2825+ * @param[in] subscription A GEIS subscription.
2826+ *
2827+ * This function is used on the server side to create a response to a received
2828+ * GEIS_DBUS_SUBSCRIPTION_CREATE method call message.
2829+ *
2830+ * @returns A DBus message object.
2831+ */
2832+DBusMessage *
2833+geis_dbus_subscription_create_return_message(DBusMessage *message,
2834+ GeisSubscription subscription);
2835+
2836+/**
2837+ * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_ACTIVATE message.
2838+ *
2839+ * @param[in] message A DBus message.
2840+ *
2841+ * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_ACTIVATE,
2842+ * GEIS_FALSE otherwise.
2843+ */
2844+GeisBoolean
2845+geis_dbus_message_is_subscription_activate_call(DBusMessage *message);
2846+
2847+/**
2848+ * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message.
2849+ *
2850+ * @param[in] subscription A GEIS subscription.
2851+ *
2852+ * This function is used on the client side to create a
2853+ * GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message from a local
2854+ * %GeisSubscription object.
2855+ *
2856+ * @returns A DBus message object.
2857+ */
2858+DBusMessage *
2859+geis_dbus_subscription_activate_call_message(GeisSubscription subscription);
2860+
2861+/**
2862+ * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method return message.
2863+ *
2864+ * @param[in] message The DBUs method_call message to reply to.
2865+ * @param[in] subscription A GEIS subscription.
2866+ *
2867+ * This function is used on the server side to create a response to a received
2868+ * GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message.
2869+ *
2870+ * @returns A DBus message object.
2871+ */
2872+DBusMessage *
2873+geis_dbus_subscription_activate_return_message(DBusMessage *message,
2874+ GeisSubscription subscription);
2875+
2876+/**
2877+ * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE message.
2878+ *
2879+ * @param[in] message A DBus message.
2880+ *
2881+ * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_DEACTIVATE,
2882+ * GEIS_FALSE otherwise.
2883+ */
2884+GeisBoolean
2885+geis_dbus_message_is_subscription_deactivate_call(DBusMessage *message);
2886+
2887+/**
2888+ * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method return message.
2889+ *
2890+ * @param[in] message The DBUs method_call message to reply to.
2891+ * @param[in] subscription A GEIS subscription.
2892+ *
2893+ * This function is used on the server side to create a response to a received
2894+ * GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message.
2895+ *
2896+ * @returns A DBus message object.
2897+ */
2898+DBusMessage *
2899+geis_dbus_subscription_deactivate_return_message(DBusMessage *message,
2900+ GeisSubscription subscription);
2901+
2902+/**
2903+ * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message.
2904+ *
2905+ * @param[in] subscription A GEIS subscription.
2906+ *
2907+ * This function is used on the client side to create a
2908+ * GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message from a local
2909+ * %GeisSubscription object.
2910+ *
2911+ * @returns A DBus message object.
2912+ */
2913+DBusMessage *
2914+geis_dbus_subscription_deactivate_call_message(GeisSubscription subscription);
2915+
2916+/**
2917+ * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DESTROY message.
2918+ *
2919+ * @param[in] message A DBus message.
2920+ *
2921+ * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_DESTROY,
2922+ * GEIS_FALSE otherwise.
2923+ */
2924+GeisBoolean
2925+geis_dbus_message_is_subscription_destroy_call(DBusMessage *message);
2926+
2927+/**
2928+ * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method call message.
2929+ *
2930+ * @param[in] subscription A GEIS subscription.
2931+ *
2932+ * This function is used on the client side to create a
2933+ * GEIS_DBUS_SUBSCRIPTION_DESTROY method call message from a local
2934+ * %GeisSubscription object.
2935+ *
2936+ * @returns A DBus message object.
2937+ */
2938+DBusMessage *
2939+geis_dbus_subscription_destroy_call_message(GeisSubscription subscription);
2940+
2941+/**
2942+ * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method return message.
2943+ *
2944+ * @param[in] message The DBUs method_call message to reply to.
2945+ *
2946+ * This function is used on the server side to create a response to a received
2947+ * GEIS_DBUS_SUBSCRIPTION_DESTROY method call message.
2948+ *
2949+ * @returns A DBus message object.
2950+ */
2951+DBusMessage *
2952+geis_dbus_subscription_destroy_return_message(DBusMessage *message);
2953+
2954+
2955+#endif /* GEIS_DBUS_SUBSCRIPTION_H_ */
2956
2957=== modified file 'libutouch-geis/Makefile.am'
2958--- libutouch-geis/Makefile.am 2011-08-17 15:48:51 +0000
2959+++ libutouch-geis/Makefile.am 2011-10-17 21:56:23 +0000
2960@@ -39,6 +39,7 @@
2961 geis_event.h geis_event.c \
2962 geis_event_queue.h geis_event_queue.c \
2963 geis_filter.h geis_filter.c \
2964+ geis_filterable.h geis_filterable.c \
2965 geis_filter_term.h geis_filter_term.c \
2966 geis_frame.h geis_frame.c \
2967 geis_gesture_flick.h geis_gesture_flick.c \
2968@@ -56,6 +57,8 @@
2969 -I$(top_srcdir) \
2970 -I$(top_srcdir)/include \
2971 -I$(srcdir)/backend \
2972+ -I$(top_srcdir)/libs/geis-dbus \
2973+ $(DBUS_CFLAGS) \
2974 $(GRAIL_CFLAGS)
2975
2976 libutouch_geis_la_LDFLAGS = \
2977@@ -66,8 +69,10 @@
2978
2979 libutouch_geis_la_LIBADD = \
2980 ${builddir}/backend/test_fixture/libutouch-geis-test-fixture.la \
2981+ ${builddir}/backend/dbus/libutouch-geis-dbus-backend.la \
2982 ${builddir}/backend/xcb/libutouch-geis-xcb-backend.la \
2983 ${builddir}/server/libutouch-geis-dbus-server.la \
2984+ $(top_builddir)/libs/geis-dbus/libgeis-dbus.la \
2985 $(top_builddir)/libs/xcb/libxcb-gesture.la
2986
2987 EXTRA_DIST = $(version_script)
2988
2989=== modified file 'libutouch-geis/backend/Makefile.am'
2990--- libutouch-geis/backend/Makefile.am 2011-01-17 14:58:27 +0000
2991+++ libutouch-geis/backend/Makefile.am 2011-10-17 21:56:23 +0000
2992@@ -19,5 +19,5 @@
2993 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2994 #
2995
2996-SUBDIRS = test_fixture xcb
2997+SUBDIRS = test_fixture xcb dbus
2998
2999
3000=== added directory 'libutouch-geis/backend/dbus'
3001=== added file 'libutouch-geis/backend/dbus/Makefile.am'
3002--- libutouch-geis/backend/dbus/Makefile.am 1970-01-01 00:00:00 +0000
3003+++ libutouch-geis/backend/dbus/Makefile.am 2011-10-17 21:56:23 +0000
3004@@ -0,0 +1,34 @@
3005+#
3006+# @file libutouch-geis/backend/xcb/Makefile.am
3007+# @brief automake recipe for the uTouch GEIS v2.0 XCB back end
3008+#
3009+# Copyright 2011 Canonical, Ltd.
3010+#
3011+# This file is part of the utouch-geis library. This library is free software;
3012+# you can redistribute it and/or modify it under the terms of the GNU Lesser
3013+# General Public License as published by the Free Software Foundation; either
3014+# version 3 of the License, or (at your option) any later version.
3015+#
3016+# This library is distributed in the hope that it will be useful, but WITHOUT
3017+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3018+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
3019+# details.
3020+#
3021+# You should have received a copy of the GNU General Public License
3022+# along with this program. If not, see <http://www.gnu.org/licenses/
3023+#
3024+
3025+noinst_LTLIBRARIES = libutouch-geis-dbus-backend.la
3026+
3027+libutouch_geis_dbus_backend_la_SOURCES = \
3028+ geis_dbus_backend.c \
3029+ geis_dbus_client.h geis_dbus_client.c \
3030+ geis_dbus_locator.h geis_dbus_locator.c
3031+
3032+libutouch_geis_dbus_backend_la_CPPFLAGS = \
3033+ -I$(top_srcdir) \
3034+ -I$(top_srcdir)/libs/geis-dbus \
3035+ -I$(top_srcdir)/include \
3036+ -I$(top_srcdir)/libutouch-geis \
3037+ $(DBUS_CFLAGS)
3038+
3039
3040=== added file 'libutouch-geis/backend/dbus/geis_dbus_backend.c'
3041--- libutouch-geis/backend/dbus/geis_dbus_backend.c 1970-01-01 00:00:00 +0000
3042+++ libutouch-geis/backend/dbus/geis_dbus_backend.c 2011-10-17 21:56:23 +0000
3043@@ -0,0 +1,248 @@
3044+/**
3045+ * @file geis_dbus_backend.c
3046+ * @brief GEIS DBus client back end
3047+ */
3048+
3049+/*
3050+ * Copyright 2011 Canonical Ltd.
3051+ *
3052+ * This library is free software; you can redistribute it and/or modify it under
3053+ * the terms of the GNU Lesser General Public License as published by the Free
3054+ * Software Foundation; either version 3 of the License, or (at your option) any
3055+ * later version.
3056+ *
3057+ * This library is distributed in the hope that it will be useful, but WITHOUT
3058+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3059+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
3060+ * details.
3061+ *
3062+ * You should have received a copy of the GNU General Public License
3063+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3064+ */
3065+#include "geis_config.h"
3066+#include "geis_backend.h"
3067+#include "geis_backend_protected.h"
3068+
3069+#include "geis_dbus_client.h"
3070+#include "geis_event.h"
3071+#include "geis_logging.h"
3072+#include "geis_private.h"
3073+
3074+
3075+/**
3076+ * @addtogroup geis_backend_dbus GEIS DBus Back End
3077+ * @ingroup geis_backends
3078+ *
3079+ * A GEIS Back End that is a DBus client, for connecting to a single central
3080+ * GEIS service offering data over the DBus.
3081+ *
3082+ * @{
3083+ */
3084+
3085+/** The opaque DBus Back End type. */
3086+typedef struct GeisDBusBackend *GeisDBusBackend;
3087+
3088+/** The less opaque DBus Back End structure. */
3089+struct GeisDBusBackend
3090+{
3091+ Geis geis;
3092+ GeisDBusClient dbus_client;
3093+};
3094+
3095+/** The DBus Back End token type */
3096+typedef struct GeisDBusToken
3097+{
3098+ struct GeisBackendToken base;
3099+ GeisDBusBackend be;
3100+} *GeisDBusToken;
3101+
3102+
3103+/**
3104+ * Converts from a GeisBackendToken to an XcbBackendToken.
3105+ */
3106+static inline GeisDBusToken
3107+_geis_dbus_token_from_geis_token(GeisBackendToken gbt)
3108+{
3109+ return (GeisDBusToken)gbt;
3110+}
3111+
3112+
3113+/**
3114+ * Allocates memory for a token from a pool.
3115+ */
3116+static GeisDBusToken
3117+_geis_dbus_token_allocate(void)
3118+{
3119+ return calloc(1, sizeof(struct GeisDBusToken));
3120+}
3121+
3122+
3123+/**
3124+ * Returns memory for a token to a pool.
3125+ */
3126+static void
3127+_geis_dbus_token_deallocate(GeisDBusToken gdt)
3128+{
3129+ free(gdt);
3130+}
3131+
3132+
3133+/**
3134+ * Deep-copy-constructs a token.
3135+ */
3136+static GeisBackendToken
3137+_geis_dbus_token_clone(GeisBackendToken original)
3138+{
3139+ return original;
3140+}
3141+
3142+
3143+/**
3144+ * Releases resources for a token.
3145+ *
3146+ * @param[in] token A %GeisDBusToken.
3147+ */
3148+static void
3149+_geis_dbus_token_finalize(GeisBackendToken token GEIS_UNUSED)
3150+{
3151+}
3152+
3153+
3154+/**
3155+ * Composes one token onto another.
3156+ *
3157+ * @param[in,out] lhs
3158+ * @param[in] rhs
3159+ */
3160+static void
3161+_geis_dbus_token_compose(GeisBackendToken lhs GEIS_UNUSED,
3162+ GeisBackendToken rhs GEIS_UNUSED)
3163+{
3164+}
3165+
3166+
3167+/**
3168+ * Activates a DBus back end token.
3169+ *
3170+ * @param[in] token A %GeisDBusToken.
3171+ * @param[in] subscription The subscrition the token will be activated on.
3172+ *
3173+ * Sends a request to the server to activate a subscription with the tokenized
3174+ * content.
3175+ *
3176+ * @returns GEIS_STATUS_SUCCESS.
3177+ */
3178+static GeisStatus
3179+_geis_dbus_token_activate(GeisBackendToken token, GeisSubscription subscription)
3180+{
3181+ GeisDBusToken gdt = _geis_dbus_token_from_geis_token(token);
3182+ geis_dbus_client_subscribe(gdt->be->dbus_client, subscription);
3183+ return GEIS_STATUS_SUCCESS;
3184+}
3185+
3186+
3187+/**
3188+ * Deactivates a DBus back end token.
3189+ *
3190+ * @param[in] token A %GeisDBusToken.
3191+ */
3192+static GeisStatus
3193+_geis_dbus_token_deactivate(GeisBackendToken token, GeisSubscription subscription)
3194+{
3195+ GeisDBusToken gdt = _geis_dbus_token_from_geis_token(token);
3196+ geis_dbus_client_unsubscribe(gdt->be->dbus_client, subscription);
3197+ _geis_dbus_token_deallocate(gdt);
3198+ return GEIS_STATUS_UNKNOWN_ERROR;
3199+}
3200+
3201+
3202+static struct GeisBackendTokenVtable _token_vtbl = {
3203+ _geis_dbus_token_clone,
3204+ _geis_dbus_token_finalize,
3205+ _geis_dbus_token_compose,
3206+ _geis_dbus_token_activate,
3207+ _geis_dbus_token_deactivate,
3208+};
3209+
3210+
3211+/**
3212+ * Constructs a DBus back end.
3213+ *
3214+ * @param[in] mem
3215+ * @param[in] geis
3216+ */
3217+static void
3218+_geis_dbus_backend_construct(void *mem, Geis geis)
3219+{
3220+ GeisDBusBackend gdb = (GeisDBusBackend)mem;
3221+ gdb->geis = geis;
3222+
3223+ gdb->dbus_client = geis_dbus_client_new(geis);
3224+ if (!gdb->dbus_client)
3225+ {
3226+ geis_error("error creating GEIS DBus client");
3227+ goto final_exit;
3228+ }
3229+
3230+final_exit:
3231+ return;
3232+}
3233+
3234+
3235+/**
3236+ * Deconstructs a DBus back end.
3237+ *
3238+ * @param[in] be A %GeisDBusBackend.
3239+ */
3240+static void
3241+_geis_dbus_backend_finalize(GeisBackend be)
3242+{
3243+ GeisDBusBackend gdb = (GeisDBusBackend)be;
3244+ geis_dbus_client_delete(gdb->dbus_client);
3245+}
3246+
3247+
3248+/**
3249+ * Creates DBus-back-end-specific back end token.
3250+ */
3251+static GeisBackendToken
3252+_geis_dbus_backend_create_token(GeisBackend be,
3253+ GeisBackendTokenInitState init_state GEIS_UNUSED)
3254+{
3255+ GeisDBusBackend gdb = (GeisDBusBackend)be;
3256+ GeisDBusToken token = _geis_dbus_token_allocate();
3257+ if (token)
3258+ {
3259+ token->base.vtbl = &_token_vtbl;
3260+ token->be = gdb;
3261+ }
3262+ return (GeisBackendToken)token;
3263+}
3264+
3265+
3266+static struct GeisBackendVtable gdb_vtbl = {
3267+ _geis_dbus_backend_construct,
3268+ _geis_dbus_backend_finalize,
3269+ _geis_dbus_backend_create_token,
3270+};
3271+
3272+
3273+/**
3274+ * Registers the back end with the GEIS back end registry.
3275+ */
3276+static void __attribute__((constructor))
3277+_register_dbus_backend(void)
3278+{
3279+ geis_register_backend(GEIS_INIT_UTOUCH_DBUS_BACKEND,
3280+ sizeof(struct GeisDBusBackend),
3281+ &gdb_vtbl);
3282+}
3283+
3284+
3285+/** A dummy routine to force linkage of this module without dlopening it */
3286+void
3287+geis_include_dbus_backend(void)
3288+{
3289+}
3290+
3291+/** @} */
3292
3293=== added file 'libutouch-geis/backend/dbus/geis_dbus_client.c'
3294--- libutouch-geis/backend/dbus/geis_dbus_client.c 1970-01-01 00:00:00 +0000
3295+++ libutouch-geis/backend/dbus/geis_dbus_client.c 2011-10-17 21:56:23 +0000
3296@@ -0,0 +1,685 @@
3297+/**
3298+ * @file geis_dbus_client.c
3299+ * @brief Implementations of the GEIS DBus client.
3300+ */
3301+
3302+/*
3303+ * Copyright 2011 Canonical Ltd.
3304+ *
3305+ * This library is free software; you can redistribute it and/or modify it under
3306+ * the terms of the GNU Lesser General Public License as published by the Free
3307+ * Software Foundation; either version 3 of the License, or (at your option) any
3308+ * later version.
3309+ *
3310+ * This library is distributed in the hope that it will be useful, but WITHOUT
3311+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3312+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
3313+ * details.
3314+ *
3315+ * You should have received a copy of the GNU General Public License
3316+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3317+ */
3318+#include "geis_config.h"
3319+#include "geis_dbus_client.h"
3320+
3321+#include "geis_dbus.h"
3322+#include "geis_dbus_class.h"
3323+#include "geis_dbus_device.h"
3324+#include "geis_dbus_gesture_event.h"
3325+#include "geis_dbus_locator.h"
3326+#include "geis_dbus_region.h"
3327+#include "geis_dbus_subscription.h"
3328+#include "geis_event.h"
3329+#include "geis_logging.h"
3330+#include "geis_private.h"
3331+#include <stdio.h>
3332+#include <stdlib.h>
3333+
3334+
3335+typedef enum GeisDBusClientState
3336+{
3337+ GEIS_DBUS_CLIENT_DISCONNECTED, /* no server available */
3338+ GEIS_DBUS_CLIENT_INITIALIZING, /* server connected, client initializing */
3339+ GEIS_DBUS_CLIENT_CONNECTING, /* server connected, not initialized */
3340+ GEIS_DBUS_CLIENT_CONNECTED /* server connected, all systems go */
3341+} GeisDBusClientState;
3342+
3343+
3344+struct GeisDBusClient
3345+{
3346+ Geis geis;
3347+ GeisDBusDispatcher dispatcher;
3348+ GeisDBusLocator locator;
3349+ GeisDBusClientState state;
3350+ DBusConnection *connection;
3351+ GeisSubBag subscription_bag;
3352+};
3353+
3354+
3355+/**
3356+ * Handles a device-available message from the server.
3357+ *
3358+ * @param[in] client A %GeisDBusClient.
3359+ * @param[in] message The %DBusMessage.
3360+ */
3361+static void
3362+_client_device_available(GeisDBusClient client, DBusMessage *message)
3363+{
3364+ GeisDevice device = geis_dbus_device_device_from_available_message(message);
3365+ if (device)
3366+ {
3367+ geis_register_device(client->geis, device, 0, NULL);
3368+ }
3369+ else
3370+ {
3371+ geis_error("no device received from remote back end");
3372+ }
3373+}
3374+
3375+
3376+/**
3377+ * Handles a device-unavailable message from the server.
3378+ *
3379+ * @param[in] client A %GeisDBusClient.
3380+ * @param[in] message The %DBusMessage.
3381+ */
3382+static void
3383+_client_device_unavailable(GeisDBusClient client, DBusMessage *message)
3384+{
3385+ GeisDevice device = geis_dbus_device_device_from_unavailable_message(message);
3386+ if (device)
3387+ {
3388+ geis_unregister_device(client->geis, device);
3389+ }
3390+ else
3391+ {
3392+ geis_error("no device received from remote back end");
3393+ }
3394+}
3395+
3396+
3397+/**
3398+ * Handles a class-available message from the server.
3399+ *
3400+ * @param[in] client A %GeisDBusClient.
3401+ * @param[in] message The %DBusMessage.
3402+ */
3403+static void
3404+_client_class_available(GeisDBusClient client, DBusMessage *message)
3405+{
3406+ GeisGestureClass gesture_class;
3407+
3408+ gesture_class = geis_dbus_class_class_from_available_message(message);
3409+ if (gesture_class)
3410+ {
3411+ geis_register_gesture_class(client->geis, gesture_class, 0, NULL);
3412+ }
3413+ else
3414+ {
3415+ geis_error("no gesture class received from remote back end");
3416+ }
3417+}
3418+
3419+
3420+/**
3421+ * Handles a region-available message from the server.
3422+ *
3423+ * @param[in] client A %GeisDBusClient.
3424+ * @param[in] message The %DBusMessage.
3425+ */
3426+static void
3427+_client_region_available(GeisDBusClient client, DBusMessage *message)
3428+{
3429+ GeisFilterableAttribute attr;
3430+
3431+ attr = geis_dbus_region_from_region_available_message(message);
3432+ if (attr)
3433+ {
3434+ attr->add_term_callback = 0;
3435+ attr->add_term_context = 0;
3436+ geis_register_region(client->geis, NULL, 1, attr);
3437+ }
3438+ else
3439+ {
3440+ geis_error("no region attr received from remote back end");
3441+ }
3442+}
3443+
3444+
3445+/**
3446+ * Handles a class-unavailable message from the server.
3447+ *
3448+ * @param[in] client A %GeisDBusClient.
3449+ * @param[in] message The %DBusMessage.
3450+ */
3451+static void
3452+_client_gesture_event(GeisDBusClient client, DBusMessage *message)
3453+{
3454+ GeisEvent event = geis_dbus_gesture_event_from_message(message);
3455+ if (!event)
3456+ {
3457+ geis_error("no gesture event received from remote back end");
3458+ }
3459+ else
3460+ {
3461+ geis_post_event(client->geis, event);
3462+ }
3463+}
3464+
3465+
3466+/**
3467+ * Processes an subscription-activate reply from the server.
3468+ *
3469+ * @param[in] pending A DBusPendingCall object.
3470+ * @param[in] user_data The %GeisDBusClient object.
3471+ */
3472+static void
3473+_geis_dbus_client_activate_reply(DBusPendingCall *pending, void *user_data)
3474+{
3475+ GeisDBusClient client GEIS_UNUSED = (GeisDBusClient)user_data;
3476+ DBusMessage *reply = dbus_pending_call_steal_reply(pending);
3477+
3478+ if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply))
3479+ {
3480+ const char *s = NULL;
3481+ dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID);
3482+ geis_error("error %s: %s", dbus_message_get_error_name(reply), s);
3483+ }
3484+}
3485+
3486+
3487+/**
3488+ * Processes a subscription-create reply from the server.
3489+ *
3490+ * @param[in] pending A DBusPendingCall object.
3491+ * @param[in] user_data The %GeisDBusClient object.
3492+ */
3493+static void
3494+_geis_dbus_client_subscribe_reply(DBusPendingCall *pending, void *user_data)
3495+{
3496+ GeisDBusClient client = (GeisDBusClient)user_data;
3497+ DBusMessage *reply = dbus_pending_call_steal_reply(pending);
3498+
3499+ if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply))
3500+ {
3501+ const char *s = NULL;
3502+ dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID);
3503+ geis_error("error %s: %s", dbus_message_get_error_name(reply), s);
3504+ }
3505+ else
3506+ {
3507+ DBusMessage *msg;
3508+ DBusPendingCall *pending;
3509+ DBusError error = DBUS_ERROR_INIT;
3510+ dbus_int32_t client_sub_id;
3511+ dbus_int32_t server_sub_id;
3512+ GeisSubscription subscription;
3513+
3514+ dbus_message_get_args(reply,
3515+ &error,
3516+ DBUS_TYPE_INT32, &client_sub_id,
3517+ DBUS_TYPE_INT32, &server_sub_id,
3518+ DBUS_TYPE_INVALID);
3519+ if (dbus_error_is_set(&error))
3520+ {
3521+ geis_error("error %s: %s", error.name, error.message);
3522+ dbus_error_free(&error);
3523+ }
3524+
3525+ subscription = geis_subscription_bag_find(client->subscription_bag,
3526+ client_sub_id);
3527+ if (!subscription)
3528+ {
3529+ geis_error("invalid client subcription id %d returned from server",
3530+ client_sub_id);
3531+ }
3532+ else
3533+ {
3534+ geis_subscription_set_pdata(subscription, (GeisPointer)(intptr_t)server_sub_id);
3535+
3536+ msg = geis_dbus_subscription_activate_call_message(subscription);
3537+ dbus_connection_send_with_reply(client->connection, msg, &pending, -1);
3538+ dbus_message_unref(msg);
3539+ if (!pending)
3540+ {
3541+ geis_error("error sending DBus CreateSubscription method call");
3542+ }
3543+ else
3544+ {
3545+ dbus_pending_call_set_notify(pending,
3546+ _geis_dbus_client_activate_reply,
3547+ client, 0);
3548+ }
3549+ }
3550+ }
3551+
3552+ dbus_message_unref(reply);
3553+ dbus_pending_call_unref(pending);
3554+}
3555+
3556+
3557+/**
3558+ * Processes a deactivate-subscription reply from the server.
3559+ *
3560+ * @param[in] pending A DBusPendingCall object.
3561+ * @param[in] user_data The %GeisDBusClient object.
3562+ */
3563+static void
3564+_geis_dbus_client_unsubscribe_reply(DBusPendingCall *pending, void *user_data)
3565+{
3566+ GeisDBusClient client GEIS_UNUSED = (GeisDBusClient)user_data;
3567+ DBusMessage *reply = dbus_pending_call_steal_reply(pending);
3568+
3569+ if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply))
3570+ {
3571+ const char *s = NULL;
3572+ dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID);
3573+ geis_error("error %s: %s", dbus_message_get_error_name(reply), s);
3574+ }
3575+ else
3576+ {
3577+ geis_warning("signature=\"%s\"", dbus_message_get_signature(reply));
3578+ geis_warning("path=\"%s\"", dbus_message_get_path(reply));
3579+ geis_warning("interface=\"%s\"", dbus_message_get_interface(reply));
3580+ geis_warning("member=\"%s\"", dbus_message_get_member(reply));
3581+ }
3582+
3583+ dbus_message_unref(reply);
3584+ dbus_pending_call_unref(pending);
3585+}
3586+
3587+
3588+/**
3589+ * Creates a remote subscription.
3590+ */
3591+void
3592+_dbus_client_subscribe(GeisDBusClient client,
3593+ GeisSubscription subscription)
3594+{
3595+ DBusPendingCall *pending_return;
3596+
3597+ GeisSubscription sub = geis_subscription_bag_find(client->subscription_bag,
3598+ geis_subscription_id(subscription));
3599+ if (sub && geis_subscription_pdata(sub))
3600+ {
3601+ geis_warning("subscription already activated!");
3602+ }
3603+ else
3604+ {
3605+ DBusMessage *msg = geis_dbus_subscription_create_call_message(subscription);
3606+ dbus_connection_send_with_reply(client->connection, msg, &pending_return, -1);
3607+ dbus_message_unref(msg);
3608+ if (!pending_return)
3609+ {
3610+ geis_error("error sending DBus CreateSubscription method call");
3611+ }
3612+ else
3613+ {
3614+ dbus_pending_call_set_notify(pending_return,
3615+ _geis_dbus_client_subscribe_reply,
3616+ client, 0);
3617+ }
3618+ }
3619+}
3620+
3621+
3622+/**
3623+ * Re-subscribes all existing sibscriptions when the server appears or
3624+ * reappears.
3625+ */
3626+void
3627+_dbus_client_resubscribe_all(GeisDBusClient client)
3628+{
3629+ GeisSubBagIterator it;
3630+ for (it = geis_subscription_bag_begin(client->subscription_bag);
3631+ it != geis_subscription_bag_end(client->subscription_bag);
3632+ it = geis_subscription_bag_iterator_next(client->subscription_bag, it))
3633+ {
3634+ geis_subscription_set_pdata(*it, 0);
3635+ _dbus_client_subscribe(client, *it);
3636+ }
3637+}
3638+
3639+
3640+/**
3641+ * The DBus message dispatch function for the GEIS DBus client.
3642+ *
3643+ * @param[in] connection The %GeisDBusClient DBus connection.
3644+ * @param[in] message The DBus message received.
3645+ * @param[in] user_data The %GeisDBusClient.
3646+ */
3647+static DBusHandlerResult
3648+_geis_dbus_client_message_handler(DBusConnection *connection GEIS_UNUSED,
3649+ DBusMessage *message,
3650+ void *user_data)
3651+{
3652+ DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3653+ GeisDBusClient client = (GeisDBusClient)user_data;
3654+ int type = dbus_message_get_type(message);
3655+
3656+ if (dbus_message_is_signal(message,
3657+ DBUS_INTERFACE_LOCAL,
3658+ "Disconnected"))
3659+ {
3660+ geis_warning("server disconnected?");
3661+ result = DBUS_HANDLER_RESULT_HANDLED;
3662+ }
3663+ else if (dbus_message_is_signal(message,
3664+ GEIS_DBUS_SERVICE_INTERFACE,
3665+ GEIS_DBUS_DEVICE_AVAILABLE))
3666+ {
3667+ _client_device_available(client, message);
3668+ result = DBUS_HANDLER_RESULT_HANDLED;
3669+ }
3670+ else if (dbus_message_is_signal(message,
3671+ GEIS_DBUS_SERVICE_INTERFACE,
3672+ GEIS_DBUS_DEVICE_UNAVAILABLE))
3673+
3674+ {
3675+ _client_device_unavailable(client, message);
3676+ result = DBUS_HANDLER_RESULT_HANDLED;
3677+ }
3678+ else if (dbus_message_is_signal(message,
3679+ GEIS_DBUS_SERVICE_INTERFACE,
3680+ GEIS_DBUS_CLASS_AVAILABLE))
3681+ {
3682+ _client_class_available(client, message);
3683+ result = DBUS_HANDLER_RESULT_HANDLED;
3684+ }
3685+ else if (dbus_message_is_signal(message,
3686+ GEIS_DBUS_SERVICE_INTERFACE,
3687+ GEIS_DBUS_REGION_AVAILABLE))
3688+ {
3689+ _client_region_available(client, message);
3690+ result = DBUS_HANDLER_RESULT_HANDLED;
3691+ }
3692+ else if (dbus_message_is_signal(message,
3693+ GEIS_DBUS_SERVICE_INTERFACE,
3694+ GEIS_DBUS_INIT_COMPLETE))
3695+ {
3696+ if (client->state == GEIS_DBUS_CLIENT_INITIALIZING)
3697+ {
3698+ geis_post_event(client->geis, geis_event_new(GEIS_EVENT_INIT_COMPLETE));
3699+ }
3700+ client->state = GEIS_DBUS_CLIENT_CONNECTED;
3701+ _dbus_client_resubscribe_all(client);
3702+ result = DBUS_HANDLER_RESULT_HANDLED;
3703+ }
3704+ else if (geis_dbus_message_is_gesture_event(message))
3705+ {
3706+ _client_gesture_event(client, message);
3707+ result = DBUS_HANDLER_RESULT_HANDLED;
3708+ }
3709+ else if (type == DBUS_MESSAGE_TYPE_ERROR)
3710+ {
3711+ const char *str = NULL;
3712+ dbus_message_get_args(message, NULL,
3713+ DBUS_TYPE_STRING, &str,
3714+ DBUS_TYPE_INVALID);
3715+ geis_warning("error %s: %s", dbus_message_get_error_name(message), str);
3716+ }
3717+ else
3718+ {
3719+ geis_warning("unhandled DBus %s received:",
3720+ dbus_message_type_to_string(dbus_message_get_type(message)));
3721+ geis_warning(" signature=\"%s\"", dbus_message_get_signature(message));
3722+ geis_warning(" sender=\"%s\"", dbus_message_get_sender(message));
3723+ geis_warning(" path=\"%s\"",
3724+ dbus_message_get_path(message) ?
3725+ dbus_message_get_path(message) :
3726+ "(no path)");
3727+ geis_warning(" interface=\"%s\"",
3728+ dbus_message_get_interface(message) ?
3729+ dbus_message_get_interface(message) :
3730+ "(no interface)");
3731+ geis_warning(" member=\"%s\"",
3732+ dbus_message_get_member(message) ?
3733+ dbus_message_get_member(message) :
3734+ "(no member)");
3735+ }
3736+ return result;
3737+}
3738+
3739+
3740+/**
3741+ * Adds the client watches to the dispatcher watch list.
3742+ *
3743+ * @param[in] watch A %DBusWatch.
3744+ * @param[in] data The %GeisDBusClientProxy.
3745+ */
3746+static dbus_bool_t
3747+_client_add_watch(DBusWatch *watch, void *data)
3748+{
3749+ dbus_bool_t status = TRUE;
3750+ GeisDBusClient client = (GeisDBusClient)data;
3751+
3752+ geis_dbus_dispatcher_register(client->dispatcher, client->connection, watch);
3753+ return status;
3754+}
3755+
3756+
3757+/**
3758+ * Toggles the enabled/disabled status of the client watches.
3759+ *
3760+ * @param[in] watch A %DBusWatch.
3761+ * @param[in] data The %GeisDBusClientProxy.
3762+ */
3763+static void
3764+_client_toggle_watch(DBusWatch *watch, void *data)
3765+{
3766+ GeisDBusClient client = (GeisDBusClient)data;
3767+
3768+ geis_dbus_dispatcher_toggle_watch(client->dispatcher, watch);
3769+}
3770+
3771+
3772+/**
3773+ * Removes the client watches from the dispatcher watch list.
3774+ *
3775+ * @param[in] watch A %DBusWatch.
3776+ * @param[in] data The %GeisDBusClientProxy.
3777+ */
3778+static void
3779+_client_remove_watch(DBusWatch *watch, void *data)
3780+{
3781+ GeisDBusClient client = (GeisDBusClient)data;
3782+
3783+ geis_dbus_dispatcher_unregister(client->dispatcher, watch);
3784+}
3785+
3786+
3787+/**
3788+ * Connects to the GEIS server once an address is located.
3789+ *
3790+ * @param[in] client A %GeisDBusClient object.
3791+ * @param[in] address The address of the server.
3792+ */
3793+static void
3794+_client_connect(GeisDBusClient client, const char *address)
3795+{
3796+ geis_debug("server address=\"%s\"", address);
3797+ DBusError error = DBUS_ERROR_INIT;
3798+ client->connection = dbus_connection_open(address, &error);
3799+ if (!client->connection || dbus_error_is_set(&error))
3800+ {
3801+ char msg[512];
3802+ snprintf(msg, sizeof(msg), "error %s connecting to server at address %s: %s",
3803+ error.name, address, error.message);
3804+ geis_error("%s", msg);
3805+ dbus_error_free(&error);
3806+ goto final_exit;
3807+ }
3808+
3809+ /* Integrate with the app event loop via the GEIS multiplexor. */
3810+ dbus_connection_set_watch_functions(client->connection,
3811+ _client_add_watch,
3812+ _client_remove_watch,
3813+ _client_toggle_watch,
3814+ client, 0);
3815+
3816+ /* Install a handler for any and all messages. */
3817+ dbus_connection_add_filter(client->connection,
3818+ _geis_dbus_client_message_handler,
3819+ client, 0);
3820+ if (client->state != GEIS_DBUS_CLIENT_INITIALIZING)
3821+ {
3822+ client->state = GEIS_DBUS_CLIENT_CONNECTING;
3823+ }
3824+
3825+final_exit:
3826+ return;
3827+}
3828+
3829+
3830+/*
3831+ * Creates a new GeisDBusClient.
3832+ */
3833+GeisDBusClient
3834+geis_dbus_client_new(Geis geis)
3835+{
3836+ GeisDBusClient client = calloc(1, sizeof(struct GeisDBusClient));
3837+ if (!client)
3838+ {
3839+ goto final_exit;
3840+ }
3841+
3842+ client->geis = geis;
3843+ client->state = GEIS_DBUS_CLIENT_INITIALIZING;
3844+
3845+ client->dispatcher = geis_dbus_dispatcher_new(geis);
3846+ if (!client->dispatcher)
3847+ {
3848+ goto unwind_client;
3849+ }
3850+
3851+ client->locator = geis_dbus_locator_new(client);
3852+ if (!client->locator)
3853+ {
3854+ goto unwind_dispatcher;
3855+ }
3856+
3857+ client->subscription_bag = geis_subscription_bag_new(1);
3858+ if (!client->subscription_bag)
3859+ {
3860+ goto unwind_locator;
3861+ }
3862+
3863+ goto final_exit;
3864+
3865+unwind_locator:
3866+ geis_dbus_locator_delete(client->locator);
3867+unwind_dispatcher:
3868+ geis_dbus_dispatcher_delete(client->dispatcher);
3869+unwind_client:
3870+ free(client);
3871+ client = NULL;
3872+final_exit:
3873+ return client;
3874+}
3875+
3876+
3877+/*
3878+ * Destroys a GeisDBusClient.
3879+ */
3880+void
3881+geis_dbus_client_delete(GeisDBusClient client)
3882+{
3883+ geis_subscription_bag_delete(client->subscription_bag);
3884+ geis_dbus_locator_delete(client->locator);
3885+ if (client->connection)
3886+ {
3887+ dbus_connection_unref(client->connection);
3888+ }
3889+ geis_dbus_dispatcher_delete(client->dispatcher);
3890+ free(client);
3891+}
3892+
3893+
3894+/*
3895+ * Gets the client dispatcher.
3896+ */
3897+GeisDBusDispatcher
3898+geis_dbus_client_dispatcher(GeisDBusClient client)
3899+{
3900+ return client->dispatcher;
3901+}
3902+
3903+
3904+/*
3905+ * Signals the client the server has been located.
3906+ */
3907+void
3908+geis_dbus_client_server_located(GeisDBusClient client)
3909+{
3910+ _client_connect(client, geis_dbus_locator_server_address(client->locator));
3911+}
3912+
3913+
3914+/*
3915+ * Signals the client the server has been dislocated.
3916+ */
3917+void
3918+geis_dbus_client_server_dislocated(GeisDBusClient client)
3919+{
3920+ GeisEvent event = geis_event_new(GEIS_EVENT_ERROR);
3921+ client->state = GEIS_DBUS_CLIENT_DISCONNECTED;
3922+ geis_post_event(client->geis, event);
3923+}
3924+
3925+
3926+/*
3927+ * Requests a subscription on the remote end.
3928+ */
3929+GeisStatus
3930+geis_dbus_client_subscribe(GeisDBusClient client,
3931+ GeisSubscription subscription)
3932+{
3933+ GeisStatus status = GEIS_STATUS_SUCCESS;
3934+
3935+ if (client->state == GEIS_DBUS_CLIENT_CONNECTED)
3936+ {
3937+ _dbus_client_subscribe(client, subscription);
3938+ }
3939+ geis_subscription_bag_insert(client->subscription_bag, subscription);
3940+
3941+ return status;
3942+}
3943+
3944+
3945+/*
3946+ * Destroys a subscription on the remote end.
3947+ */
3948+GeisStatus
3949+geis_dbus_client_unsubscribe(GeisDBusClient client,
3950+ GeisSubscription subscription)
3951+{
3952+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
3953+ if (geis_subscription_bag_find(client->subscription_bag,
3954+ geis_subscription_id(subscription)))
3955+ {
3956+ DBusMessage *msg;
3957+ DBusPendingCall *pending_return;
3958+
3959+ msg = geis_dbus_subscription_destroy_call_message(subscription);
3960+ dbus_connection_send_with_reply(client->connection, msg, &pending_return, -1);
3961+ dbus_message_unref(msg);
3962+ if (!pending_return)
3963+ {
3964+ geis_error("error sending DBus CreateSubscription method call");
3965+ goto final_exit;
3966+ }
3967+
3968+ dbus_pending_call_set_notify(pending_return,
3969+ _geis_dbus_client_unsubscribe_reply,
3970+ client, 0);
3971+ geis_subscription_bag_remove(client->subscription_bag, subscription);
3972+ status = GEIS_STATUS_SUCCESS;
3973+ }
3974+
3975+final_exit:
3976+ return status;
3977+}
3978+
3979+
3980+
3981+
3982
3983=== added file 'libutouch-geis/backend/dbus/geis_dbus_client.h'
3984--- libutouch-geis/backend/dbus/geis_dbus_client.h 1970-01-01 00:00:00 +0000
3985+++ libutouch-geis/backend/dbus/geis_dbus_client.h 2011-10-17 21:56:23 +0000
3986@@ -0,0 +1,97 @@
3987+/**
3988+ * @file geis_dbus_client.h
3989+ * @brief Interface for the GEIS DBus client.
3990+ *
3991+ * The GEIS DBus client offers remote GEIS functionality over a managed
3992+ * DBus connection.
3993+ *
3994+ * This header is for internal GEIS use only and contains no client
3995+ * (externally-visible) symbols.
3996+ */
3997+
3998+/*
3999+ * Copyright 2011 Canonical Ltd.
4000+ *
4001+ * This library is free software; you can redistribute it and/or modify it under
4002+ * the terms of the GNU Lesser General Public License as published by the Free
4003+ * Software Foundation; either version 3 of the License, or (at your option) any
4004+ * later version.
4005+ *
4006+ * This library is distributed in the hope that it will be useful, but WITHOUT
4007+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4008+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
4009+ * details.
4010+ *
4011+ * You should have received a copy of the GNU General Public License
4012+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4013+ */
4014+#ifndef GEIS_DBUS_CLIENT_H_
4015+#define GEIS_DBUS_CLIENT_H_
4016+
4017+#include "geis/geis.h"
4018+#include "geis_dbus_dispatcher.h"
4019+
4020+
4021+typedef struct GeisDBusClient *GeisDBusClient;
4022+
4023+
4024+/**
4025+ * Creates a new %GeisDBusClient object.
4026+ */
4027+GeisDBusClient
4028+geis_dbus_client_new(Geis geis);
4029+
4030+/**
4031+ * Destroys a %GeisDBusClient.
4032+ *
4033+ * @param[in] client A GeisDBusClient.
4034+ */
4035+void
4036+geis_dbus_client_delete(GeisDBusClient client);
4037+
4038+/**
4039+ * Gets the client dispatcher.
4040+ *
4041+ * @param[in] client A GeisDBusClient.
4042+ */
4043+GeisDBusDispatcher
4044+geis_dbus_client_dispatcher(GeisDBusClient client);
4045+
4046+/**
4047+ * Signals the client the server has been located.
4048+ *
4049+ * @param[in] client A GeisDBusClient.
4050+ */
4051+void
4052+geis_dbus_client_server_located(GeisDBusClient client);
4053+
4054+/**
4055+ * Signals the client the server has been dislocated.
4056+ *
4057+ * @param[in] client A GeisDBusClient.
4058+ */
4059+void
4060+geis_dbus_client_server_dislocated(GeisDBusClient client);
4061+
4062+/**
4063+ * Cerates a subscription on the remote end.
4064+ *
4065+ * @param[in] client The client-side of the DBus connection.
4066+ * @param[in] subscription The local subscription object.
4067+ */
4068+GeisStatus
4069+geis_dbus_client_subscribe(GeisDBusClient client,
4070+ GeisSubscription subscription);
4071+
4072+/**
4073+ * Deactivates a subscription on the remote end.
4074+ *
4075+ * @param[in] client The client-side of the DBus connection.
4076+ * @param[in] subscription The local subscription object.
4077+ */
4078+GeisStatus
4079+geis_dbus_client_unsubscribe(GeisDBusClient client,
4080+ GeisSubscription subscription);
4081+
4082+
4083+#endif /* GEIS_DBUS_CLIENT_H_ */
4084
4085=== added file 'libutouch-geis/backend/dbus/geis_dbus_locator.c'
4086--- libutouch-geis/backend/dbus/geis_dbus_locator.c 1970-01-01 00:00:00 +0000
4087+++ libutouch-geis/backend/dbus/geis_dbus_locator.c 2011-10-17 21:56:23 +0000
4088@@ -0,0 +1,268 @@
4089+/**
4090+ * @file geis_dbus_locator.c
4091+ * @brief Implementation of the GEIS DBus locator.
4092+ */
4093+
4094+/*
4095+ * Copyright 2011 Canonical Ltd.
4096+ *
4097+ * This library is free software; you can redistribute it and/or modify it under
4098+ * the terms of the GNU Lesser General Public License as published by the Free
4099+ * Software Foundation; either version 3 of the License, or (at your option) any
4100+ * later version.
4101+ *
4102+ * This library is distributed in the hope that it will be useful, but WITHOUT
4103+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4104+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
4105+ * details.
4106+ *
4107+ * You should have received a copy of the GNU General Public License
4108+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4109+ */
4110+#include "geis_config.h"
4111+#include "geis_dbus_locator.h"
4112+
4113+#include <dbus/dbus.h>
4114+#include "geis_dbus.h"
4115+#include "geis_logging.h"
4116+#include <stdio.h>
4117+#include <stdlib.h>
4118+#include <string.h>
4119+
4120+
4121+typedef enum GeisDBusLocatorState
4122+{
4123+ GEIS_DBUS_LOCATOR_STATE_INITIALIZING,
4124+ GEIS_DBUS_LOCATOR_STATE_LOCATING,
4125+ GEIS_DBUS_LOCATOR_STATE_WAITING,
4126+ GEIS_DBUS_LOCATOR_STATE_FINALIZING
4127+} GeisDBusLocatorState;
4128+
4129+
4130+struct GeisDBusLocator
4131+{
4132+ GeisDBusClient client;
4133+ GeisDBusLocatorState state;
4134+ DBusConnection *session_bus;
4135+ char *server_address;
4136+ dbus_uint32_t serial;
4137+};
4138+
4139+
4140+/*
4141+ * Performs the act of actually locating the server.
4142+ */
4143+static void
4144+_locator_find_server(GeisDBusLocator locator)
4145+{
4146+ locator->state = GEIS_DBUS_LOCATOR_STATE_LOCATING;
4147+ DBusMessage *msg = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
4148+ GEIS_DBUS_SERVICE_PATH,
4149+ GEIS_DBUS_SERVICE_INTERFACE,
4150+ GEIS_DBUS_GET_SERVER_ADDRESS);
4151+ dbus_connection_send(locator->session_bus, msg, &locator->serial);
4152+ dbus_message_unref(msg);
4153+}
4154+
4155+
4156+/*
4157+ * A generic message handler function.
4158+ */
4159+static DBusHandlerResult
4160+_locator_message_handler(DBusConnection *connection GEIS_UNUSED,
4161+ DBusMessage *message,
4162+ void *user_data)
4163+{
4164+ DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4165+ GeisDBusLocator locator = (GeisDBusLocator)user_data;
4166+ int type = dbus_message_get_type(message);
4167+
4168+ if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
4169+ {
4170+ char *name;
4171+ char *old_owner;
4172+ char *new_owner;
4173+ dbus_message_get_args(message, NULL,
4174+ DBUS_TYPE_STRING, &name,
4175+ DBUS_TYPE_STRING, &old_owner,
4176+ DBUS_TYPE_STRING, &new_owner,
4177+ DBUS_TYPE_INVALID);
4178+ if (strlen(old_owner))
4179+ {
4180+ geis_debug("%s has gone away", name);
4181+ geis_dbus_client_server_dislocated(locator->client);
4182+ result = DBUS_HANDLER_RESULT_HANDLED;
4183+ }
4184+ else if (strlen(new_owner))
4185+ {
4186+ geis_debug("%s has appeared", name);
4187+ _locator_find_server(locator);
4188+ result = DBUS_HANDLER_RESULT_HANDLED;
4189+ }
4190+ }
4191+ else if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN)
4192+ {
4193+ if (locator->serial == dbus_message_get_reply_serial(message))
4194+ {
4195+ dbus_message_get_args(message, NULL,
4196+ DBUS_TYPE_STRING, &locator->server_address,
4197+ DBUS_TYPE_INVALID);
4198+ geis_dbus_client_server_located(locator->client);
4199+ result = DBUS_HANDLER_RESULT_HANDLED;
4200+ }
4201+ }
4202+ else if (type == DBUS_MESSAGE_TYPE_ERROR)
4203+ {
4204+ if (dbus_message_is_error(message, DBUS_ERROR_SERVICE_UNKNOWN))
4205+ {
4206+ geis_warning("server not found!");
4207+ geis_dbus_client_server_dislocated(locator->client);
4208+ result = DBUS_HANDLER_RESULT_HANDLED;
4209+ }
4210+ else
4211+ {
4212+ const char *str = NULL;
4213+ dbus_message_get_args(message, NULL,
4214+ DBUS_TYPE_STRING, &str,
4215+ DBUS_TYPE_INVALID);
4216+ geis_warning("error %s: %s", dbus_message_get_error_name(message), str);
4217+ }
4218+ }
4219+
4220+ return result;
4221+}
4222+
4223+
4224+/*
4225+ * Adds the locator watches to the dispatcher watch list.
4226+ */
4227+static dbus_bool_t
4228+_locator_add_watch(DBusWatch *watch, void *data)
4229+{
4230+ dbus_bool_t status = TRUE;
4231+ GeisDBusLocator locator = (GeisDBusLocator)data;
4232+ GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client);
4233+
4234+ geis_dbus_dispatcher_register(dispatcher, locator->session_bus, watch);
4235+ return status;
4236+}
4237+
4238+
4239+/*
4240+ * Toggles the enabled/disabled status of the locator watches.
4241+ */
4242+static void
4243+_locator_toggle_watch(DBusWatch *watch, void *data)
4244+{
4245+ GeisDBusLocator locator = (GeisDBusLocator)data;
4246+ GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client);
4247+
4248+ geis_dbus_dispatcher_toggle_watch(dispatcher, watch);
4249+}
4250+
4251+
4252+/*
4253+ * Removes the locator watches from the dispatcher watch list.
4254+ */
4255+static void
4256+_locator_remove_watch(DBusWatch *watch, void *data)
4257+{
4258+ GeisDBusLocator locator = (GeisDBusLocator)data;
4259+ GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client);
4260+
4261+ geis_dbus_dispatcher_unregister(dispatcher, watch);
4262+}
4263+
4264+
4265+/*
4266+ * Creates a new GeisDBusLocator object.
4267+ */
4268+GeisDBusLocator
4269+geis_dbus_locator_new(GeisDBusClient client)
4270+{
4271+ GeisDBusLocator locator = calloc(1, sizeof(struct GeisDBusLocator));
4272+ if (!locator)
4273+ {
4274+ goto final_exit;
4275+ }
4276+
4277+ locator->client = client;
4278+ locator->state = GEIS_DBUS_LOCATOR_STATE_INITIALIZING;
4279+
4280+ /* Connect to the DBus session bus. */
4281+ DBusError error = DBUS_ERROR_INIT;
4282+ locator->session_bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
4283+ if (!locator->session_bus || dbus_error_is_set(&error))
4284+ {
4285+ char msg[512];
4286+ snprintf(msg, sizeof(msg), "error %s connecting to session bus: %s",
4287+ error.name, error.message);
4288+ geis_error("%s", msg);
4289+ goto unwind_error;
4290+ }
4291+
4292+ /* Integrate with the app event loop via the GEIS multiplexor. */
4293+ dbus_connection_set_watch_functions(locator->session_bus,
4294+ _locator_add_watch,
4295+ _locator_remove_watch,
4296+ _locator_toggle_watch,
4297+ locator, 0);
4298+
4299+ /* Look for server-connect and server-disconnect messages. */
4300+ dbus_bus_add_match(locator->session_bus,
4301+ "type='signal',sender='" DBUS_SERVICE_DBUS "'," \
4302+ "interface='" DBUS_INTERFACE_DBUS "'," \
4303+ "member='NameOwnerChanged'," \
4304+ "arg0='" GEIS_DBUS_SERVICE_INTERFACE "'",
4305+ &error);
4306+ if (dbus_error_is_set(&error))
4307+ {
4308+ char msg[512];
4309+ snprintf(msg, sizeof(msg), "error %s adding match to session bus: %s",
4310+ error.name, error.message);
4311+ geis_error("%s", msg);
4312+ goto unwind_error;
4313+ }
4314+
4315+ /* Install a handler for any and all messages. */
4316+ dbus_connection_add_filter(locator->session_bus,
4317+ _locator_message_handler,
4318+ locator, 0);
4319+
4320+ /* OK, go eh? */
4321+ _locator_find_server(locator);
4322+
4323+unwind_error:
4324+ dbus_error_free(&error);
4325+final_exit:
4326+ return locator;
4327+}
4328+
4329+
4330+/*
4331+ * Destroys a %GeisDBusLocator object.
4332+ */
4333+void
4334+geis_dbus_locator_delete(GeisDBusLocator locator)
4335+{
4336+ if (locator)
4337+ {
4338+ if (locator->server_address)
4339+ {
4340+ free(locator->server_address);
4341+ }
4342+ if (locator->session_bus)
4343+ {
4344+ dbus_connection_unref(locator->session_bus);
4345+ }
4346+ free(locator);
4347+ }
4348+}
4349+
4350+
4351+char *
4352+geis_dbus_locator_server_address(GeisDBusLocator locator)
4353+{
4354+ return locator->server_address;
4355+}
4356+
4357
4358=== added file 'libutouch-geis/backend/dbus/geis_dbus_locator.h'
4359--- libutouch-geis/backend/dbus/geis_dbus_locator.h 1970-01-01 00:00:00 +0000
4360+++ libutouch-geis/backend/dbus/geis_dbus_locator.h 2011-10-17 21:56:23 +0000
4361@@ -0,0 +1,62 @@
4362+/**
4363+ * @file geis_dbus_locator.h
4364+ * @brief Interface for the GEIS DBus locator.
4365+ *
4366+ * The GEIS DBus locator makes the location of the GEIS DBus server available
4367+ * over the DBus session bus.
4368+ *
4369+ * This header is for internal GEIS use only and contains no client
4370+ * (externally-visible) symbols.
4371+ */
4372+
4373+/*
4374+ * Copyright 2011 Canonical Ltd.
4375+ *
4376+ * This library is free software; you can redistribute it and/or modify it under
4377+ * the terms of the GNU Lesser General Public License as published by the Free
4378+ * Software Foundation; either version 3 of the License, or (at your option) any
4379+ * later version.
4380+ *
4381+ * This library is distributed in the hope that it will be useful, but WITHOUT
4382+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4383+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
4384+ * details.
4385+ *
4386+ * You should have received a copy of the GNU General Public License
4387+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4388+ */
4389+#ifndef GEIS_DBUS_LOCATOR_H_
4390+#define GEIS_DBUS_LOCATOR_H_
4391+
4392+#include "geis/geis.h"
4393+#include "geis_dbus_client.h"
4394+
4395+
4396+typedef struct GeisDBusLocator *GeisDBusLocator;
4397+
4398+
4399+/**
4400+ * Creates a new GeisDBusLocator object.
4401+ *
4402+ * @param[in] client A GEIS DBus CLient.
4403+ */
4404+GeisDBusLocator
4405+geis_dbus_locator_new(GeisDBusClient client);
4406+
4407+/**
4408+ * Destroys a %GeisDBusLocator object.
4409+ *
4410+ * @param[in] locator A GeisDBusLocator.
4411+ */
4412+void
4413+geis_dbus_locator_delete(GeisDBusLocator locator);
4414+
4415+/**
4416+ * Gets the currently located server address.
4417+ *
4418+ * @param[in] locator A GeisDBusLocator.
4419+ */
4420+char *
4421+geis_dbus_locator_server_address(GeisDBusLocator locator);
4422+
4423+#endif /* GEIS_DBUS_LOCATOR_H_ */
4424
4425=== modified file 'libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c'
4426--- libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2011-08-18 18:14:12 +0000
4427+++ libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2011-10-17 21:56:23 +0000
4428@@ -77,8 +77,8 @@
4429 static GeisBackendToken _token_clone(GeisBackendToken);
4430 static void _token_finalize(GeisBackendToken);
4431 static void _token_compose(GeisBackendToken, GeisBackendToken);
4432-static GeisStatus _token_activate(GeisBackendToken);
4433-static GeisStatus _token_deactivate(GeisBackendToken);
4434+static GeisStatus _token_activate(GeisBackendToken, GeisSubscription);
4435+static GeisStatus _token_deactivate(GeisBackendToken, GeisSubscription);
4436
4437 static struct GeisBackendTokenVtable _token_vtbl = {
4438 _token_clone,
4439@@ -361,7 +361,8 @@
4440
4441
4442 GeisStatus
4443-_token_activate(GeisBackendToken gbtoken)
4444+_token_activate(GeisBackendToken gbtoken,
4445+ GeisSubscription subscription GEIS_UNUSED)
4446 {
4447 GeisStatus status = GEIS_STATUS_SUCCESS;
4448 TestBackendToken token = _tbtoken_from_token(gbtoken);
4449@@ -371,7 +372,8 @@
4450
4451
4452 GeisStatus
4453-_token_deactivate(GeisBackendToken gbtoken GEIS_UNUSED)
4454+_token_deactivate(GeisBackendToken gbtoken GEIS_UNUSED,
4455+ GeisSubscription subscription GEIS_UNUSED)
4456 {
4457 GeisStatus status = GEIS_STATUS_SUCCESS;
4458 return status;
4459@@ -381,7 +383,7 @@
4460 __attribute__((constructor))
4461 static void _register_test_fixture()
4462 {
4463- geis_register_backend(GEIS_INIT_UTOUCH_MOCK_ENGINE,
4464+ geis_register_backend(GEIS_INIT_UTOUCH_MOCK_BACKEND,
4465 sizeof(struct GeisBackendTestFixture),
4466 &tf_vtbl);
4467 }
4468
4469=== modified file 'libutouch-geis/backend/xcb/geis_xcb_backend.c'
4470--- libutouch-geis/backend/xcb/geis_xcb_backend.c 2011-09-02 15:52:27 +0000
4471+++ libutouch-geis/backend/xcb/geis_xcb_backend.c 2011-10-17 21:56:23 +0000
4472@@ -105,7 +105,7 @@
4473 static void _construct(void *mem, Geis geis);
4474 static void _finalize(GeisBackend g);
4475 static GeisBackendToken _create_token(GeisBackend be, GeisBackendTokenInitState);
4476-static void _fd_callback(int fd, GeisBackendMultiplexorEvent ev, void *ctx);
4477+static void _fd_callback(int fd, GeisBackendMultiplexorActivity ev, void *ctx);
4478
4479
4480 static struct GeisBackendVtable be_vtbl = {
4481@@ -116,7 +116,7 @@
4482
4483
4484 /* A handy little table to map grail types to geis gesture classes. */
4485-struct GrailTypeToGeisClass
4486+static struct GrailTypeToGeisClass
4487 {
4488 GeisInteger grail_type;
4489 GeisGestureClass geis_class;
4490@@ -156,7 +156,8 @@
4491 { GRAIL_TYPE_MTOUCH, NULL }
4492 };
4493
4494-GeisSize s_grail_type_map_size = sizeof(s_grail_type_map) / sizeof(struct GrailTypeToGeisClass);
4495+static GeisSize s_grail_type_map_size = sizeof(s_grail_type_map)
4496+ / sizeof(struct GrailTypeToGeisClass);
4497
4498 static void
4499 _set_grail_type_class(GeisInteger grail_type, GeisGestureClass geis_class)
4500@@ -653,7 +654,8 @@
4501 }
4502
4503 be->xcb_fd = xcb_get_file_descriptor(be->xcb_connection);
4504- geis_multiplex_fd(be->geis, be->xcb_fd, _fd_callback, be);
4505+ geis_multiplex_fd(be->geis, be->xcb_fd, GEIS_BE_MX_READ_AVAILABLE,
4506+ _fd_callback, be);
4507
4508 be->sub_table = geis_xcb_backend_sub_table_new();
4509
4510@@ -933,9 +935,9 @@
4511
4512 /** @todo implement this */
4513 void
4514-_fd_callback(int fd GEIS_UNUSED,
4515- GeisBackendMultiplexorEvent ev GEIS_UNUSED,
4516- void *ctx)
4517+_fd_callback(int fd GEIS_UNUSED,
4518+ GeisBackendMultiplexorActivity ev GEIS_UNUSED,
4519+ void *ctx)
4520 {
4521 GeisXcbBackend be = (GeisXcbBackend)ctx;
4522 _xcb_dispatch(be);
4523@@ -1022,7 +1024,7 @@
4524 __attribute__((constructor))
4525 static void _register_xcb_backend()
4526 {
4527- geis_register_backend(GEIS_INIT_UTOUCH_XCB,
4528+ geis_register_backend(GEIS_INIT_UTOUCH_XCB_BACKEND,
4529 sizeof(struct GeisXcbBackend),
4530 &be_vtbl);
4531 }
4532
4533=== modified file 'libutouch-geis/backend/xcb/geis_xcb_backend_token.c'
4534--- libutouch-geis/backend/xcb/geis_xcb_backend_token.c 2011-08-29 18:41:20 +0000
4535+++ libutouch-geis/backend/xcb/geis_xcb_backend_token.c 2011-10-17 21:56:23 +0000
4536@@ -55,8 +55,8 @@
4537 static GeisBackendToken _token_clone(GeisBackendToken);
4538 static void _token_finalize(GeisBackendToken);
4539 static void _token_compose(GeisBackendToken, GeisBackendToken);
4540-static GeisStatus _token_activate(GeisBackendToken);
4541-static GeisStatus _token_deactivate(GeisBackendToken);
4542+static GeisStatus _token_activate(GeisBackendToken, GeisSubscription);
4543+static GeisStatus _token_deactivate(GeisBackendToken, GeisSubscription);
4544
4545 static struct GeisBackendTokenVtable _token_vtbl = {
4546 _token_clone,
4547@@ -317,7 +317,7 @@
4548 * various back end subscriptions appropriately.
4549 */
4550 static GeisStatus
4551-_token_activate(GeisBackendToken token)
4552+_token_activate(GeisBackendToken token, GeisSubscription subscripton GEIS_UNUSED)
4553 {
4554 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
4555 XcbBackendToken t = _xcb_token_from_geis_token(token);
4556@@ -338,7 +338,7 @@
4557 * various back end subscriptions appropriately.
4558 */
4559 static GeisStatus
4560-_token_deactivate(GeisBackendToken token)
4561+_token_deactivate(GeisBackendToken token, GeisSubscription sub GEIS_UNUSED)
4562 {
4563 GeisStatus status = GEIS_STATUS_SUCCESS;
4564 XcbBackendToken t = _xcb_token_from_geis_token(token);
4565
4566=== modified file 'libutouch-geis/backend/xcb/grail_gestures.c'
4567--- libutouch-geis/backend/xcb/grail_gestures.c 2011-07-22 15:54:50 +0000
4568+++ libutouch-geis/backend/xcb/grail_gestures.c 2011-10-17 21:56:23 +0000
4569@@ -505,7 +505,7 @@
4570 (char *)grail_class->name);
4571 geis_frame_add_attr(frame, attr);
4572
4573- attr = geis_attr_new("geis gesture class id",
4574+ attr = geis_attr_new(GEIS_CLASS_ATTRIBUTE_ID,
4575 GEIS_ATTR_TYPE_INTEGER,
4576 (void *)&grail_class->geis_class_id);
4577 geis_frame_add_attr(frame, attr);
4578
4579=== modified file 'libutouch-geis/geis.c'
4580--- libutouch-geis/geis.c 2011-08-21 16:28:27 +0000
4581+++ libutouch-geis/geis.c 2011-10-17 21:56:23 +0000
4582@@ -32,6 +32,7 @@
4583 #include "geis_attr.h"
4584 #include "geis_backend.h"
4585 #include "geis_class.h"
4586+#include "server/geis_dbus_server.h" /* @TODO replace me */
4587 #include "geis_device.h"
4588 #include "geis_backend_multiplexor.h"
4589 #include "geis_error.h"
4590@@ -45,16 +46,6 @@
4591
4592
4593 /*
4594- * An internal struct to collect filterable attributes for facilities.
4595- */
4596-typedef struct FilterableAttributeBag
4597-{
4598- GeisFilterableAttribute store;
4599- GeisSize size;
4600- GeisSize count;
4601-} *FilterableAttributeBag;
4602-
4603-/*
4604 * An internal structure to track processing callbacks in some order.
4605 */
4606 typedef struct GeisProcessingEntry *GeisProcessingEntry;
4607@@ -78,6 +69,8 @@
4608 GeisSubBag subscription_bag;
4609 GeisBackendMultiplexor backend_multiplexor;
4610 GeisBackend backend;
4611+ GeisBoolean backend_pending;
4612+ GeisDBusServer server; /* @TODO: replace me */
4613 GeisEventQueue input_event_queue;
4614 int input_event_signal_pipe[2];
4615 GeisProcessingEntry processing_callbacks;
4616@@ -200,12 +193,14 @@
4617 * Filters and transforms raw gesture events into cooked gesture events.
4618 */
4619 static void
4620-_input_event_handler(int fd, GeisBackendMultiplexorEvent mux_ev, void *context)
4621+_input_event_handler(int fd,
4622+ GeisBackendMultiplexorActivity activity,
4623+ void *context)
4624 {
4625 Geis geis = (Geis)context;
4626 GeisProcessingEntry cb;
4627
4628- if (mux_ev == GEIS_BE_MX_READ_AVAILABLE)
4629+ if (activity & GEIS_BE_MX_READ_AVAILABLE)
4630 {
4631 GeisEvent event;
4632
4633@@ -234,6 +229,20 @@
4634 handled = _class_event_handler(geis, event);
4635 break;
4636
4637+ case GEIS_EVENT_INIT_COMPLETE:
4638+ geis->backend_pending = GEIS_FALSE;
4639+ break;
4640+
4641+ case GEIS_EVENT_ERROR:
4642+ if (geis->backend_pending)
4643+ {
4644+ geis->backend = geis_backend_by_name(geis,
4645+ GEIS_INIT_UTOUCH_XCB_BACKEND);
4646+ geis->backend_pending = GEIS_FALSE;
4647+ handled = GEIS_TRUE;
4648+ }
4649+ break;
4650+
4651 default:
4652 break;
4653 }
4654@@ -273,93 +282,6 @@
4655
4656
4657 /*
4658- * Constructs a new filterable attribute bag.
4659- */
4660-static FilterableAttributeBag
4661-_filterable_attribute_bag_new()
4662-{
4663- FilterableAttributeBag bag = calloc(1, sizeof(struct FilterableAttributeBag));
4664- if (!bag)
4665- {
4666- geis_error("failed to allocate filterable attribute bag");
4667- goto final_exit;
4668- }
4669-
4670- bag->size = 2;
4671- bag->count = 0;
4672-
4673- bag->store = calloc(1, sizeof(struct GeisFilterableAttribute));
4674- if (!bag)
4675- {
4676- geis_error("failed to allocate filterable attribute bag store");
4677- goto unwind_bag;
4678- }
4679- goto final_exit;
4680-
4681-unwind_bag:
4682- free(bag);
4683- bag = NULL;
4684-final_exit:
4685- return bag;
4686-}
4687-
4688-
4689-/*
4690- * Destroys a filterable attribute bag.
4691- */
4692-static void
4693-_filterable_attribute_bag_delete(FilterableAttributeBag bag)
4694-{
4695- if (bag)
4696- {
4697- GeisSize i;
4698- for (i = 0; i < bag->count; ++i)
4699- {
4700- free((char *)bag->store[i].name);
4701- }
4702- free(bag->store);
4703- }
4704- free(bag);
4705-}
4706-
4707-
4708-static void
4709-_filterable_attribute_copy(GeisFilterableAttribute src,
4710- GeisFilterableAttribute dst)
4711-{
4712- dst->name = strdup(src->name);
4713- dst->type = src->type;
4714- dst->add_term_callback = src->add_term_callback;
4715- dst->add_term_context = src->add_term_context;
4716-}
4717-
4718-
4719-static void
4720-_filterable_attribute_bag_insert(FilterableAttributeBag bag,
4721- GeisFilterableAttribute fa)
4722-{
4723- GeisSize new_count = bag->count + 1;
4724- if (new_count >= bag->size)
4725- {
4726- GeisSize new_size = bag->size * 2;
4727- GeisSize allocation_size = new_size * sizeof(struct GeisFilterableAttribute);
4728- GeisFilterableAttribute new_store = realloc(bag->store, allocation_size);
4729- if (!new_store)
4730- {
4731- geis_error("failed to reallocate filterable attribute bag store");
4732- }
4733- else
4734- {
4735- bag->store = new_store;
4736- bag->size = new_size;
4737- }
4738- }
4739- _filterable_attribute_copy(fa, &bag->store[bag->count]);
4740- bag->count = new_count;
4741-}
4742-
4743-
4744-/*
4745 * Applies the back end callback to the back end token for each filterable
4746 * attribute with a name matching the argument.
4747 */
4748@@ -371,13 +293,16 @@
4749 void *value)
4750 {
4751 GeisStatus status = GEIS_STATUS_SUCCESS;
4752- GeisSize i;
4753- for (i = 0; i < bag->count; ++i)
4754+ GeisFilterableAttributeBagIter it;
4755+ for (it = geis_filterable_attribute_bag_begin(bag);
4756+ it != geis_filterable_attribute_bag_end(bag);
4757+ it = geis_filterable_attribute_bag_next(bag, it))
4758 {
4759- GeisFilterableAttribute fa = &bag->store[i];
4760- if (0 == strcmp(fa->name, name))
4761+ if (0 == strcmp(it->name, name) && it->add_term_callback)
4762 {
4763- status = fa->add_term_callback(token, fa->add_term_context, name, op, value);
4764+ status = it->add_term_callback(token,
4765+ it->add_term_context,
4766+ name, op, value);
4767 }
4768 }
4769 return status;
4770@@ -389,11 +314,11 @@
4771 */
4772 GeisStatus
4773 geis_filterable_attribute_foreach(Geis geis,
4774- GeisFilterFacility facility,
4775- GeisBackendToken token,
4776- GeisString name,
4777- GeisFilterOperation op,
4778- void *value)
4779+ GeisFilterFacility facility,
4780+ GeisBackendToken token,
4781+ GeisString name,
4782+ GeisFilterOperation op,
4783+ void *value)
4784 {
4785 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
4786 switch (facility)
4787@@ -470,6 +395,7 @@
4788 }
4789 geis_backend_multiplexor_add_fd(geis->backend_multiplexor,
4790 geis->input_event_signal_pipe[0],
4791+ GEIS_BE_MX_READ_AVAILABLE,
4792 _input_event_handler,
4793 geis);
4794
4795@@ -482,7 +408,7 @@
4796 }
4797 geis->output_event_callback = _default_output_event_callback;
4798
4799- geis->class_filterable_attributes = _filterable_attribute_bag_new();
4800+ geis->class_filterable_attributes = geis_filterable_attribute_bag_new();
4801 if (!geis->class_filterable_attributes)
4802 {
4803 geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR);
4804@@ -499,7 +425,7 @@
4805 }
4806 geis->class_event_callback = _default_output_event_callback;
4807
4808- geis->device_filterable_attributes = _filterable_attribute_bag_new();
4809+ geis->device_filterable_attributes = geis_filterable_attribute_bag_new();
4810 if (!geis->device_filterable_attributes)
4811 {
4812 geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR);
4813@@ -516,13 +442,13 @@
4814 }
4815 geis->device_event_callback = _default_output_event_callback;
4816
4817- geis->region_filterable_attributes = _filterable_attribute_bag_new();
4818+ geis->region_filterable_attributes = geis_filterable_attribute_bag_new();
4819 if (!geis->region_filterable_attributes)
4820 {
4821 goto unwind_device_bag;
4822 }
4823
4824- geis->special_filterable_attributes = _filterable_attribute_bag_new();
4825+ geis->special_filterable_attributes = geis_filterable_attribute_bag_new();
4826 if (!geis->special_filterable_attributes)
4827 {
4828 goto unwind_region_attrs;
4829@@ -531,15 +457,15 @@
4830 goto final_exit;
4831
4832 unwind_region_attrs:
4833- _filterable_attribute_bag_delete(geis->region_filterable_attributes);
4834+ geis_filterable_attribute_bag_delete(geis->region_filterable_attributes);
4835 unwind_device_bag:
4836 geis_device_bag_delete(geis->devices);
4837 unwind_device_attrs:
4838- _filterable_attribute_bag_delete(geis->device_filterable_attributes);
4839+ geis_filterable_attribute_bag_delete(geis->device_filterable_attributes);
4840 unwind_class_bag:
4841 geis_gesture_class_bag_delete(geis->gesture_classes);
4842 unwind_class_attrs:
4843- _filterable_attribute_bag_delete(geis->class_filterable_attributes);
4844+ geis_filterable_attribute_bag_delete(geis->class_filterable_attributes);
4845 unwind_output_queue:
4846 geis_event_queue_delete(geis->output_event_queue);
4847 unwind_input_signal_pipe:
4848@@ -564,6 +490,7 @@
4849 {
4850 BACK_END_TYPE_NONE,
4851 BACK_END_TYPE_MOCK_ENGINE,
4852+ BACK_END_TYPE_DBUS,
4853 BACK_END_TYPE_XCB
4854 } BackendType;
4855
4856@@ -580,7 +507,7 @@
4857 {
4858 if (0 == strcmp(init_arg_name, GEIS_INIT_SERVICE_PROVIDER))
4859 {
4860- geis_debug("initializing GEIS server");
4861+ geis->server = geis_dbus_server_new(geis);
4862 }
4863 else if (0 == strcmp(init_arg_name, GEIS_INIT_TRACK_DEVICES))
4864 {
4865@@ -590,7 +517,7 @@
4866 {
4867 /* no longer supported */
4868 }
4869- else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_MOCK_ENGINE))
4870+ else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_MOCK_BACKEND))
4871 {
4872 if (back_end_type != BACK_END_TYPE_NONE)
4873 {
4874@@ -598,7 +525,15 @@
4875 }
4876 back_end_type = BACK_END_TYPE_MOCK_ENGINE;
4877 }
4878- else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_XCB))
4879+ else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_DBUS_BACKEND))
4880+ {
4881+ if (back_end_type != BACK_END_TYPE_NONE)
4882+ {
4883+ geis_error("multiple back ends requested, only using last request");
4884+ }
4885+ back_end_type = BACK_END_TYPE_DBUS;
4886+ }
4887+ else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_XCB_BACKEND))
4888 {
4889 if (back_end_type != BACK_END_TYPE_NONE)
4890 {
4891@@ -612,16 +547,22 @@
4892
4893 if (back_end_type == BACK_END_TYPE_MOCK_ENGINE)
4894 {
4895- geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_MOCK_ENGINE);
4896- }
4897- else if (back_end_type ==BACK_END_TYPE_XCB)
4898- {
4899- geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_XCB);
4900+ geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_MOCK_BACKEND);
4901+ }
4902+ else if (back_end_type == BACK_END_TYPE_DBUS)
4903+ {
4904+ geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_DBUS_BACKEND);
4905+ geis->backend_pending = GEIS_TRUE;
4906+ }
4907+ else if (back_end_type == BACK_END_TYPE_XCB)
4908+ {
4909+ geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_XCB_BACKEND);
4910 }
4911 else
4912 {
4913- geis_warning("back end not specified, defaulting to XCB");
4914- geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_XCB);
4915+ geis_warning("back end not specified, defaulting to DBus");
4916+ geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_DBUS_BACKEND);
4917+ geis->backend_pending = GEIS_TRUE;
4918 }
4919 if (!geis->backend)
4920 {
4921@@ -681,16 +622,18 @@
4922 }
4923
4924 geis_gesture_flick_delete(geis->flick);
4925- _filterable_attribute_bag_delete(geis->special_filterable_attributes);
4926- _filterable_attribute_bag_delete(geis->region_filterable_attributes);
4927+ geis_filterable_attribute_bag_delete(geis->special_filterable_attributes);
4928+ geis_filterable_attribute_bag_delete(geis->region_filterable_attributes);
4929 geis_device_bag_delete(geis->devices);
4930- _filterable_attribute_bag_delete(geis->device_filterable_attributes);
4931+ geis_filterable_attribute_bag_delete(geis->device_filterable_attributes);
4932 geis_gesture_class_bag_delete(geis->gesture_classes);
4933- _filterable_attribute_bag_delete(geis->class_filterable_attributes);
4934+ geis_filterable_attribute_bag_delete(geis->class_filterable_attributes);
4935 geis_event_queue_delete(geis->output_event_queue);
4936 close(geis->input_event_signal_pipe[0]);
4937 close(geis->input_event_signal_pipe[1]);
4938 geis_event_queue_delete(geis->input_event_queue);
4939+ if (geis->server)
4940+ geis_dbus_server_delete(geis->server);
4941 if (geis->backend)
4942 geis_backend_delete(geis->backend);
4943 geis_backend_multiplexor_delete(geis->backend_multiplexor);
4944@@ -930,13 +873,31 @@
4945 * Adds a back end file descriptor to multiplex.
4946 */
4947 void
4948-geis_multiplex_fd(Geis geis,
4949- int fd,
4950- GeisBackendFdEventCallback callback,
4951- void *context)
4952+geis_multiplex_fd(Geis geis,
4953+ int fd,
4954+ GeisBackendMultiplexorActivity activity,
4955+ GeisBackendFdEventCallback callback,
4956+ void *context)
4957 {
4958 geis_backend_multiplexor_add_fd(geis->backend_multiplexor,
4959- fd, callback, context);
4960+ fd,
4961+ activity,
4962+ callback,
4963+ context);
4964+}
4965+
4966+
4967+/*
4968+ * Modifies a multiplexed back end file descriptor.
4969+ */
4970+void
4971+geis_remultiplex_fd(Geis geis,
4972+ int fd,
4973+ GeisBackendMultiplexorActivity activity)
4974+{
4975+ geis_backend_multiplexor_modify_fd(geis->backend_multiplexor,
4976+ fd,
4977+ activity);
4978 }
4979
4980
4981@@ -957,10 +918,16 @@
4982 }
4983
4984
4985-GeisSubBag
4986-geis_subscription_bag(Geis geis)
4987-{
4988- return geis->subscription_bag;
4989+GeisSize
4990+geis_add_subscription(Geis geis, GeisSubscription subscription)
4991+{
4992+ return geis_subscription_bag_insert(geis->subscription_bag, subscription);
4993+}
4994+
4995+void
4996+geis_remove_subscription(Geis geis, GeisSubscription subscription)
4997+{
4998+ geis_subscription_bag_remove(geis->subscription_bag, subscription);
4999 }
5000
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: