Status: | Merged |
---|---|
Merged at revision: | 166 |
Proposed branch: | lp:geis/client-arch |
Merge into: | lp:geis |
Diff against target: |
9842 lines (+7414/-649) 90 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 (+573/-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 (+249/-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 (+270/-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 (+129/-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_frame.c (+26/-2) libutouch-geis/geis_frame.h (+27/-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 |
Related bugs: | |
Related blueprints: |
OIF gesture integration into compiz
(Essential)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chase Douglas (community) | Approve | ||
Review via email: mp+79626@code.launchpad.net |
This proposal supersedes a proposal from 2011-10-13.
Commit message
Description of the change
Adds selectable client-server architecture using a private DBus.
Sets the default back end to DBus and automatically falls back to XCB if the GEIS DBus server is not available.
Handles server disconnects and reconnects gracefully.
A command-line switch can be used with the geisview tool to explicitly select a back end.
Only a simple server test tool supplied, an actual utouchd GEIS server daemon will be developed separately.
Stephen M. Webb (bregma) wrote : Posted in a previous version of this proposal | # |
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal | # |
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-
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!
Stephen M. Webb (bregma) wrote : Posted in a previous version of this proposal | # |
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-
the addition of the GEIS_INIT_
> 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-
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.
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal | # |
> 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-
> the addition of the GEIS_INIT_
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...
Stephen M. Webb (bregma) wrote : Posted in a previous version of this proposal | # |
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.
Chase Douglas (chasedouglas) wrote : | # |
I've reviewed all the changes at a high level, and I believe my original criteria 1 and 2 are satisfied. For 1, the only change is the naming of the backend macro definitions. In one sense, it's probably a good thing since it will force anyone specifying the XCB backend to rethink their decision. I'm ok with this.
Criteria 4 has been satisfied by commit 198, which resolves the only previously mentioned issue with the implementation.
The only implementation concern I have now is that if you specify the DBus backend, it will fall back to XCB. I think if the backend is specified, it should only succeed or fail. If the backend is left unspecified, we can do defaulting and failovers. After chatting with Stephen on irc, he agreed with the idea, but felt it wasn't worth the hassle for now. Our solution is to ensure documentation matches what it *should* do, and file a bug to resolve this issue for the DBus backend.
I then tried to test it out. geisview worked great with and without a server, and it reconnected to a server that went away and came back anew. Very cool. Unfortunately, geis causes the turbine.qml example in utouch-qml to crash. We need to figure out what is going on there before we merge it.
Stephen, do you know how we can test out the server with unity? Will running unity --replace after starting the server work?
Chase Douglas (chasedouglas) wrote : | # |
The crash in utouch-qml was a bug in utouch-qml itself. XCB fallback works properly now.
However, utouch-qml fails to see the gesture events. I see subscriptions and gesture event generation in the server when run with GEIS_DEBUG=3, but the client doesn't see anything. Nothing is output from the client at GEIS_DEBUG=3 when the gestures are performed. This also happens when restarting unity while the server is running.
- 199. By Stephen M. Webb
-
Added full support for filtering by gesture class name with DBus server back end.
Stephen M. Webb (bregma) wrote : | # |
Pushed in an additional commit that adds full support for filtering by gesture class name when using the DBus server back end.
Chase Douglas (chasedouglas) wrote : | # |
Unity and utouch-qml now work. The only bug I see left to deal with is a client segfault when the client is closed. This only occurs when the dbus server is used. The xcb interface doesn't crash.
- 200. By Stephen M. Webb
-
Fixed a couple of invalid deallocations on exit.
Stephen M. Webb (bregma) wrote : | # |
Pushed an additional commit to repair a couple of miplaced free()s on teardown.
Chase Douglas (chasedouglas) wrote : | # |
I no longer receive a segfault on client close. This satisfies all my criteria.
I'm approving the merge proposal. Please open a bug about the backend selection default issue.
Great work!
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2011-04-18 13:48:35 +0000 |
3 | +++ .bzrignore 2011-10-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34: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-18 19:34:23 +0000 |
1509 | @@ -0,0 +1,573 @@ |
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_private.h" |
1541 | +#include "geis_touch.h" |
1542 | + |
1543 | +/** |
1544 | + * A frame is marshalled as a dict entry of |
1545 | + * {id: [array of attrs, array of classes, array of touch ids]}, which is |
1546 | + * {i(a(sv)aiai))} in DBus terminaology. |
1547 | + */ |
1548 | +#define GEIS_DBUS_TYPE_SIGNATURE_FRAME \ |
1549 | + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \ |
1550 | + DBUS_TYPE_INT32_AS_STRING \ |
1551 | + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ |
1552 | + DBUS_TYPE_ARRAY_AS_STRING \ |
1553 | + GEIS_DBUS_TYPE_SIGNATURE_ATTR \ |
1554 | + DBUS_TYPE_ARRAY_AS_STRING \ |
1555 | + DBUS_TYPE_INT32_AS_STRING \ |
1556 | + DBUS_TYPE_ARRAY_AS_STRING \ |
1557 | + DBUS_TYPE_INT32_AS_STRING \ |
1558 | + DBUS_STRUCT_END_CHAR_AS_STRING \ |
1559 | + DBUS_DICT_ENTRY_END_CHAR_AS_STRING \ |
1560 | + |
1561 | +#define GEIS_DBUS_TYPE_SIGNATURE_FRAMESET \ |
1562 | + DBUS_TYPE_ARRAY_AS_STRING \ |
1563 | + GEIS_DBUS_TYPE_SIGNATURE_FRAME |
1564 | + |
1565 | + |
1566 | +static void |
1567 | +_marshall_touchset(GeisTouchSet touchset, DBusMessageIter *iter) |
1568 | +{ |
1569 | + DBusMessageIter touchset_iter; |
1570 | + dbus_message_iter_open_container(iter, |
1571 | + DBUS_TYPE_ARRAY, |
1572 | + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING |
1573 | + DBUS_TYPE_INT32_AS_STRING |
1574 | + DBUS_TYPE_ARRAY_AS_STRING |
1575 | + GEIS_DBUS_TYPE_SIGNATURE_ATTR |
1576 | + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, |
1577 | + &touchset_iter); |
1578 | + for (GeisSize t = 0; t < geis_touchset_touch_count(touchset); ++t) |
1579 | + { |
1580 | + DBusMessageIter touch_iter; |
1581 | + dbus_message_iter_open_container(&touchset_iter, |
1582 | + DBUS_TYPE_DICT_ENTRY, |
1583 | + NULL, |
1584 | + &touch_iter); |
1585 | + GeisTouch touch = geis_touchset_touch(touchset, t); |
1586 | + dbus_int32_t touch_id = geis_touch_id(touch); |
1587 | + |
1588 | + dbus_message_iter_append_basic(&touch_iter, DBUS_TYPE_INT32, &touch_id); |
1589 | + DBusMessageIter attr_iter; |
1590 | + dbus_message_iter_open_container(&touch_iter, |
1591 | + DBUS_TYPE_ARRAY, |
1592 | + GEIS_DBUS_TYPE_SIGNATURE_ATTR, |
1593 | + &attr_iter); |
1594 | + for (GeisSize a = 0; a < geis_touch_attr_count(touch); ++a) |
1595 | + { |
1596 | + geis_dbus_attr_marshall(geis_touch_attr(touch, a), &attr_iter); |
1597 | + } |
1598 | + dbus_message_iter_close_container(&touch_iter, &attr_iter); |
1599 | + dbus_message_iter_close_container(&touchset_iter, &touch_iter); |
1600 | + } |
1601 | + dbus_message_iter_close_container(iter, &touchset_iter); |
1602 | +} |
1603 | + |
1604 | + |
1605 | +static void |
1606 | +_unmarshall_touchset(DBusMessageIter *iter, GeisTouchSet touchset) |
1607 | +{ |
1608 | + int dtype = dbus_message_iter_get_arg_type(iter); |
1609 | + if (dtype != DBUS_TYPE_ARRAY) |
1610 | + { |
1611 | + geis_error("malformed GeisEvent touchset"); |
1612 | + } |
1613 | + |
1614 | + DBusMessageIter touch_iter; |
1615 | + dbus_message_iter_recurse(iter, &touch_iter); |
1616 | + for (dtype = dbus_message_iter_get_arg_type(&touch_iter); |
1617 | + dtype != DBUS_TYPE_INVALID; |
1618 | + dbus_message_iter_next(&touch_iter), |
1619 | + dtype = dbus_message_iter_get_arg_type(&touch_iter)) |
1620 | + { |
1621 | + DBusMessageIter dict_iter; |
1622 | + dbus_message_iter_recurse(&touch_iter, &dict_iter); |
1623 | + int type = dbus_message_iter_get_arg_type(&dict_iter); |
1624 | + if (type != DBUS_TYPE_INT32) |
1625 | + { |
1626 | + geis_error("malformed GeisEvent touchset"); |
1627 | + continue; |
1628 | + } |
1629 | + dbus_int32_t touch_id; |
1630 | + dbus_message_iter_get_basic(&dict_iter, &touch_id); |
1631 | + dbus_message_iter_next(&dict_iter); |
1632 | + GeisTouch touch = geis_touch_new(touch_id); |
1633 | + |
1634 | + type = dbus_message_iter_get_arg_type(&dict_iter); |
1635 | + if (type != DBUS_TYPE_ARRAY) |
1636 | + { |
1637 | + geis_error("malformed GeisEvent touchset"); |
1638 | + continue; |
1639 | + } |
1640 | + |
1641 | + DBusMessageIter attr_iter; |
1642 | + dbus_message_iter_recurse(&dict_iter, &attr_iter); |
1643 | + for (int type = dbus_message_iter_get_arg_type(&attr_iter); |
1644 | + type != DBUS_TYPE_INVALID; |
1645 | + dbus_message_iter_next(&attr_iter), |
1646 | + type = dbus_message_iter_get_arg_type(&attr_iter)) |
1647 | + { |
1648 | + GeisAttr attr = geis_dbus_attr_unmarshall(&attr_iter); |
1649 | + geis_touch_add_attr(touch, attr); |
1650 | + } |
1651 | + geis_touchset_insert(touchset, touch); |
1652 | + } |
1653 | +} |
1654 | + |
1655 | + |
1656 | +/** |
1657 | + * Marshalls a GEIS frame to a DBus message via a message iterator. |
1658 | + * @param[in] frame The GEIS frame to marshall. |
1659 | + * @param[in] iter The DBus message iterator. |
1660 | + * |
1661 | + * @todo The class set and matrix need to be added. |
1662 | + */ |
1663 | +static void |
1664 | +_marshall_frame(GeisFrame frame, DBusMessageIter *frame_iter) |
1665 | +{ |
1666 | + DBusMessageIter dict_iter; |
1667 | + dbus_message_iter_open_container(frame_iter, |
1668 | + DBUS_TYPE_DICT_ENTRY, |
1669 | + NULL, |
1670 | + &dict_iter); |
1671 | + |
1672 | + dbus_int32_t frame_id = geis_frame_id(frame); |
1673 | + dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_INT32, &frame_id); |
1674 | + |
1675 | + { |
1676 | + DBusMessageIter struct_iter; |
1677 | + dbus_message_iter_open_container(&dict_iter, |
1678 | + DBUS_TYPE_STRUCT, |
1679 | + NULL, |
1680 | + &struct_iter); |
1681 | + { |
1682 | + DBusMessageIter attr_iter; |
1683 | + dbus_message_iter_open_container(&struct_iter, |
1684 | + DBUS_TYPE_ARRAY, |
1685 | + GEIS_DBUS_TYPE_SIGNATURE_ATTR, |
1686 | + &attr_iter); |
1687 | + for (GeisSize a = 0; a < geis_frame_attr_count(frame); ++a) |
1688 | + { |
1689 | + geis_dbus_attr_marshall(geis_frame_attr(frame, a), &attr_iter); |
1690 | + } |
1691 | + dbus_message_iter_close_container(&struct_iter, &attr_iter); |
1692 | + } |
1693 | + { |
1694 | + DBusMessageIter class_iter; |
1695 | + dbus_message_iter_open_container(&struct_iter, |
1696 | + DBUS_TYPE_ARRAY, |
1697 | + DBUS_TYPE_INT32_AS_STRING, |
1698 | + &class_iter); |
1699 | + for (GeisSize t = 0; t < geis_frame_class_count(frame); ++t) |
1700 | + { |
1701 | + GeisGestureClass frame_class = geis_frame_class(frame, t); |
1702 | + dbus_int32_t class_id = geis_gesture_class_id(frame_class); |
1703 | + dbus_message_iter_append_basic(&class_iter, DBUS_TYPE_INT32, &class_id); |
1704 | + } |
1705 | + dbus_message_iter_close_container(&struct_iter, &class_iter); |
1706 | + } |
1707 | + { |
1708 | + DBusMessageIter touch_iter; |
1709 | + dbus_message_iter_open_container(&struct_iter, |
1710 | + DBUS_TYPE_ARRAY, |
1711 | + DBUS_TYPE_INT32_AS_STRING, |
1712 | + &touch_iter); |
1713 | + for (GeisSize t = 0; t < geis_frame_touchid_count(frame); ++t) |
1714 | + { |
1715 | + dbus_int32_t touch_id = geis_frame_touchid(frame, t); |
1716 | + dbus_message_iter_append_basic(&touch_iter, DBUS_TYPE_INT32, &touch_id); |
1717 | + } |
1718 | + dbus_message_iter_close_container(&struct_iter, &touch_iter); |
1719 | + } |
1720 | + dbus_message_iter_close_container(&dict_iter, &struct_iter); |
1721 | + } |
1722 | + dbus_message_iter_close_container(frame_iter, &dict_iter); |
1723 | +} |
1724 | + |
1725 | + |
1726 | +/** |
1727 | + * Unmarshalls a GEIS frame from a DBus message via a message iterator. |
1728 | + * @param[in] frame_iter The DBus message iterator. |
1729 | + * @param[in] group The group the unmarshalled frame will belong to. |
1730 | + */ |
1731 | +static void |
1732 | +_unmarshall_frame(Geis geis, DBusMessageIter *frame_iter, GeisGroup group) |
1733 | +{ |
1734 | + int type = dbus_message_iter_get_arg_type(frame_iter); |
1735 | + if (type != DBUS_TYPE_DICT_ENTRY) |
1736 | + { |
1737 | + geis_error("malformed GeisEvent frame: expected %c, received %c", |
1738 | + DBUS_TYPE_DICT_ENTRY, type); |
1739 | + goto final_exit; |
1740 | + } |
1741 | + DBusMessageIter dict_iter; |
1742 | + dbus_message_iter_recurse(frame_iter, &dict_iter); |
1743 | + |
1744 | + type = dbus_message_iter_get_arg_type(&dict_iter); |
1745 | + if (type != DBUS_TYPE_INT32) |
1746 | + { |
1747 | + geis_error("malformed GeisEvent frame: expected %c, received %c", |
1748 | + DBUS_TYPE_INT32, type); |
1749 | + goto final_exit; |
1750 | + } |
1751 | + dbus_int32_t frame_id; |
1752 | + dbus_message_iter_get_basic(&dict_iter, &frame_id); |
1753 | + GeisFrame frame = geis_frame_new(frame_id); |
1754 | + geis_group_insert_frame(group, frame); |
1755 | + |
1756 | + dbus_message_iter_next(&dict_iter); |
1757 | + type = dbus_message_iter_get_arg_type(&dict_iter); |
1758 | + if (type != DBUS_TYPE_STRUCT) |
1759 | + { |
1760 | + geis_error("malformed GeisEvent frame: expected %c, received %c", |
1761 | + DBUS_TYPE_STRUCT, type); |
1762 | + } |
1763 | + else |
1764 | + { |
1765 | + DBusMessageIter struct_iter; |
1766 | + dbus_message_iter_recurse(&dict_iter, &struct_iter); |
1767 | + |
1768 | + type = dbus_message_iter_get_arg_type(&struct_iter); |
1769 | + if (type != DBUS_TYPE_ARRAY) |
1770 | + { |
1771 | + geis_error("malformed GeisEvent frame: expected %c, received %c", |
1772 | + DBUS_TYPE_ARRAY, type); |
1773 | + } |
1774 | + else |
1775 | + { |
1776 | + DBusMessageIter attr_iter; |
1777 | + dbus_message_iter_recurse(&struct_iter, &attr_iter); |
1778 | + for (int type = dbus_message_iter_get_arg_type(&attr_iter); |
1779 | + type != DBUS_TYPE_INVALID; |
1780 | + dbus_message_iter_next(&attr_iter), |
1781 | + type = dbus_message_iter_get_arg_type(&attr_iter)) |
1782 | + { |
1783 | + GeisAttr attr = geis_dbus_attr_unmarshall(&attr_iter); |
1784 | + geis_frame_add_attr(frame, attr); |
1785 | + } |
1786 | + } |
1787 | + |
1788 | + dbus_message_iter_next(&struct_iter), |
1789 | + type = dbus_message_iter_get_arg_type(&struct_iter); |
1790 | + if (type != DBUS_TYPE_ARRAY) |
1791 | + { |
1792 | + geis_error("malformed GeisEvent frame: expected %c, received %c", |
1793 | + DBUS_TYPE_ARRAY, type); |
1794 | + } |
1795 | + else |
1796 | + { |
1797 | + DBusMessageIter class_iter; |
1798 | + dbus_message_iter_recurse(&struct_iter, &class_iter); |
1799 | + for (int type = dbus_message_iter_get_arg_type(&class_iter); |
1800 | + type != DBUS_TYPE_INVALID; |
1801 | + dbus_message_iter_next(&class_iter), |
1802 | + type = dbus_message_iter_get_arg_type(&class_iter)) |
1803 | + { |
1804 | + type = dbus_message_iter_get_arg_type(&class_iter); |
1805 | + if (type != DBUS_TYPE_INT32) |
1806 | + { |
1807 | + geis_error("malformed GeisEvent frame: expected %c, received %c", |
1808 | + DBUS_TYPE_INT32, type); |
1809 | + break; |
1810 | + } |
1811 | + |
1812 | + dbus_int32_t class_id; |
1813 | + dbus_message_iter_get_basic(&class_iter, &class_id); |
1814 | + GeisGestureClassBag bag = geis_gesture_classes(geis); |
1815 | + for (GeisSize i = 0; i < geis_gesture_class_bag_count(bag); ++i) |
1816 | + { |
1817 | + GeisGestureClass gesture_class; |
1818 | + gesture_class = geis_gesture_class_bag_gesture_class(bag, i); |
1819 | + if (geis_gesture_class_id(gesture_class) == class_id) |
1820 | + { |
1821 | + geis_frame_set_is_class(frame, gesture_class); |
1822 | + break; |
1823 | + } |
1824 | + } |
1825 | + } |
1826 | + } |
1827 | + |
1828 | + dbus_message_iter_next(&struct_iter), |
1829 | + type = dbus_message_iter_get_arg_type(&struct_iter); |
1830 | + if (type != DBUS_TYPE_ARRAY) |
1831 | + { |
1832 | + geis_error("malformed GeisEvent frame: expected %c, received %c", |
1833 | + DBUS_TYPE_ARRAY, type); |
1834 | + } |
1835 | + else |
1836 | + { |
1837 | + DBusMessageIter touch_iter; |
1838 | + dbus_message_iter_recurse(&struct_iter, &touch_iter); |
1839 | + for (int type = dbus_message_iter_get_arg_type(&touch_iter); |
1840 | + type != DBUS_TYPE_INVALID; |
1841 | + dbus_message_iter_next(&touch_iter), |
1842 | + type = dbus_message_iter_get_arg_type(&touch_iter)) |
1843 | + { |
1844 | + type = dbus_message_iter_get_arg_type(&touch_iter); |
1845 | + if (type != DBUS_TYPE_INT32) |
1846 | + { |
1847 | + geis_error("malformed GeisEvent frame: expected %c, received %c", |
1848 | + DBUS_TYPE_INT32, type); |
1849 | + break; |
1850 | + } |
1851 | + |
1852 | + dbus_int32_t touch_id; |
1853 | + dbus_message_iter_get_basic(&touch_iter, &touch_id); |
1854 | + geis_frame_add_touchid(frame, touch_id); |
1855 | + } |
1856 | + } |
1857 | + } |
1858 | + |
1859 | +final_exit: |
1860 | + return; |
1861 | +} |
1862 | + |
1863 | + |
1864 | +/** |
1865 | + * Marshalls a GEIS groupset to a DBus message via a message iterator. |
1866 | + * @param[in] groupset The GEIS groupset. |
1867 | + * @param[in] iter A DBus message iterator. |
1868 | + */ |
1869 | +static void |
1870 | +_marshall_groupset(GeisGroupSet groupset, DBusMessageIter *iter) |
1871 | +{ |
1872 | + DBusMessageIter groupset_iter; |
1873 | + dbus_message_iter_open_container(iter, |
1874 | + DBUS_TYPE_ARRAY, |
1875 | + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING |
1876 | + DBUS_TYPE_INT32_AS_STRING |
1877 | + GEIS_DBUS_TYPE_SIGNATURE_FRAMESET |
1878 | + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, |
1879 | + &groupset_iter); |
1880 | + for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i) |
1881 | + { |
1882 | + GeisGroup group = geis_groupset_group(groupset, i); |
1883 | + if (!group) |
1884 | + { |
1885 | + geis_warning("can not extract group %zu from groupset", i); |
1886 | + goto final_exit; |
1887 | + } |
1888 | + DBusMessageIter group_iter; |
1889 | + dbus_message_iter_open_container(&groupset_iter, |
1890 | + DBUS_TYPE_DICT_ENTRY, |
1891 | + NULL, |
1892 | + &group_iter); |
1893 | + dbus_int32_t group_id = geis_group_id(group); |
1894 | + dbus_message_iter_append_basic(&group_iter, DBUS_TYPE_INT32, &group_id); |
1895 | + DBusMessageIter frameset_iter; |
1896 | + dbus_message_iter_open_container(&group_iter, |
1897 | + DBUS_TYPE_ARRAY, |
1898 | + GEIS_DBUS_TYPE_SIGNATURE_FRAME, |
1899 | + &frameset_iter); |
1900 | + for (GeisSize j = 0; j < geis_group_frame_count(group); ++j) |
1901 | + { |
1902 | + GeisFrame frame = geis_group_frame(group, j); |
1903 | + if (!frame) |
1904 | + { |
1905 | + geis_warning("can not extract frame %zu from group", j); |
1906 | + goto final_exit; |
1907 | + } |
1908 | + _marshall_frame(frame, &frameset_iter); |
1909 | + } |
1910 | + dbus_message_iter_close_container(&group_iter, &frameset_iter); |
1911 | + dbus_message_iter_close_container(&groupset_iter, &group_iter); |
1912 | + } |
1913 | + dbus_message_iter_close_container(iter, &groupset_iter); |
1914 | + |
1915 | +final_exit: |
1916 | + return; |
1917 | +} |
1918 | + |
1919 | + |
1920 | +static void |
1921 | +_unmarshall_groupset(Geis geis, DBusMessageIter *iter, GeisGroupSet groupset) |
1922 | +{ |
1923 | + int dtype = dbus_message_iter_get_arg_type(iter); |
1924 | + if (dtype != DBUS_TYPE_ARRAY) |
1925 | + { |
1926 | + geis_error("malformed GeisEvent groupset"); |
1927 | + } |
1928 | + |
1929 | + DBusMessageIter groupset_iter; |
1930 | + dbus_message_iter_recurse(iter, &groupset_iter); |
1931 | + for (dtype = dbus_message_iter_get_arg_type(&groupset_iter); |
1932 | + dtype != DBUS_TYPE_INVALID; |
1933 | + dbus_message_iter_next(&groupset_iter), |
1934 | + dtype = dbus_message_iter_get_arg_type(&groupset_iter)) |
1935 | + { |
1936 | + DBusMessageIter group_iter; |
1937 | + dbus_message_iter_recurse(&groupset_iter, &group_iter); |
1938 | + |
1939 | + int type = dbus_message_iter_get_arg_type(&group_iter); |
1940 | + if (type != DBUS_TYPE_INT32) |
1941 | + { |
1942 | + geis_error("malformed GeisEvent group"); |
1943 | + continue; |
1944 | + } |
1945 | + dbus_int32_t group_id; |
1946 | + dbus_message_iter_get_basic(&group_iter, &group_id); |
1947 | + GeisGroup group = geis_group_new(group_id); |
1948 | + geis_groupset_insert(groupset, group); |
1949 | + dbus_message_iter_next(&group_iter); |
1950 | + |
1951 | + DBusMessageIter frameset_iter; |
1952 | + dbus_message_iter_recurse(&group_iter, &frameset_iter); |
1953 | + for (int ftype = dbus_message_iter_get_arg_type(&frameset_iter); |
1954 | + ftype != DBUS_TYPE_INVALID; |
1955 | + dbus_message_iter_next(&frameset_iter), |
1956 | + ftype = dbus_message_iter_get_arg_type(&frameset_iter)) |
1957 | + { |
1958 | + _unmarshall_frame(geis, &frameset_iter, group); |
1959 | + } |
1960 | + } |
1961 | +} |
1962 | + |
1963 | + |
1964 | +/* |
1965 | + * Creates a Dbus "gesture event" message from a GEIS gesture event. |
1966 | + * |
1967 | + * A gesture event has the following structure. |
1968 | + * - a numeric event type (begin/update/end) |
1969 | + * - a set of one or more touches, where each touch has |
1970 | + * - a touch ID |
1971 | + * - a set of one or more attrs |
1972 | + * - a set of one or more gesture groups, where is group has |
1973 | + * - a group ID |
1974 | + * - a set of one or more gesture frames, where each frame has |
1975 | + * - a set of one or more gesture classes |
1976 | + * - a set of one or more gesture attrs |
1977 | + * - a zet of one or more touch indexes |
1978 | + * |
1979 | + * @todo add the gesture classes |
1980 | + */ |
1981 | +DBusMessage * |
1982 | +geis_dbus_gesture_event_message_from_geis_event(GeisEvent event) |
1983 | +{ |
1984 | + DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH, |
1985 | + GEIS_DBUS_SERVICE_INTERFACE, |
1986 | + GEIS_DBUS_GESTURE_EVENT); |
1987 | + DBusMessageIter iter; |
1988 | + dbus_message_iter_init_append(message, &iter); |
1989 | + |
1990 | + dbus_uint32_t event_type = geis_event_type(event); |
1991 | + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &event_type); |
1992 | + |
1993 | + GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET); |
1994 | + if (!attr) |
1995 | + { |
1996 | + geis_error("no touchset for gesture event"); |
1997 | + goto final_exit; |
1998 | + } |
1999 | + |
2000 | + GeisTouchSet touchset = geis_attr_value_to_pointer(attr); |
2001 | + if (!touchset) |
2002 | + { |
2003 | + geis_warning("can not convert attr to touchset"); |
2004 | + goto final_exit; |
2005 | + } |
2006 | + |
2007 | + _marshall_touchset(touchset, &iter); |
2008 | + |
2009 | + attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET); |
2010 | + if (!attr) |
2011 | + { |
2012 | + geis_error("no groupset for gesture event"); |
2013 | + goto final_exit; |
2014 | + } |
2015 | + |
2016 | + GeisGroupSet groupset = geis_attr_value_to_pointer(attr); |
2017 | + if (!groupset) |
2018 | + { |
2019 | + geis_warning("can not convert attr to groupset"); |
2020 | + goto final_exit; |
2021 | + } |
2022 | + |
2023 | + _marshall_groupset(groupset, &iter); |
2024 | + |
2025 | +final_exit: |
2026 | + return message; |
2027 | +} |
2028 | + |
2029 | + |
2030 | +/* |
2031 | + * Indicates if a DBus message is a "gesture event" message. |
2032 | + */ |
2033 | +GeisBoolean |
2034 | +geis_dbus_message_is_gesture_event(DBusMessage *message) |
2035 | +{ |
2036 | + GeisBoolean is_gesture_event_message = GEIS_FALSE; |
2037 | + if (dbus_message_is_signal(message, |
2038 | + GEIS_DBUS_SERVICE_INTERFACE, |
2039 | + GEIS_DBUS_GESTURE_EVENT)) |
2040 | + { |
2041 | + is_gesture_event_message = GEIS_TRUE; |
2042 | + } |
2043 | + |
2044 | + return is_gesture_event_message; |
2045 | +} |
2046 | + |
2047 | + |
2048 | +/* |
2049 | + * Creates GEIS event from a DBus "gesture_event" message. |
2050 | + */ |
2051 | +GeisEvent |
2052 | +geis_dbus_gesture_event_from_message(Geis geis, DBusMessage *message) |
2053 | +{ |
2054 | + DBusMessageIter iter; |
2055 | + dbus_message_iter_init(message, &iter); |
2056 | + |
2057 | + dbus_uint32_t event_type; |
2058 | + dbus_message_iter_get_basic(&iter, &event_type); |
2059 | + GeisEvent event = geis_event_new(event_type); |
2060 | + |
2061 | + dbus_message_iter_next(&iter); |
2062 | + GeisTouchSet touchset = geis_touchset_new(); |
2063 | + _unmarshall_touchset(&iter, touchset); |
2064 | + GeisAttr touch_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_TOUCHSET, |
2065 | + GEIS_ATTR_TYPE_POINTER, |
2066 | + touchset); |
2067 | + geis_attr_set_destructor(touch_attr, (GeisAttrDestructor)geis_touchset_delete); |
2068 | + geis_event_add_attr(event, touch_attr); |
2069 | + |
2070 | + dbus_message_iter_next(&iter); |
2071 | + GeisGroupSet groupset = geis_groupset_new(); |
2072 | + _unmarshall_groupset(geis, &iter, groupset); |
2073 | + GeisAttr group_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_GROUPSET, |
2074 | + GEIS_ATTR_TYPE_POINTER, |
2075 | + groupset); |
2076 | + geis_attr_set_destructor(group_attr, (GeisAttrDestructor)geis_groupset_delete); |
2077 | + geis_event_add_attr(event, group_attr); |
2078 | + |
2079 | + return event; |
2080 | +} |
2081 | + |
2082 | + |
2083 | |
2084 | === added file 'libs/geis-dbus/geis_dbus_gesture_event.h' |
2085 | --- libs/geis-dbus/geis_dbus_gesture_event.h 1970-01-01 00:00:00 +0000 |
2086 | +++ libs/geis-dbus/geis_dbus_gesture_event.h 2011-10-18 19:34:23 +0000 |
2087 | @@ -0,0 +1,55 @@ |
2088 | +/** |
2089 | + * @file geis_dbus_gesture_event.h |
2090 | + * @brief Interface for the GEIS DBus gesture event transport. |
2091 | + */ |
2092 | + |
2093 | +/* |
2094 | + * Copyright 2011 Canonical Ltd. |
2095 | + * |
2096 | + * This library is free software; you can redistribute it and/or modify it under |
2097 | + * the terms of the GNU Lesser General Public License as published by the Free |
2098 | + * Software Foundation; either version 3 of the License, or (at your option) any |
2099 | + * later version. |
2100 | + * |
2101 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
2102 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
2103 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
2104 | + * details. |
2105 | + * |
2106 | + * You should have received a copy of the GNU General Public License |
2107 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2108 | + */ |
2109 | +#ifndef GEIS_DBUS_GESTURE_EVENT_H_ |
2110 | +#define GEIS_DBUS_GESTURE_EVENT_H_ |
2111 | + |
2112 | +#include <dbus/dbus.h> |
2113 | +#include "geis/geis.h" |
2114 | + |
2115 | + |
2116 | +/** |
2117 | + * Creates a Dbus "gesture event" message from a GEIS gesture event. |
2118 | + * |
2119 | + * @param[in] event A GEIS event. |
2120 | + */ |
2121 | +DBusMessage * |
2122 | +geis_dbus_gesture_event_message_from_geis_event(GeisEvent event); |
2123 | + |
2124 | +/** |
2125 | + * Indicates if a DBus message is a "gesture event" message. |
2126 | + * |
2127 | + * @param[in] message A DBus message. |
2128 | + */ |
2129 | +GeisBoolean |
2130 | +geis_dbus_message_is_gesture_event(DBusMessage *message); |
2131 | + |
2132 | +/** |
2133 | + * Creates GEIS event from a DBus "gesture_event" message. |
2134 | + * |
2135 | + * @param[in] message A DBus message. |
2136 | + */ |
2137 | +GeisEvent |
2138 | +geis_dbus_gesture_event_from_message(Geis geis, DBusMessage *message); |
2139 | + |
2140 | + |
2141 | +#endif /* GEIS_DBUS_GESTURE_EVENT_H_ */ |
2142 | + |
2143 | |
2144 | === added file 'libs/geis-dbus/geis_dbus_region.c' |
2145 | --- libs/geis-dbus/geis_dbus_region.c 1970-01-01 00:00:00 +0000 |
2146 | +++ libs/geis-dbus/geis_dbus_region.c 2011-10-18 19:34:23 +0000 |
2147 | @@ -0,0 +1,91 @@ |
2148 | +/** |
2149 | + * @file geis_dbus_region.c |
2150 | + * @brief Implementations of the GEIS DBus region transport. |
2151 | + */ |
2152 | + |
2153 | +/* |
2154 | + * Copyright 2011 Canonical Ltd. |
2155 | + * |
2156 | + * This library is free software; you can redistribute it and/or modify it under |
2157 | + * the terms of the GNU Lesser General Public License as published by the Free |
2158 | + * Software Foundation; either version 3 of the License, or (at your option) any |
2159 | + * later version. |
2160 | + * |
2161 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
2162 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
2163 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
2164 | + * details. |
2165 | + * |
2166 | + * You should have received a copy of the GNU Lesser General Public License |
2167 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2168 | + */ |
2169 | +#include "geis_config.h" |
2170 | +#include "geis_dbus_region.h" |
2171 | + |
2172 | +#include "geis_dbus.h" |
2173 | +#include "geis_logging.h" |
2174 | + |
2175 | + |
2176 | +/* |
2177 | + * Creates a Dbus "region available" message from a GEIS region. |
2178 | + */ |
2179 | +DBusMessage * |
2180 | +geis_dbus_region_available_message_from_region(GeisFilterableAttribute fa) |
2181 | +{ |
2182 | + DBusMessage *message = dbus_message_new_signal(GEIS_DBUS_SERVICE_PATH, |
2183 | + GEIS_DBUS_SERVICE_INTERFACE, |
2184 | + GEIS_DBUS_REGION_AVAILABLE); |
2185 | + DBusMessageIter iter; |
2186 | + dbus_message_iter_init_append(message, &iter); |
2187 | + |
2188 | + const char *attr_name = fa->name; |
2189 | + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &attr_name); |
2190 | + |
2191 | + dbus_int32_t attr_type = fa->type; |
2192 | + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &attr_type); |
2193 | + |
2194 | + |
2195 | + return message; |
2196 | +} |
2197 | + |
2198 | + |
2199 | +/* |
2200 | + * Creates GEIS region filterable attribute from a DBus "region available" |
2201 | + * message. |
2202 | + */ |
2203 | +GeisFilterableAttribute |
2204 | +geis_dbus_region_from_region_available_message(DBusMessage *message) |
2205 | +{ |
2206 | + geis_debug("begins"); |
2207 | + static struct GeisFilterableAttribute attr; |
2208 | + DBusMessageIter iter; |
2209 | + dbus_message_iter_init(message, &iter); |
2210 | + |
2211 | + int type = dbus_message_iter_get_arg_type(&iter); |
2212 | + if (type != DBUS_TYPE_STRING) |
2213 | + { |
2214 | + geis_error("error getting attr name name from DBus message."); |
2215 | + goto final_exit; |
2216 | + } |
2217 | + char *attr_name; |
2218 | + dbus_message_iter_get_basic(&iter, &attr_name); |
2219 | + dbus_message_iter_next(&iter); |
2220 | + |
2221 | + type = dbus_message_iter_get_arg_type(&iter); |
2222 | + if (type != DBUS_TYPE_INT32) |
2223 | + { |
2224 | + geis_error("error getting attr type from DBus message."); |
2225 | + goto final_exit; |
2226 | + } |
2227 | + dbus_int32_t attr_type; |
2228 | + dbus_message_iter_get_basic(&iter, &attr_type); |
2229 | + |
2230 | + attr.name = attr_name; |
2231 | + attr.type = attr_type; |
2232 | + |
2233 | +final_exit: |
2234 | + geis_debug("ends"); |
2235 | + return &attr; |
2236 | +} |
2237 | + |
2238 | + |
2239 | |
2240 | === added file 'libs/geis-dbus/geis_dbus_region.h' |
2241 | --- libs/geis-dbus/geis_dbus_region.h 1970-01-01 00:00:00 +0000 |
2242 | +++ libs/geis-dbus/geis_dbus_region.h 2011-10-18 19:34:23 +0000 |
2243 | @@ -0,0 +1,47 @@ |
2244 | +/** |
2245 | + * @file geis_dbus_region.h |
2246 | + * @brief Interface for the GEIS DBus region transport. |
2247 | + */ |
2248 | + |
2249 | +/* |
2250 | + * Copyright 2011 Canonical Ltd. |
2251 | + * |
2252 | + * This library is free software; you can redistribute it and/or modify it under |
2253 | + * the terms of the GNU Lesser General Public License as published by the Free |
2254 | + * Software Foundation; either version 3 of the License, or (at your option) any |
2255 | + * later version. |
2256 | + * |
2257 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
2258 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
2259 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
2260 | + * details. |
2261 | + * |
2262 | + * You should have received a copy of the GNU General Public License |
2263 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2264 | + */ |
2265 | +#ifndef GEIS_DBUS_REGION_H_ |
2266 | +#define GEIS_DBUS_REGION_H_ |
2267 | + |
2268 | +#include <dbus/dbus.h> |
2269 | +#include "geis/geis.h" |
2270 | +#include "geis_filterable.h" |
2271 | + |
2272 | + |
2273 | +/** |
2274 | + * Creates a Dbus "region available" message from a GEIS region. |
2275 | + * |
2276 | + * @param[in] fa A GEIS region filterable attribute. |
2277 | + */ |
2278 | +DBusMessage * |
2279 | +geis_dbus_region_available_message_from_region(GeisFilterableAttribute fa); |
2280 | + |
2281 | +/** |
2282 | + * Creates GEIS region filterable attribute from a DBus "region available" |
2283 | + * message. |
2284 | + * |
2285 | + * @param[in] message A DBus message. |
2286 | + */ |
2287 | +GeisFilterableAttribute |
2288 | +geis_dbus_region_from_region_available_message(DBusMessage *message); |
2289 | + |
2290 | +#endif /* GEIS_DBUS_REGION_H_ */ |
2291 | |
2292 | === added file 'libs/geis-dbus/geis_dbus_subscription.c' |
2293 | --- libs/geis-dbus/geis_dbus_subscription.c 1970-01-01 00:00:00 +0000 |
2294 | +++ libs/geis-dbus/geis_dbus_subscription.c 2011-10-18 19:34:23 +0000 |
2295 | @@ -0,0 +1,506 @@ |
2296 | +/** |
2297 | + * @file geis_dbus_subscription.c |
2298 | + * @brief Implementation of the GEIS DBus subscription transport. |
2299 | + */ |
2300 | + |
2301 | +/* |
2302 | + * Copyright 2011 Canonical Ltd. |
2303 | + * |
2304 | + * This library is free software; you can redistribute it and/or modify it under |
2305 | + * the terms of the GNU Lesser General Public License as published by the Free |
2306 | + * Software Foundation; either version 3 of the License, or (at your option) any |
2307 | + * later version. |
2308 | + * |
2309 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
2310 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
2311 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
2312 | + * details. |
2313 | + * |
2314 | + * You should have received a copy of the GNU General Public License |
2315 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2316 | + */ |
2317 | +#include "geis_config.h" |
2318 | +#include "geis_dbus_subscription.h" |
2319 | + |
2320 | +#include "geis_dbus.h" |
2321 | +#include "geis_dbus_attr.h" |
2322 | +#include "geis_filter_term.h" |
2323 | +#include "geis_logging.h" |
2324 | +#include "geis_subscription.h" |
2325 | +#include <stdint.h> |
2326 | + |
2327 | + |
2328 | +/* |
2329 | + * A filter term is marshalled as a (facility, operation, value) tuple. |
2330 | + * That would be a (ii(sv)) in DBusspeak. |
2331 | + */ |
2332 | +#define GEIS_DBUS_TYPE_SIGNATURE_TERM \ |
2333 | + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ |
2334 | + DBUS_TYPE_INT32_AS_STRING \ |
2335 | + DBUS_TYPE_INT32_AS_STRING \ |
2336 | + GEIS_DBUS_TYPE_SIGNATURE_ATTR \ |
2337 | + DBUS_STRUCT_END_CHAR_AS_STRING |
2338 | + |
2339 | +/* |
2340 | + * A term list is an array of terms, as in a(ii(sv)). |
2341 | + */ |
2342 | +#define GEIS_DBUS_TYPE_SIGNATURE_TERM_LIST \ |
2343 | + DBUS_TYPE_ARRAY_AS_STRING \ |
2344 | + GEIS_DBUS_TYPE_SIGNATURE_TERM |
2345 | + |
2346 | +/* |
2347 | + * A filter is a named array of filter terms. |
2348 | + * That's a {sa(ii(sv))} in the DBus tongue. |
2349 | + */ |
2350 | +#define GEIS_DBUS_TYPE_SIGNATURE_FILTER \ |
2351 | + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \ |
2352 | + DBUS_TYPE_STRING_AS_STRING \ |
2353 | + GEIS_DBUS_TYPE_SIGNATURE_TERM_LIST \ |
2354 | + DBUS_DICT_ENTRY_END_CHAR_AS_STRING |
2355 | + |
2356 | + |
2357 | +/** |
2358 | + * Adds filter terms to a DBus message. |
2359 | + * |
2360 | + * @param[in] filter The filter for which terms will be marshalled. |
2361 | + * @param[in] filter_iter A DBus message output iterator. |
2362 | + */ |
2363 | +static void |
2364 | +_geis_dbus_marshall_subscription_filter_terms(GeisFilter filter, |
2365 | + DBusMessageIter *filter_iter) |
2366 | +{ |
2367 | + DBusMessageIter term_list_iter; |
2368 | + dbus_message_iter_open_container(filter_iter, |
2369 | + DBUS_TYPE_ARRAY, |
2370 | + GEIS_DBUS_TYPE_SIGNATURE_TERM, |
2371 | + &term_list_iter); |
2372 | + for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i) |
2373 | + { |
2374 | + GeisFilterTerm term = geis_filter_term(filter, i); |
2375 | + dbus_int32_t facility = geis_filter_term_facility(term); |
2376 | + dbus_int32_t operation = geis_filter_term_operation(term); |
2377 | + GeisAttr attr = geis_filter_term_attr(term); |
2378 | + |
2379 | + DBusMessageIter term_iter; |
2380 | + dbus_message_iter_open_container(&term_list_iter, |
2381 | + DBUS_TYPE_STRUCT, |
2382 | + NULL, |
2383 | + &term_iter); |
2384 | + dbus_message_iter_append_basic(&term_iter, DBUS_TYPE_INT32, &facility); |
2385 | + dbus_message_iter_append_basic(&term_iter, DBUS_TYPE_INT32, &operation); |
2386 | + geis_dbus_attr_marshall(attr, &term_iter); |
2387 | + dbus_message_iter_close_container(&term_list_iter, &term_iter); |
2388 | + } |
2389 | + dbus_message_iter_close_container(filter_iter, &term_list_iter); |
2390 | +} |
2391 | + |
2392 | + |
2393 | +/** |
2394 | + * Squeezes the filters on a subscription into the DBus wire protocol. |
2395 | + * |
2396 | + * @param[in] sub A %GeisSubscription |
2397 | + * @param[in] msg_iter The open output iterator for a DBus message. |
2398 | + * |
2399 | + * The filters are marshalled as an array of DBus dict entries. |
2400 | + */ |
2401 | +static void |
2402 | +_geis_dbus_marshall_subscription_filters(GeisSubscription subscription, |
2403 | + DBusMessageIter *msg_iter) |
2404 | +{ |
2405 | + DBusMessageIter filter_list_iter; |
2406 | + |
2407 | + dbus_message_iter_open_container(msg_iter, |
2408 | + DBUS_TYPE_ARRAY, |
2409 | + GEIS_DBUS_TYPE_SIGNATURE_FILTER, |
2410 | + &filter_list_iter); |
2411 | + |
2412 | + for (GeisFilterIterator it = geis_subscription_filter_begin(subscription); |
2413 | + it != geis_subscription_filter_end(subscription); |
2414 | + it = geis_subscription_filter_next(subscription, it)) |
2415 | + { |
2416 | + const char *filter_name = geis_filter_name(*it); |
2417 | + |
2418 | + DBusMessageIter filter_iter; |
2419 | + dbus_message_iter_open_container(&filter_list_iter, |
2420 | + DBUS_TYPE_DICT_ENTRY, |
2421 | + NULL, |
2422 | + &filter_iter); |
2423 | + dbus_message_iter_append_basic(&filter_iter, DBUS_TYPE_STRING, &filter_name); |
2424 | + _geis_dbus_marshall_subscription_filter_terms(*it, &filter_iter); |
2425 | + dbus_message_iter_close_container(&filter_list_iter, &filter_iter); |
2426 | + } |
2427 | + dbus_message_iter_close_container(msg_iter, &filter_list_iter); |
2428 | +} |
2429 | + |
2430 | + |
2431 | +static void |
2432 | +_geis_dbus_unmarshall_filter_terms(GeisFilter filter, |
2433 | + DBusMessageIter *filter_iter) |
2434 | +{ |
2435 | + DBusMessageIter term_list_iter; |
2436 | + dbus_message_iter_recurse(filter_iter, &term_list_iter); |
2437 | + for (int dtype = dbus_message_iter_get_arg_type(&term_list_iter); |
2438 | + dtype != DBUS_TYPE_INVALID; |
2439 | + dbus_message_iter_next(&term_list_iter), |
2440 | + dtype = dbus_message_iter_get_arg_type(&term_list_iter)) |
2441 | + { |
2442 | + int ttype = dbus_message_iter_get_arg_type(&term_list_iter); |
2443 | + if (ttype != DBUS_TYPE_STRUCT) |
2444 | + { |
2445 | + geis_error("malformed GeisSubscription term"); |
2446 | + goto final_exit; |
2447 | + } |
2448 | + |
2449 | + DBusMessageIter term_iter; |
2450 | + dbus_message_iter_recurse(&term_list_iter, &term_iter); |
2451 | + |
2452 | + dbus_int32_t facility; |
2453 | + dbus_message_iter_get_basic(&term_iter, &facility); |
2454 | + dbus_message_iter_next(&term_iter); |
2455 | + |
2456 | + dbus_int32_t operation; |
2457 | + dbus_message_iter_get_basic(&term_iter, &operation); |
2458 | + dbus_message_iter_next(&term_iter); |
2459 | + |
2460 | + GeisAttr attr = geis_dbus_attr_unmarshall(&term_iter); |
2461 | + GeisFilterTerm term = geis_filter_term_new(facility, operation, attr); |
2462 | + geis_filter_add_term_internal(filter, term); |
2463 | + } |
2464 | + |
2465 | +final_exit: |
2466 | + return; |
2467 | +} |
2468 | + |
2469 | + |
2470 | +/** |
2471 | + * Unmarshalls a filter from a DBus message. |
2472 | + * |
2473 | + * @param[in] geis A GEIS instance. |
2474 | + * @param[in] filter_iter A DBus message iterator pointing to the filter. |
2475 | + */ |
2476 | +static GeisFilter |
2477 | +_geis_dbus_unmarshall_filter(Geis geis, DBusMessageIter *filter_iter) |
2478 | +{ |
2479 | + GeisFilter filter = NULL; |
2480 | + |
2481 | + int ftype = dbus_message_iter_get_arg_type(filter_iter); |
2482 | + if (ftype != DBUS_TYPE_DICT_ENTRY) |
2483 | + { |
2484 | + geis_error("malformed GeisSubscription filter"); |
2485 | + goto final_exit; |
2486 | + } |
2487 | + |
2488 | + DBusMessageIter dict_iter; |
2489 | + dbus_message_iter_recurse(filter_iter, &dict_iter); |
2490 | + |
2491 | + ftype = dbus_message_iter_get_arg_type(&dict_iter); |
2492 | + if (ftype != DBUS_TYPE_STRING) |
2493 | + { |
2494 | + geis_error("malformed GeisSubscription filter"); |
2495 | + goto final_exit; |
2496 | + } |
2497 | + GeisString filter_name; |
2498 | + dbus_message_iter_get_basic(&dict_iter, &filter_name); |
2499 | + dbus_message_iter_next(&dict_iter); |
2500 | + |
2501 | + filter = geis_filter_new(geis, filter_name); |
2502 | + |
2503 | + ftype = dbus_message_iter_get_arg_type(&dict_iter); |
2504 | + if (ftype != DBUS_TYPE_ARRAY) |
2505 | + { |
2506 | + geis_error("malformed GeisSubscription filter"); |
2507 | + goto final_exit; |
2508 | + } |
2509 | + _geis_dbus_unmarshall_filter_terms(filter, &dict_iter); |
2510 | + |
2511 | +final_exit: |
2512 | + return filter; |
2513 | +} |
2514 | + |
2515 | + |
2516 | +/** |
2517 | + * Unmarshalls a list of filters from a DBus message. |
2518 | + * |
2519 | + * @param[in] geis A GEIS instance. |
2520 | + * @param[in] subscription_iter A DBus message iterator for the subscription. |
2521 | + * @param[in] subscription A GEIS subsccription. |
2522 | + * |
2523 | + * This function unmarshalls filters from a GEIS DBus subscription message and |
2524 | + * adds them to a existing GEIS subscription. |
2525 | + */ |
2526 | +static void |
2527 | +_geis_dbus_unmarshall_subscription_filters(Geis geis, |
2528 | + DBusMessageIter *subscription_iter, |
2529 | + GeisSubscription subscription) |
2530 | +{ |
2531 | + DBusMessageIter filter_list_iter; |
2532 | + dbus_message_iter_recurse(subscription_iter, &filter_list_iter); |
2533 | + for (int dtype = dbus_message_iter_get_arg_type(&filter_list_iter); |
2534 | + dtype != DBUS_TYPE_INVALID; |
2535 | + dbus_message_iter_next(&filter_list_iter), |
2536 | + dtype = dbus_message_iter_get_arg_type(&filter_list_iter)) |
2537 | + { |
2538 | + GeisFilter filter = _geis_dbus_unmarshall_filter(geis, &filter_list_iter); |
2539 | + if (filter) |
2540 | + { |
2541 | + geis_subscription_add_filter(subscription, filter); |
2542 | + } |
2543 | + } |
2544 | +} |
2545 | + |
2546 | + |
2547 | +/* |
2548 | + * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_CREATE method call. |
2549 | + */ |
2550 | +GeisBoolean |
2551 | +geis_dbus_message_is_subscription_create_call(DBusMessage *message) |
2552 | +{ |
2553 | + return dbus_message_is_method_call(message, |
2554 | + GEIS_DBUS_SERVICE_INTERFACE, |
2555 | + GEIS_DBUS_SUBSCRIPTION_CREATE); |
2556 | +} |
2557 | + |
2558 | + |
2559 | +/* |
2560 | + * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method call message. |
2561 | + */ |
2562 | +DBusMessage * |
2563 | +geis_dbus_subscription_create_call_message(GeisSubscription subscription) |
2564 | +{ |
2565 | + DBusMessage *message = NULL; |
2566 | + GeisString sub_name = "dummy"; |
2567 | + dbus_int32_t sub_id = -1; |
2568 | + dbus_uint32_t sub_flags = 0; |
2569 | + DBusMessageIter iter; |
2570 | + |
2571 | + message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, |
2572 | + GEIS_DBUS_SERVICE_PATH, |
2573 | + GEIS_DBUS_SERVICE_INTERFACE, |
2574 | + GEIS_DBUS_SUBSCRIPTION_CREATE); |
2575 | + |
2576 | + if (subscription) |
2577 | + { |
2578 | + sub_name = geis_subscription_name(subscription); |
2579 | + sub_id = geis_subscription_id(subscription); |
2580 | + sub_flags = geis_subscription_flags(subscription); |
2581 | + } |
2582 | + dbus_message_iter_init_append(message, &iter); |
2583 | + |
2584 | + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &sub_name); |
2585 | + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &sub_id); |
2586 | + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &sub_flags); |
2587 | + _geis_dbus_marshall_subscription_filters(subscription, &iter); |
2588 | + |
2589 | + return message; |
2590 | +} |
2591 | + |
2592 | + |
2593 | +/* |
2594 | + * Creates a %GeisSubscription from a method call message. |
2595 | + */ |
2596 | +GeisSubscription |
2597 | +geis_dbus_subscription_from_create_call_message(Geis geis, DBusMessage *message) |
2598 | +{ |
2599 | + DBusMessageIter message_iter; |
2600 | + dbus_message_iter_init(message, &message_iter); |
2601 | + |
2602 | + GeisString client_sub_name; |
2603 | + dbus_message_iter_get_basic(&message_iter, &client_sub_name); |
2604 | + dbus_message_iter_next(&message_iter); |
2605 | + |
2606 | + dbus_int32_t client_sub_id; |
2607 | + dbus_message_iter_get_basic(&message_iter, &client_sub_id); |
2608 | + dbus_message_iter_next(&message_iter); |
2609 | + |
2610 | + dbus_uint32_t client_sub_flags; |
2611 | + dbus_message_iter_get_basic(&message_iter, &client_sub_flags); |
2612 | + dbus_message_iter_next(&message_iter); |
2613 | + |
2614 | + GeisSubscription subscription = NULL; |
2615 | + subscription = geis_subscription_new(geis, client_sub_name, client_sub_flags); |
2616 | + if (!subscription) |
2617 | + { |
2618 | + geis_error("error creating proxy subscription"); |
2619 | + goto final_exit; |
2620 | + } |
2621 | + intptr_t fudge = client_sub_id; |
2622 | + geis_subscription_set_pdata(subscription, (GeisPointer)fudge); |
2623 | + |
2624 | + int dtype = dbus_message_iter_get_arg_type(&message_iter); |
2625 | + if (dtype != DBUS_TYPE_ARRAY) |
2626 | + { |
2627 | + geis_error("malformed GeisSubscription message" |
2628 | + " (expected type %c, received type %c)", |
2629 | + DBUS_TYPE_ARRAY, dtype); |
2630 | + goto final_exit; |
2631 | + } |
2632 | + |
2633 | + _geis_dbus_unmarshall_subscription_filters(geis, &message_iter, subscription); |
2634 | + |
2635 | +final_exit: |
2636 | + return subscription; |
2637 | +} |
2638 | + |
2639 | + |
2640 | +/* |
2641 | + * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method return message. |
2642 | + */ |
2643 | +DBusMessage * |
2644 | +geis_dbus_subscription_create_return_message(DBusMessage *message, |
2645 | + GeisSubscription subscription) |
2646 | +{ |
2647 | + DBusMessage *reply = dbus_message_new_method_return(message); |
2648 | + intptr_t fudge = (intptr_t)geis_subscription_pdata(subscription); |
2649 | + dbus_int32_t client_sub_id = fudge; |
2650 | + dbus_int32_t server_sub_id = geis_subscription_id(subscription); |
2651 | + dbus_message_append_args(reply, |
2652 | + DBUS_TYPE_INT32, &client_sub_id, |
2653 | + DBUS_TYPE_INT32, &server_sub_id, |
2654 | + DBUS_TYPE_INVALID); |
2655 | + |
2656 | + return reply; |
2657 | +} |
2658 | + |
2659 | + |
2660 | +/* |
2661 | + * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_ACTIVATE message. |
2662 | + */ |
2663 | +GeisBoolean |
2664 | +geis_dbus_message_is_subscription_activate_call(DBusMessage *message) |
2665 | +{ |
2666 | + return dbus_message_is_method_call(message, |
2667 | + GEIS_DBUS_SERVICE_INTERFACE, |
2668 | + GEIS_DBUS_SUBSCRIPTION_ACTIVATE); |
2669 | +} |
2670 | + |
2671 | + |
2672 | +/* |
2673 | + * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message. |
2674 | + */ |
2675 | +DBusMessage * |
2676 | +geis_dbus_subscription_activate_call_message(GeisSubscription subscription) |
2677 | +{ |
2678 | + DBusMessage *message = NULL; |
2679 | + DBusMessageIter iter; |
2680 | + |
2681 | + message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, |
2682 | + GEIS_DBUS_SERVICE_PATH, |
2683 | + GEIS_DBUS_SERVICE_INTERFACE, |
2684 | + GEIS_DBUS_SUBSCRIPTION_ACTIVATE); |
2685 | + dbus_message_iter_init_append(message, &iter); |
2686 | + |
2687 | + dbus_int32_t subscription_id = geis_subscription_id(subscription); |
2688 | + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &subscription_id); |
2689 | + _geis_dbus_marshall_subscription_filters(subscription, &iter); |
2690 | + return message; |
2691 | +} |
2692 | + |
2693 | + |
2694 | +/* |
2695 | + * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method return message. |
2696 | + */ |
2697 | +DBusMessage * |
2698 | +geis_dbus_subscription_activate_return_message(DBusMessage *message, |
2699 | + GeisSubscription subscription) |
2700 | +{ |
2701 | + DBusMessage *reply = NULL; |
2702 | + reply = dbus_message_new_method_return(message); |
2703 | + dbus_int32_t subscription_id = -1; |
2704 | + |
2705 | + if (subscription) |
2706 | + { |
2707 | + subscription_id = geis_subscription_id(subscription); |
2708 | + } |
2709 | + dbus_message_append_args(reply, |
2710 | + DBUS_TYPE_INT32, &subscription_id, |
2711 | + DBUS_TYPE_INVALID); |
2712 | + return reply; |
2713 | +} |
2714 | + |
2715 | + |
2716 | +/* |
2717 | + * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE message. |
2718 | + */ |
2719 | +GeisBoolean |
2720 | +geis_dbus_message_is_subscription_deactivate_call(DBusMessage *message) |
2721 | +{ |
2722 | + return dbus_message_is_method_call(message, |
2723 | + GEIS_DBUS_SERVICE_INTERFACE, |
2724 | + GEIS_DBUS_SUBSCRIPTION_DEACTIVATE); |
2725 | +} |
2726 | + |
2727 | + |
2728 | +/* |
2729 | + * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message. |
2730 | + */ |
2731 | +DBusMessage * |
2732 | +geis_dbus_subscription_deactivate_call_message(GeisSubscription subscription GEIS_UNUSED) |
2733 | +{ |
2734 | + DBusMessage *message = NULL; |
2735 | + message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, |
2736 | + GEIS_DBUS_SERVICE_PATH, |
2737 | + GEIS_DBUS_SERVICE_INTERFACE, |
2738 | + GEIS_DBUS_SUBSCRIPTION_DEACTIVATE); |
2739 | + return message; |
2740 | +} |
2741 | + |
2742 | + |
2743 | +/** |
2744 | + */ |
2745 | +DBusMessage * |
2746 | +geis_dbus_subscription_deactivate_return_message(DBusMessage *message, |
2747 | + GeisSubscription subscription) |
2748 | +{ |
2749 | + DBusMessage *reply = NULL; |
2750 | + reply = dbus_message_new_method_return(message); |
2751 | + dbus_int32_t subscription_id = geis_subscription_id(subscription); |
2752 | + dbus_message_append_args(reply, |
2753 | + DBUS_TYPE_INT32, &subscription_id, |
2754 | + DBUS_TYPE_INVALID); |
2755 | + return reply; |
2756 | +} |
2757 | + |
2758 | + |
2759 | +/* |
2760 | + * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DESTROY message. |
2761 | + */ |
2762 | +GeisBoolean |
2763 | +geis_dbus_message_is_subscription_destroy_call(DBusMessage *message) |
2764 | +{ |
2765 | + return dbus_message_is_method_call(message, |
2766 | + GEIS_DBUS_SERVICE_INTERFACE, |
2767 | + GEIS_DBUS_SUBSCRIPTION_DESTROY); |
2768 | +} |
2769 | + |
2770 | + |
2771 | +/* |
2772 | + * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method call message. |
2773 | + */ |
2774 | +DBusMessage * |
2775 | +geis_dbus_subscription_destroy_call_message(GeisSubscription subscription) |
2776 | +{ |
2777 | + DBusMessage *message = NULL; |
2778 | + message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, |
2779 | + GEIS_DBUS_SERVICE_PATH, |
2780 | + GEIS_DBUS_SERVICE_INTERFACE, |
2781 | + GEIS_DBUS_SUBSCRIPTION_DESTROY); |
2782 | + |
2783 | + dbus_int32_t server_sub_id = (intptr_t)geis_subscription_pdata(subscription); |
2784 | + dbus_message_append_args(message, |
2785 | + DBUS_TYPE_INT32, &server_sub_id, |
2786 | + DBUS_TYPE_INVALID); |
2787 | + |
2788 | + return message; |
2789 | +} |
2790 | + |
2791 | + |
2792 | +/* |
2793 | + * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method return message. |
2794 | + */ |
2795 | +DBusMessage * |
2796 | +geis_dbus_subscription_destroy_return_message(DBusMessage *message) |
2797 | +{ |
2798 | + return dbus_message_new_method_return(message); |
2799 | +} |
2800 | + |
2801 | + |
2802 | |
2803 | === added file 'libs/geis-dbus/geis_dbus_subscription.h' |
2804 | --- libs/geis-dbus/geis_dbus_subscription.h 1970-01-01 00:00:00 +0000 |
2805 | +++ libs/geis-dbus/geis_dbus_subscription.h 2011-10-18 19:34:23 +0000 |
2806 | @@ -0,0 +1,206 @@ |
2807 | +/** |
2808 | + * @file geis_dbus_subscription.h |
2809 | + * @brief Interface for the GEIS DBus subscription transport. |
2810 | + */ |
2811 | + |
2812 | +/* |
2813 | + * Copyright 2011 Canonical Ltd. |
2814 | + * |
2815 | + * This library is free software; you can redistribute it and/or modify it under |
2816 | + * the terms of the GNU Lesser General Public License as published by the Free |
2817 | + * Software Foundation; either version 3 of the License, or (at your option) any |
2818 | + * later version. |
2819 | + * |
2820 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
2821 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
2822 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
2823 | + * details. |
2824 | + * |
2825 | + * You should have received a copy of the GNU General Public License |
2826 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2827 | + */ |
2828 | +#ifndef GEIS_DBUS_SUBSCRIPTION_H_ |
2829 | +#define GEIS_DBUS_SUBSCRIPTION_H_ |
2830 | + |
2831 | +#include <dbus/dbus.h> |
2832 | +#include "geis/geis.h" |
2833 | + |
2834 | + |
2835 | +/** |
2836 | + * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_CREATE method call. |
2837 | + * |
2838 | + * @param[in] message A DBus message. |
2839 | + * |
2840 | + * This function is used on the server side to identify if a received message is |
2841 | + * a GEIS_DBUS_SUBSCRIPTION_CREATE method call. |
2842 | + * |
2843 | + * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_CREATE, |
2844 | + * GEIS_FALSE otherwise. |
2845 | + */ |
2846 | +GeisBoolean |
2847 | +geis_dbus_message_is_subscription_create_call(DBusMessage *message); |
2848 | + |
2849 | +/** |
2850 | + * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method call message. |
2851 | + * |
2852 | + * @param[in] subscription A GEIS subscription. |
2853 | + * |
2854 | + * This function is used on the client side to create a |
2855 | + * GEIS_DBUS_SUBSCRIPTION_CREATE method call message from a local |
2856 | + * %GeisSubscription object. |
2857 | + * |
2858 | + * @returns A DBus message object. |
2859 | + */ |
2860 | +DBusMessage * |
2861 | +geis_dbus_subscription_create_call_message(GeisSubscription subscription); |
2862 | + |
2863 | +/** |
2864 | + * Creates a %GeisSubscription from a GEIS_DBUS_SUBSCRIPTION_CREATE method call |
2865 | + * message. |
2866 | + * |
2867 | + * @param[in] geis A %Geis instance. |
2868 | + * @param[in] message A DBus message. |
2869 | + * |
2870 | + * This function is used on the server side to create a subscription object to |
2871 | + * proxy the client-side subscription object. |
2872 | + * |
2873 | + * @returns a %GeisSubscription or NULL on failure. |
2874 | + */ |
2875 | +GeisSubscription |
2876 | +geis_dbus_subscription_from_create_call_message(Geis geis, DBusMessage *message); |
2877 | + |
2878 | +/** |
2879 | + * Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method return message. |
2880 | + * |
2881 | + * @param[in] message The DBUs method_call message to reply to. |
2882 | + * @param[in] subscription A GEIS subscription. |
2883 | + * |
2884 | + * This function is used on the server side to create a response to a received |
2885 | + * GEIS_DBUS_SUBSCRIPTION_CREATE method call message. |
2886 | + * |
2887 | + * @returns A DBus message object. |
2888 | + */ |
2889 | +DBusMessage * |
2890 | +geis_dbus_subscription_create_return_message(DBusMessage *message, |
2891 | + GeisSubscription subscription); |
2892 | + |
2893 | +/** |
2894 | + * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_ACTIVATE message. |
2895 | + * |
2896 | + * @param[in] message A DBus message. |
2897 | + * |
2898 | + * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_ACTIVATE, |
2899 | + * GEIS_FALSE otherwise. |
2900 | + */ |
2901 | +GeisBoolean |
2902 | +geis_dbus_message_is_subscription_activate_call(DBusMessage *message); |
2903 | + |
2904 | +/** |
2905 | + * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message. |
2906 | + * |
2907 | + * @param[in] subscription A GEIS subscription. |
2908 | + * |
2909 | + * This function is used on the client side to create a |
2910 | + * GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message from a local |
2911 | + * %GeisSubscription object. |
2912 | + * |
2913 | + * @returns A DBus message object. |
2914 | + */ |
2915 | +DBusMessage * |
2916 | +geis_dbus_subscription_activate_call_message(GeisSubscription subscription); |
2917 | + |
2918 | +/** |
2919 | + * Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method return message. |
2920 | + * |
2921 | + * @param[in] message The DBUs method_call message to reply to. |
2922 | + * @param[in] subscription A GEIS subscription. |
2923 | + * |
2924 | + * This function is used on the server side to create a response to a received |
2925 | + * GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message. |
2926 | + * |
2927 | + * @returns A DBus message object. |
2928 | + */ |
2929 | +DBusMessage * |
2930 | +geis_dbus_subscription_activate_return_message(DBusMessage *message, |
2931 | + GeisSubscription subscription); |
2932 | + |
2933 | +/** |
2934 | + * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE message. |
2935 | + * |
2936 | + * @param[in] message A DBus message. |
2937 | + * |
2938 | + * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_DEACTIVATE, |
2939 | + * GEIS_FALSE otherwise. |
2940 | + */ |
2941 | +GeisBoolean |
2942 | +geis_dbus_message_is_subscription_deactivate_call(DBusMessage *message); |
2943 | + |
2944 | +/** |
2945 | + * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method return message. |
2946 | + * |
2947 | + * @param[in] message The DBUs method_call message to reply to. |
2948 | + * @param[in] subscription A GEIS subscription. |
2949 | + * |
2950 | + * This function is used on the server side to create a response to a received |
2951 | + * GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message. |
2952 | + * |
2953 | + * @returns A DBus message object. |
2954 | + */ |
2955 | +DBusMessage * |
2956 | +geis_dbus_subscription_deactivate_return_message(DBusMessage *message, |
2957 | + GeisSubscription subscription); |
2958 | + |
2959 | +/** |
2960 | + * Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message. |
2961 | + * |
2962 | + * @param[in] subscription A GEIS subscription. |
2963 | + * |
2964 | + * This function is used on the client side to create a |
2965 | + * GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message from a local |
2966 | + * %GeisSubscription object. |
2967 | + * |
2968 | + * @returns A DBus message object. |
2969 | + */ |
2970 | +DBusMessage * |
2971 | +geis_dbus_subscription_deactivate_call_message(GeisSubscription subscription); |
2972 | + |
2973 | +/** |
2974 | + * Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DESTROY message. |
2975 | + * |
2976 | + * @param[in] message A DBus message. |
2977 | + * |
2978 | + * @returns GEIS_TRUE if the message is GEIS_DBUS_SUBSCRIPTION_DESTROY, |
2979 | + * GEIS_FALSE otherwise. |
2980 | + */ |
2981 | +GeisBoolean |
2982 | +geis_dbus_message_is_subscription_destroy_call(DBusMessage *message); |
2983 | + |
2984 | +/** |
2985 | + * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method call message. |
2986 | + * |
2987 | + * @param[in] subscription A GEIS subscription. |
2988 | + * |
2989 | + * This function is used on the client side to create a |
2990 | + * GEIS_DBUS_SUBSCRIPTION_DESTROY method call message from a local |
2991 | + * %GeisSubscription object. |
2992 | + * |
2993 | + * @returns A DBus message object. |
2994 | + */ |
2995 | +DBusMessage * |
2996 | +geis_dbus_subscription_destroy_call_message(GeisSubscription subscription); |
2997 | + |
2998 | +/** |
2999 | + * Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method return message. |
3000 | + * |
3001 | + * @param[in] message The DBUs method_call message to reply to. |
3002 | + * |
3003 | + * This function is used on the server side to create a response to a received |
3004 | + * GEIS_DBUS_SUBSCRIPTION_DESTROY method call message. |
3005 | + * |
3006 | + * @returns A DBus message object. |
3007 | + */ |
3008 | +DBusMessage * |
3009 | +geis_dbus_subscription_destroy_return_message(DBusMessage *message); |
3010 | + |
3011 | + |
3012 | +#endif /* GEIS_DBUS_SUBSCRIPTION_H_ */ |
3013 | |
3014 | === modified file 'libutouch-geis/Makefile.am' |
3015 | --- libutouch-geis/Makefile.am 2011-08-17 15:48:51 +0000 |
3016 | +++ libutouch-geis/Makefile.am 2011-10-18 19:34:23 +0000 |
3017 | @@ -39,6 +39,7 @@ |
3018 | geis_event.h geis_event.c \ |
3019 | geis_event_queue.h geis_event_queue.c \ |
3020 | geis_filter.h geis_filter.c \ |
3021 | + geis_filterable.h geis_filterable.c \ |
3022 | geis_filter_term.h geis_filter_term.c \ |
3023 | geis_frame.h geis_frame.c \ |
3024 | geis_gesture_flick.h geis_gesture_flick.c \ |
3025 | @@ -56,6 +57,8 @@ |
3026 | -I$(top_srcdir) \ |
3027 | -I$(top_srcdir)/include \ |
3028 | -I$(srcdir)/backend \ |
3029 | + -I$(top_srcdir)/libs/geis-dbus \ |
3030 | + $(DBUS_CFLAGS) \ |
3031 | $(GRAIL_CFLAGS) |
3032 | |
3033 | libutouch_geis_la_LDFLAGS = \ |
3034 | @@ -66,8 +69,10 @@ |
3035 | |
3036 | libutouch_geis_la_LIBADD = \ |
3037 | ${builddir}/backend/test_fixture/libutouch-geis-test-fixture.la \ |
3038 | + ${builddir}/backend/dbus/libutouch-geis-dbus-backend.la \ |
3039 | ${builddir}/backend/xcb/libutouch-geis-xcb-backend.la \ |
3040 | ${builddir}/server/libutouch-geis-dbus-server.la \ |
3041 | + $(top_builddir)/libs/geis-dbus/libgeis-dbus.la \ |
3042 | $(top_builddir)/libs/xcb/libxcb-gesture.la |
3043 | |
3044 | EXTRA_DIST = $(version_script) |
3045 | |
3046 | === modified file 'libutouch-geis/backend/Makefile.am' |
3047 | --- libutouch-geis/backend/Makefile.am 2011-01-17 14:58:27 +0000 |
3048 | +++ libutouch-geis/backend/Makefile.am 2011-10-18 19:34:23 +0000 |
3049 | @@ -19,5 +19,5 @@ |
3050 | # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
3051 | # |
3052 | |
3053 | -SUBDIRS = test_fixture xcb |
3054 | +SUBDIRS = test_fixture xcb dbus |
3055 | |
3056 | |
3057 | === added directory 'libutouch-geis/backend/dbus' |
3058 | === added file 'libutouch-geis/backend/dbus/Makefile.am' |
3059 | --- libutouch-geis/backend/dbus/Makefile.am 1970-01-01 00:00:00 +0000 |
3060 | +++ libutouch-geis/backend/dbus/Makefile.am 2011-10-18 19:34:23 +0000 |
3061 | @@ -0,0 +1,34 @@ |
3062 | +# |
3063 | +# @file libutouch-geis/backend/xcb/Makefile.am |
3064 | +# @brief automake recipe for the uTouch GEIS v2.0 XCB back end |
3065 | +# |
3066 | +# Copyright 2011 Canonical, Ltd. |
3067 | +# |
3068 | +# This file is part of the utouch-geis library. This library is free software; |
3069 | +# you can redistribute it and/or modify it under the terms of the GNU Lesser |
3070 | +# General Public License as published by the Free Software Foundation; either |
3071 | +# version 3 of the License, or (at your option) any later version. |
3072 | +# |
3073 | +# This library is distributed in the hope that it will be useful, but WITHOUT |
3074 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
3075 | +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
3076 | +# details. |
3077 | +# |
3078 | +# You should have received a copy of the GNU General Public License |
3079 | +# along with this program. If not, see <http://www.gnu.org/licenses/ |
3080 | +# |
3081 | + |
3082 | +noinst_LTLIBRARIES = libutouch-geis-dbus-backend.la |
3083 | + |
3084 | +libutouch_geis_dbus_backend_la_SOURCES = \ |
3085 | + geis_dbus_backend.c \ |
3086 | + geis_dbus_client.h geis_dbus_client.c \ |
3087 | + geis_dbus_locator.h geis_dbus_locator.c |
3088 | + |
3089 | +libutouch_geis_dbus_backend_la_CPPFLAGS = \ |
3090 | + -I$(top_srcdir) \ |
3091 | + -I$(top_srcdir)/libs/geis-dbus \ |
3092 | + -I$(top_srcdir)/include \ |
3093 | + -I$(top_srcdir)/libutouch-geis \ |
3094 | + $(DBUS_CFLAGS) |
3095 | + |
3096 | |
3097 | === added file 'libutouch-geis/backend/dbus/geis_dbus_backend.c' |
3098 | --- libutouch-geis/backend/dbus/geis_dbus_backend.c 1970-01-01 00:00:00 +0000 |
3099 | +++ libutouch-geis/backend/dbus/geis_dbus_backend.c 2011-10-18 19:34:23 +0000 |
3100 | @@ -0,0 +1,249 @@ |
3101 | +/** |
3102 | + * @file geis_dbus_backend.c |
3103 | + * @brief GEIS DBus client back end |
3104 | + */ |
3105 | + |
3106 | +/* |
3107 | + * Copyright 2011 Canonical Ltd. |
3108 | + * |
3109 | + * This library is free software; you can redistribute it and/or modify it under |
3110 | + * the terms of the GNU Lesser General Public License as published by the Free |
3111 | + * Software Foundation; either version 3 of the License, or (at your option) any |
3112 | + * later version. |
3113 | + * |
3114 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
3115 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
3116 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
3117 | + * details. |
3118 | + * |
3119 | + * You should have received a copy of the GNU General Public License |
3120 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3121 | + */ |
3122 | +#include "geis_config.h" |
3123 | +#include "geis_backend.h" |
3124 | +#include "geis_backend_protected.h" |
3125 | + |
3126 | +#include "geis_dbus_client.h" |
3127 | +#include "geis_event.h" |
3128 | +#include "geis_logging.h" |
3129 | +#include "geis_private.h" |
3130 | + |
3131 | + |
3132 | +/** |
3133 | + * @addtogroup geis_backend_dbus GEIS DBus Back End |
3134 | + * @ingroup geis_backends |
3135 | + * |
3136 | + * A GEIS Back End that is a DBus client, for connecting to a single central |
3137 | + * GEIS service offering data over the DBus. |
3138 | + * |
3139 | + * @{ |
3140 | + */ |
3141 | + |
3142 | +/** The opaque DBus Back End type. */ |
3143 | +typedef struct GeisDBusBackend *GeisDBusBackend; |
3144 | + |
3145 | +/** The less opaque DBus Back End structure. */ |
3146 | +struct GeisDBusBackend |
3147 | +{ |
3148 | + Geis geis; |
3149 | + GeisDBusClient dbus_client; |
3150 | +}; |
3151 | + |
3152 | +/** The DBus Back End token type */ |
3153 | +typedef struct GeisDBusToken |
3154 | +{ |
3155 | + struct GeisBackendToken base; |
3156 | + GeisDBusBackend be; |
3157 | +} *GeisDBusToken; |
3158 | + |
3159 | + |
3160 | +/** |
3161 | + * Converts from a GeisBackendToken to an XcbBackendToken. |
3162 | + */ |
3163 | +static inline GeisDBusToken |
3164 | +_geis_dbus_token_from_geis_token(GeisBackendToken gbt) |
3165 | +{ |
3166 | + return (GeisDBusToken)gbt; |
3167 | +} |
3168 | + |
3169 | + |
3170 | +/** |
3171 | + * Allocates memory for a token from a pool. |
3172 | + */ |
3173 | +static GeisDBusToken |
3174 | +_geis_dbus_token_allocate(void) |
3175 | +{ |
3176 | + return calloc(1, sizeof(struct GeisDBusToken)); |
3177 | +} |
3178 | + |
3179 | + |
3180 | +/** |
3181 | + * Returns memory for a token to a pool. |
3182 | + */ |
3183 | +static void |
3184 | +_geis_dbus_token_deallocate(GeisDBusToken gdt) |
3185 | +{ |
3186 | + free(gdt); |
3187 | +} |
3188 | + |
3189 | + |
3190 | +/** |
3191 | + * Deep-copy-constructs a token. |
3192 | + */ |
3193 | +static GeisBackendToken |
3194 | +_geis_dbus_token_clone(GeisBackendToken original) |
3195 | +{ |
3196 | + return original; |
3197 | +} |
3198 | + |
3199 | + |
3200 | +/** |
3201 | + * Releases resources for a token. |
3202 | + * |
3203 | + * @param[in] token A %GeisDBusToken. |
3204 | + */ |
3205 | +static void |
3206 | +_geis_dbus_token_finalize(GeisBackendToken token GEIS_UNUSED) |
3207 | +{ |
3208 | + GeisDBusToken gdt = _geis_dbus_token_from_geis_token(token); |
3209 | + _geis_dbus_token_deallocate(gdt); |
3210 | +} |
3211 | + |
3212 | + |
3213 | +/** |
3214 | + * Composes one token onto another. |
3215 | + * |
3216 | + * @param[in,out] lhs |
3217 | + * @param[in] rhs |
3218 | + */ |
3219 | +static void |
3220 | +_geis_dbus_token_compose(GeisBackendToken lhs GEIS_UNUSED, |
3221 | + GeisBackendToken rhs GEIS_UNUSED) |
3222 | +{ |
3223 | +} |
3224 | + |
3225 | + |
3226 | +/** |
3227 | + * Activates a DBus back end token. |
3228 | + * |
3229 | + * @param[in] token A %GeisDBusToken. |
3230 | + * @param[in] subscription The subscrition the token will be activated on. |
3231 | + * |
3232 | + * Sends a request to the server to activate a subscription with the tokenized |
3233 | + * content. |
3234 | + * |
3235 | + * @returns GEIS_STATUS_SUCCESS. |
3236 | + */ |
3237 | +static GeisStatus |
3238 | +_geis_dbus_token_activate(GeisBackendToken token, GeisSubscription subscription) |
3239 | +{ |
3240 | + GeisDBusToken gdt = _geis_dbus_token_from_geis_token(token); |
3241 | + geis_dbus_client_subscribe(gdt->be->dbus_client, subscription); |
3242 | + return GEIS_STATUS_SUCCESS; |
3243 | +} |
3244 | + |
3245 | + |
3246 | +/** |
3247 | + * Deactivates a DBus back end token. |
3248 | + * |
3249 | + * @param[in] token A %GeisDBusToken. |
3250 | + */ |
3251 | +static GeisStatus |
3252 | +_geis_dbus_token_deactivate(GeisBackendToken token, GeisSubscription subscription) |
3253 | +{ |
3254 | + GeisDBusToken gdt = _geis_dbus_token_from_geis_token(token); |
3255 | + geis_dbus_client_unsubscribe(gdt->be->dbus_client, subscription); |
3256 | + return GEIS_STATUS_UNKNOWN_ERROR; |
3257 | +} |
3258 | + |
3259 | + |
3260 | +static struct GeisBackendTokenVtable _token_vtbl = { |
3261 | + _geis_dbus_token_clone, |
3262 | + _geis_dbus_token_finalize, |
3263 | + _geis_dbus_token_compose, |
3264 | + _geis_dbus_token_activate, |
3265 | + _geis_dbus_token_deactivate, |
3266 | +}; |
3267 | + |
3268 | + |
3269 | +/** |
3270 | + * Constructs a DBus back end. |
3271 | + * |
3272 | + * @param[in] mem |
3273 | + * @param[in] geis |
3274 | + */ |
3275 | +static void |
3276 | +_geis_dbus_backend_construct(void *mem, Geis geis) |
3277 | +{ |
3278 | + GeisDBusBackend gdb = (GeisDBusBackend)mem; |
3279 | + gdb->geis = geis; |
3280 | + |
3281 | + gdb->dbus_client = geis_dbus_client_new(geis); |
3282 | + if (!gdb->dbus_client) |
3283 | + { |
3284 | + geis_error("error creating GEIS DBus client"); |
3285 | + goto final_exit; |
3286 | + } |
3287 | + |
3288 | +final_exit: |
3289 | + return; |
3290 | +} |
3291 | + |
3292 | + |
3293 | +/** |
3294 | + * Deconstructs a DBus back end. |
3295 | + * |
3296 | + * @param[in] be A %GeisDBusBackend. |
3297 | + */ |
3298 | +static void |
3299 | +_geis_dbus_backend_finalize(GeisBackend be) |
3300 | +{ |
3301 | + GeisDBusBackend gdb = (GeisDBusBackend)be; |
3302 | + geis_dbus_client_delete(gdb->dbus_client); |
3303 | +} |
3304 | + |
3305 | + |
3306 | +/** |
3307 | + * Creates DBus-back-end-specific back end token. |
3308 | + */ |
3309 | +static GeisBackendToken |
3310 | +_geis_dbus_backend_create_token(GeisBackend be, |
3311 | + GeisBackendTokenInitState init_state GEIS_UNUSED) |
3312 | +{ |
3313 | + GeisDBusBackend gdb = (GeisDBusBackend)be; |
3314 | + GeisDBusToken token = _geis_dbus_token_allocate(); |
3315 | + if (token) |
3316 | + { |
3317 | + token->base.vtbl = &_token_vtbl; |
3318 | + token->be = gdb; |
3319 | + } |
3320 | + return (GeisBackendToken)token; |
3321 | +} |
3322 | + |
3323 | + |
3324 | +static struct GeisBackendVtable gdb_vtbl = { |
3325 | + _geis_dbus_backend_construct, |
3326 | + _geis_dbus_backend_finalize, |
3327 | + _geis_dbus_backend_create_token, |
3328 | +}; |
3329 | + |
3330 | + |
3331 | +/** |
3332 | + * Registers the back end with the GEIS back end registry. |
3333 | + */ |
3334 | +static void __attribute__((constructor)) |
3335 | +_register_dbus_backend(void) |
3336 | +{ |
3337 | + geis_register_backend(GEIS_INIT_UTOUCH_DBUS_BACKEND, |
3338 | + sizeof(struct GeisDBusBackend), |
3339 | + &gdb_vtbl); |
3340 | +} |
3341 | + |
3342 | + |
3343 | +/** A dummy routine to force linkage of this module without dlopening it */ |
3344 | +void |
3345 | +geis_include_dbus_backend(void) |
3346 | +{ |
3347 | +} |
3348 | + |
3349 | +/** @} */ |
3350 | |
3351 | === added file 'libutouch-geis/backend/dbus/geis_dbus_client.c' |
3352 | --- libutouch-geis/backend/dbus/geis_dbus_client.c 1970-01-01 00:00:00 +0000 |
3353 | +++ libutouch-geis/backend/dbus/geis_dbus_client.c 2011-10-18 19:34:23 +0000 |
3354 | @@ -0,0 +1,685 @@ |
3355 | +/** |
3356 | + * @file geis_dbus_client.c |
3357 | + * @brief Implementations of the GEIS DBus client. |
3358 | + */ |
3359 | + |
3360 | +/* |
3361 | + * Copyright 2011 Canonical Ltd. |
3362 | + * |
3363 | + * This library is free software; you can redistribute it and/or modify it under |
3364 | + * the terms of the GNU Lesser General Public License as published by the Free |
3365 | + * Software Foundation; either version 3 of the License, or (at your option) any |
3366 | + * later version. |
3367 | + * |
3368 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
3369 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
3370 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
3371 | + * details. |
3372 | + * |
3373 | + * You should have received a copy of the GNU General Public License |
3374 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3375 | + */ |
3376 | +#include "geis_config.h" |
3377 | +#include "geis_dbus_client.h" |
3378 | + |
3379 | +#include "geis_dbus.h" |
3380 | +#include "geis_dbus_class.h" |
3381 | +#include "geis_dbus_device.h" |
3382 | +#include "geis_dbus_gesture_event.h" |
3383 | +#include "geis_dbus_locator.h" |
3384 | +#include "geis_dbus_region.h" |
3385 | +#include "geis_dbus_subscription.h" |
3386 | +#include "geis_event.h" |
3387 | +#include "geis_logging.h" |
3388 | +#include "geis_private.h" |
3389 | +#include <stdio.h> |
3390 | +#include <stdlib.h> |
3391 | + |
3392 | + |
3393 | +typedef enum GeisDBusClientState |
3394 | +{ |
3395 | + GEIS_DBUS_CLIENT_DISCONNECTED, /* no server available */ |
3396 | + GEIS_DBUS_CLIENT_INITIALIZING, /* server connected, client initializing */ |
3397 | + GEIS_DBUS_CLIENT_CONNECTING, /* server connected, not initialized */ |
3398 | + GEIS_DBUS_CLIENT_CONNECTED /* server connected, all systems go */ |
3399 | +} GeisDBusClientState; |
3400 | + |
3401 | + |
3402 | +struct GeisDBusClient |
3403 | +{ |
3404 | + Geis geis; |
3405 | + GeisDBusDispatcher dispatcher; |
3406 | + GeisDBusLocator locator; |
3407 | + GeisDBusClientState state; |
3408 | + DBusConnection *connection; |
3409 | + GeisSubBag subscription_bag; |
3410 | +}; |
3411 | + |
3412 | + |
3413 | +/** |
3414 | + * Handles a device-available message from the server. |
3415 | + * |
3416 | + * @param[in] client A %GeisDBusClient. |
3417 | + * @param[in] message The %DBusMessage. |
3418 | + */ |
3419 | +static void |
3420 | +_client_device_available(GeisDBusClient client, DBusMessage *message) |
3421 | +{ |
3422 | + GeisDevice device = geis_dbus_device_device_from_available_message(message); |
3423 | + if (device) |
3424 | + { |
3425 | + geis_register_device(client->geis, device, 0, NULL); |
3426 | + } |
3427 | + else |
3428 | + { |
3429 | + geis_error("no device received from remote back end"); |
3430 | + } |
3431 | +} |
3432 | + |
3433 | + |
3434 | +/** |
3435 | + * Handles a device-unavailable message from the server. |
3436 | + * |
3437 | + * @param[in] client A %GeisDBusClient. |
3438 | + * @param[in] message The %DBusMessage. |
3439 | + */ |
3440 | +static void |
3441 | +_client_device_unavailable(GeisDBusClient client, DBusMessage *message) |
3442 | +{ |
3443 | + GeisDevice device = geis_dbus_device_device_from_unavailable_message(message); |
3444 | + if (device) |
3445 | + { |
3446 | + geis_unregister_device(client->geis, device); |
3447 | + } |
3448 | + else |
3449 | + { |
3450 | + geis_error("no device received from remote back end"); |
3451 | + } |
3452 | +} |
3453 | + |
3454 | + |
3455 | +/** |
3456 | + * Handles a class-available message from the server. |
3457 | + * |
3458 | + * @param[in] client A %GeisDBusClient. |
3459 | + * @param[in] message The %DBusMessage. |
3460 | + */ |
3461 | +static void |
3462 | +_client_class_available(GeisDBusClient client, DBusMessage *message) |
3463 | +{ |
3464 | + GeisGestureClass gesture_class; |
3465 | + |
3466 | + gesture_class = geis_dbus_class_class_from_available_message(message); |
3467 | + if (gesture_class) |
3468 | + { |
3469 | + geis_register_gesture_class(client->geis, gesture_class, 0, NULL); |
3470 | + } |
3471 | + else |
3472 | + { |
3473 | + geis_error("no gesture class received from remote back end"); |
3474 | + } |
3475 | +} |
3476 | + |
3477 | + |
3478 | +/** |
3479 | + * Handles a region-available message from the server. |
3480 | + * |
3481 | + * @param[in] client A %GeisDBusClient. |
3482 | + * @param[in] message The %DBusMessage. |
3483 | + */ |
3484 | +static void |
3485 | +_client_region_available(GeisDBusClient client, DBusMessage *message) |
3486 | +{ |
3487 | + GeisFilterableAttribute attr; |
3488 | + |
3489 | + attr = geis_dbus_region_from_region_available_message(message); |
3490 | + if (attr) |
3491 | + { |
3492 | + attr->add_term_callback = 0; |
3493 | + attr->add_term_context = 0; |
3494 | + geis_register_region(client->geis, NULL, 1, attr); |
3495 | + } |
3496 | + else |
3497 | + { |
3498 | + geis_error("no region attr received from remote back end"); |
3499 | + } |
3500 | +} |
3501 | + |
3502 | + |
3503 | +/** |
3504 | + * Handles a class-unavailable message from the server. |
3505 | + * |
3506 | + * @param[in] client A %GeisDBusClient. |
3507 | + * @param[in] message The %DBusMessage. |
3508 | + */ |
3509 | +static void |
3510 | +_client_gesture_event(GeisDBusClient client, DBusMessage *message) |
3511 | +{ |
3512 | + GeisEvent event = geis_dbus_gesture_event_from_message(client->geis, message); |
3513 | + if (!event) |
3514 | + { |
3515 | + geis_error("no gesture event received from remote back end"); |
3516 | + } |
3517 | + else |
3518 | + { |
3519 | + geis_post_event(client->geis, event); |
3520 | + } |
3521 | +} |
3522 | + |
3523 | + |
3524 | +/** |
3525 | + * Processes an subscription-activate reply from the server. |
3526 | + * |
3527 | + * @param[in] pending A DBusPendingCall object. |
3528 | + * @param[in] user_data The %GeisDBusClient object. |
3529 | + */ |
3530 | +static void |
3531 | +_geis_dbus_client_activate_reply(DBusPendingCall *pending, void *user_data) |
3532 | +{ |
3533 | + GeisDBusClient client GEIS_UNUSED = (GeisDBusClient)user_data; |
3534 | + DBusMessage *reply = dbus_pending_call_steal_reply(pending); |
3535 | + |
3536 | + if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply)) |
3537 | + { |
3538 | + const char *s = NULL; |
3539 | + dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); |
3540 | + geis_error("error %s: %s", dbus_message_get_error_name(reply), s); |
3541 | + } |
3542 | +} |
3543 | + |
3544 | + |
3545 | +/** |
3546 | + * Processes a subscription-create reply from the server. |
3547 | + * |
3548 | + * @param[in] pending A DBusPendingCall object. |
3549 | + * @param[in] user_data The %GeisDBusClient object. |
3550 | + */ |
3551 | +static void |
3552 | +_geis_dbus_client_subscribe_reply(DBusPendingCall *pending, void *user_data) |
3553 | +{ |
3554 | + GeisDBusClient client = (GeisDBusClient)user_data; |
3555 | + DBusMessage *reply = dbus_pending_call_steal_reply(pending); |
3556 | + |
3557 | + if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply)) |
3558 | + { |
3559 | + const char *s = NULL; |
3560 | + dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); |
3561 | + geis_error("error %s: %s", dbus_message_get_error_name(reply), s); |
3562 | + } |
3563 | + else |
3564 | + { |
3565 | + DBusMessage *msg; |
3566 | + DBusPendingCall *pending; |
3567 | + DBusError error = DBUS_ERROR_INIT; |
3568 | + dbus_int32_t client_sub_id; |
3569 | + dbus_int32_t server_sub_id; |
3570 | + GeisSubscription subscription; |
3571 | + |
3572 | + dbus_message_get_args(reply, |
3573 | + &error, |
3574 | + DBUS_TYPE_INT32, &client_sub_id, |
3575 | + DBUS_TYPE_INT32, &server_sub_id, |
3576 | + DBUS_TYPE_INVALID); |
3577 | + if (dbus_error_is_set(&error)) |
3578 | + { |
3579 | + geis_error("error %s: %s", error.name, error.message); |
3580 | + dbus_error_free(&error); |
3581 | + } |
3582 | + |
3583 | + subscription = geis_subscription_bag_find(client->subscription_bag, |
3584 | + client_sub_id); |
3585 | + if (!subscription) |
3586 | + { |
3587 | + geis_error("invalid client subcription id %d returned from server", |
3588 | + client_sub_id); |
3589 | + } |
3590 | + else |
3591 | + { |
3592 | + geis_subscription_set_pdata(subscription, (GeisPointer)(intptr_t)server_sub_id); |
3593 | + |
3594 | + msg = geis_dbus_subscription_activate_call_message(subscription); |
3595 | + dbus_connection_send_with_reply(client->connection, msg, &pending, -1); |
3596 | + dbus_message_unref(msg); |
3597 | + if (!pending) |
3598 | + { |
3599 | + geis_error("error sending DBus CreateSubscription method call"); |
3600 | + } |
3601 | + else |
3602 | + { |
3603 | + dbus_pending_call_set_notify(pending, |
3604 | + _geis_dbus_client_activate_reply, |
3605 | + client, 0); |
3606 | + } |
3607 | + } |
3608 | + } |
3609 | + |
3610 | + dbus_message_unref(reply); |
3611 | + dbus_pending_call_unref(pending); |
3612 | +} |
3613 | + |
3614 | + |
3615 | +/** |
3616 | + * Processes a deactivate-subscription reply from the server. |
3617 | + * |
3618 | + * @param[in] pending A DBusPendingCall object. |
3619 | + * @param[in] user_data The %GeisDBusClient object. |
3620 | + */ |
3621 | +static void |
3622 | +_geis_dbus_client_unsubscribe_reply(DBusPendingCall *pending, void *user_data) |
3623 | +{ |
3624 | + GeisDBusClient client GEIS_UNUSED = (GeisDBusClient)user_data; |
3625 | + DBusMessage *reply = dbus_pending_call_steal_reply(pending); |
3626 | + |
3627 | + if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply)) |
3628 | + { |
3629 | + const char *s = NULL; |
3630 | + dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); |
3631 | + geis_error("error %s: %s", dbus_message_get_error_name(reply), s); |
3632 | + } |
3633 | + else |
3634 | + { |
3635 | + geis_warning("signature=\"%s\"", dbus_message_get_signature(reply)); |
3636 | + geis_warning("path=\"%s\"", dbus_message_get_path(reply)); |
3637 | + geis_warning("interface=\"%s\"", dbus_message_get_interface(reply)); |
3638 | + geis_warning("member=\"%s\"", dbus_message_get_member(reply)); |
3639 | + } |
3640 | + |
3641 | + dbus_message_unref(reply); |
3642 | + dbus_pending_call_unref(pending); |
3643 | +} |
3644 | + |
3645 | + |
3646 | +/** |
3647 | + * Creates a remote subscription. |
3648 | + */ |
3649 | +void |
3650 | +_dbus_client_subscribe(GeisDBusClient client, |
3651 | + GeisSubscription subscription) |
3652 | +{ |
3653 | + DBusPendingCall *pending_return; |
3654 | + |
3655 | + GeisSubscription sub = geis_subscription_bag_find(client->subscription_bag, |
3656 | + geis_subscription_id(subscription)); |
3657 | + if (sub && geis_subscription_pdata(sub)) |
3658 | + { |
3659 | + geis_warning("subscription already activated!"); |
3660 | + } |
3661 | + else |
3662 | + { |
3663 | + DBusMessage *msg = geis_dbus_subscription_create_call_message(subscription); |
3664 | + dbus_connection_send_with_reply(client->connection, msg, &pending_return, -1); |
3665 | + dbus_message_unref(msg); |
3666 | + if (!pending_return) |
3667 | + { |
3668 | + geis_error("error sending DBus CreateSubscription method call"); |
3669 | + } |
3670 | + else |
3671 | + { |
3672 | + dbus_pending_call_set_notify(pending_return, |
3673 | + _geis_dbus_client_subscribe_reply, |
3674 | + client, 0); |
3675 | + } |
3676 | + } |
3677 | +} |
3678 | + |
3679 | + |
3680 | +/** |
3681 | + * Re-subscribes all existing sibscriptions when the server appears or |
3682 | + * reappears. |
3683 | + */ |
3684 | +void |
3685 | +_dbus_client_resubscribe_all(GeisDBusClient client) |
3686 | +{ |
3687 | + GeisSubBagIterator it; |
3688 | + for (it = geis_subscription_bag_begin(client->subscription_bag); |
3689 | + it != geis_subscription_bag_end(client->subscription_bag); |
3690 | + it = geis_subscription_bag_iterator_next(client->subscription_bag, it)) |
3691 | + { |
3692 | + geis_subscription_set_pdata(*it, 0); |
3693 | + _dbus_client_subscribe(client, *it); |
3694 | + } |
3695 | +} |
3696 | + |
3697 | + |
3698 | +/** |
3699 | + * The DBus message dispatch function for the GEIS DBus client. |
3700 | + * |
3701 | + * @param[in] connection The %GeisDBusClient DBus connection. |
3702 | + * @param[in] message The DBus message received. |
3703 | + * @param[in] user_data The %GeisDBusClient. |
3704 | + */ |
3705 | +static DBusHandlerResult |
3706 | +_geis_dbus_client_message_handler(DBusConnection *connection GEIS_UNUSED, |
3707 | + DBusMessage *message, |
3708 | + void *user_data) |
3709 | +{ |
3710 | + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
3711 | + GeisDBusClient client = (GeisDBusClient)user_data; |
3712 | + int type = dbus_message_get_type(message); |
3713 | + |
3714 | + if (dbus_message_is_signal(message, |
3715 | + DBUS_INTERFACE_LOCAL, |
3716 | + "Disconnected")) |
3717 | + { |
3718 | + geis_warning("server disconnected?"); |
3719 | + result = DBUS_HANDLER_RESULT_HANDLED; |
3720 | + } |
3721 | + else if (dbus_message_is_signal(message, |
3722 | + GEIS_DBUS_SERVICE_INTERFACE, |
3723 | + GEIS_DBUS_DEVICE_AVAILABLE)) |
3724 | + { |
3725 | + _client_device_available(client, message); |
3726 | + result = DBUS_HANDLER_RESULT_HANDLED; |
3727 | + } |
3728 | + else if (dbus_message_is_signal(message, |
3729 | + GEIS_DBUS_SERVICE_INTERFACE, |
3730 | + GEIS_DBUS_DEVICE_UNAVAILABLE)) |
3731 | + |
3732 | + { |
3733 | + _client_device_unavailable(client, message); |
3734 | + result = DBUS_HANDLER_RESULT_HANDLED; |
3735 | + } |
3736 | + else if (dbus_message_is_signal(message, |
3737 | + GEIS_DBUS_SERVICE_INTERFACE, |
3738 | + GEIS_DBUS_CLASS_AVAILABLE)) |
3739 | + { |
3740 | + _client_class_available(client, message); |
3741 | + result = DBUS_HANDLER_RESULT_HANDLED; |
3742 | + } |
3743 | + else if (dbus_message_is_signal(message, |
3744 | + GEIS_DBUS_SERVICE_INTERFACE, |
3745 | + GEIS_DBUS_REGION_AVAILABLE)) |
3746 | + { |
3747 | + _client_region_available(client, message); |
3748 | + result = DBUS_HANDLER_RESULT_HANDLED; |
3749 | + } |
3750 | + else if (dbus_message_is_signal(message, |
3751 | + GEIS_DBUS_SERVICE_INTERFACE, |
3752 | + GEIS_DBUS_INIT_COMPLETE)) |
3753 | + { |
3754 | + if (client->state == GEIS_DBUS_CLIENT_INITIALIZING) |
3755 | + { |
3756 | + geis_post_event(client->geis, geis_event_new(GEIS_EVENT_INIT_COMPLETE)); |
3757 | + } |
3758 | + client->state = GEIS_DBUS_CLIENT_CONNECTED; |
3759 | + _dbus_client_resubscribe_all(client); |
3760 | + result = DBUS_HANDLER_RESULT_HANDLED; |
3761 | + } |
3762 | + else if (geis_dbus_message_is_gesture_event(message)) |
3763 | + { |
3764 | + _client_gesture_event(client, message); |
3765 | + result = DBUS_HANDLER_RESULT_HANDLED; |
3766 | + } |
3767 | + else if (type == DBUS_MESSAGE_TYPE_ERROR) |
3768 | + { |
3769 | + const char *str = NULL; |
3770 | + dbus_message_get_args(message, NULL, |
3771 | + DBUS_TYPE_STRING, &str, |
3772 | + DBUS_TYPE_INVALID); |
3773 | + geis_warning("error %s: %s", dbus_message_get_error_name(message), str); |
3774 | + } |
3775 | + else |
3776 | + { |
3777 | + geis_warning("unhandled DBus %s received:", |
3778 | + dbus_message_type_to_string(dbus_message_get_type(message))); |
3779 | + geis_warning(" signature=\"%s\"", dbus_message_get_signature(message)); |
3780 | + geis_warning(" sender=\"%s\"", dbus_message_get_sender(message)); |
3781 | + geis_warning(" path=\"%s\"", |
3782 | + dbus_message_get_path(message) ? |
3783 | + dbus_message_get_path(message) : |
3784 | + "(no path)"); |
3785 | + geis_warning(" interface=\"%s\"", |
3786 | + dbus_message_get_interface(message) ? |
3787 | + dbus_message_get_interface(message) : |
3788 | + "(no interface)"); |
3789 | + geis_warning(" member=\"%s\"", |
3790 | + dbus_message_get_member(message) ? |
3791 | + dbus_message_get_member(message) : |
3792 | + "(no member)"); |
3793 | + } |
3794 | + return result; |
3795 | +} |
3796 | + |
3797 | + |
3798 | +/** |
3799 | + * Adds the client watches to the dispatcher watch list. |
3800 | + * |
3801 | + * @param[in] watch A %DBusWatch. |
3802 | + * @param[in] data The %GeisDBusClientProxy. |
3803 | + */ |
3804 | +static dbus_bool_t |
3805 | +_client_add_watch(DBusWatch *watch, void *data) |
3806 | +{ |
3807 | + dbus_bool_t status = TRUE; |
3808 | + GeisDBusClient client = (GeisDBusClient)data; |
3809 | + |
3810 | + geis_dbus_dispatcher_register(client->dispatcher, client->connection, watch); |
3811 | + return status; |
3812 | +} |
3813 | + |
3814 | + |
3815 | +/** |
3816 | + * Toggles the enabled/disabled status of the client watches. |
3817 | + * |
3818 | + * @param[in] watch A %DBusWatch. |
3819 | + * @param[in] data The %GeisDBusClientProxy. |
3820 | + */ |
3821 | +static void |
3822 | +_client_toggle_watch(DBusWatch *watch, void *data) |
3823 | +{ |
3824 | + GeisDBusClient client = (GeisDBusClient)data; |
3825 | + |
3826 | + geis_dbus_dispatcher_toggle_watch(client->dispatcher, watch); |
3827 | +} |
3828 | + |
3829 | + |
3830 | +/** |
3831 | + * Removes the client watches from the dispatcher watch list. |
3832 | + * |
3833 | + * @param[in] watch A %DBusWatch. |
3834 | + * @param[in] data The %GeisDBusClientProxy. |
3835 | + */ |
3836 | +static void |
3837 | +_client_remove_watch(DBusWatch *watch, void *data) |
3838 | +{ |
3839 | + GeisDBusClient client = (GeisDBusClient)data; |
3840 | + |
3841 | + geis_dbus_dispatcher_unregister(client->dispatcher, watch); |
3842 | +} |
3843 | + |
3844 | + |
3845 | +/** |
3846 | + * Connects to the GEIS server once an address is located. |
3847 | + * |
3848 | + * @param[in] client A %GeisDBusClient object. |
3849 | + * @param[in] address The address of the server. |
3850 | + */ |
3851 | +static void |
3852 | +_client_connect(GeisDBusClient client, const char *address) |
3853 | +{ |
3854 | + geis_debug("server address=\"%s\"", address); |
3855 | + DBusError error = DBUS_ERROR_INIT; |
3856 | + client->connection = dbus_connection_open(address, &error); |
3857 | + if (!client->connection || dbus_error_is_set(&error)) |
3858 | + { |
3859 | + char msg[512]; |
3860 | + snprintf(msg, sizeof(msg), "error %s connecting to server at address %s: %s", |
3861 | + error.name, address, error.message); |
3862 | + geis_error("%s", msg); |
3863 | + dbus_error_free(&error); |
3864 | + goto final_exit; |
3865 | + } |
3866 | + |
3867 | + /* Integrate with the app event loop via the GEIS multiplexor. */ |
3868 | + dbus_connection_set_watch_functions(client->connection, |
3869 | + _client_add_watch, |
3870 | + _client_remove_watch, |
3871 | + _client_toggle_watch, |
3872 | + client, 0); |
3873 | + |
3874 | + /* Install a handler for any and all messages. */ |
3875 | + dbus_connection_add_filter(client->connection, |
3876 | + _geis_dbus_client_message_handler, |
3877 | + client, 0); |
3878 | + if (client->state != GEIS_DBUS_CLIENT_INITIALIZING) |
3879 | + { |
3880 | + client->state = GEIS_DBUS_CLIENT_CONNECTING; |
3881 | + } |
3882 | + |
3883 | +final_exit: |
3884 | + return; |
3885 | +} |
3886 | + |
3887 | + |
3888 | +/* |
3889 | + * Creates a new GeisDBusClient. |
3890 | + */ |
3891 | +GeisDBusClient |
3892 | +geis_dbus_client_new(Geis geis) |
3893 | +{ |
3894 | + GeisDBusClient client = calloc(1, sizeof(struct GeisDBusClient)); |
3895 | + if (!client) |
3896 | + { |
3897 | + goto final_exit; |
3898 | + } |
3899 | + |
3900 | + client->geis = geis; |
3901 | + client->state = GEIS_DBUS_CLIENT_INITIALIZING; |
3902 | + |
3903 | + client->dispatcher = geis_dbus_dispatcher_new(geis); |
3904 | + if (!client->dispatcher) |
3905 | + { |
3906 | + goto unwind_client; |
3907 | + } |
3908 | + |
3909 | + client->locator = geis_dbus_locator_new(client); |
3910 | + if (!client->locator) |
3911 | + { |
3912 | + goto unwind_dispatcher; |
3913 | + } |
3914 | + |
3915 | + client->subscription_bag = geis_subscription_bag_new(1); |
3916 | + if (!client->subscription_bag) |
3917 | + { |
3918 | + goto unwind_locator; |
3919 | + } |
3920 | + |
3921 | + goto final_exit; |
3922 | + |
3923 | +unwind_locator: |
3924 | + geis_dbus_locator_delete(client->locator); |
3925 | +unwind_dispatcher: |
3926 | + geis_dbus_dispatcher_delete(client->dispatcher); |
3927 | +unwind_client: |
3928 | + free(client); |
3929 | + client = NULL; |
3930 | +final_exit: |
3931 | + return client; |
3932 | +} |
3933 | + |
3934 | + |
3935 | +/* |
3936 | + * Destroys a GeisDBusClient. |
3937 | + */ |
3938 | +void |
3939 | +geis_dbus_client_delete(GeisDBusClient client) |
3940 | +{ |
3941 | + geis_subscription_bag_delete(client->subscription_bag); |
3942 | + geis_dbus_locator_delete(client->locator); |
3943 | + if (client->connection) |
3944 | + { |
3945 | + dbus_connection_unref(client->connection); |
3946 | + } |
3947 | + geis_dbus_dispatcher_delete(client->dispatcher); |
3948 | + free(client); |
3949 | +} |
3950 | + |
3951 | + |
3952 | +/* |
3953 | + * Gets the client dispatcher. |
3954 | + */ |
3955 | +GeisDBusDispatcher |
3956 | +geis_dbus_client_dispatcher(GeisDBusClient client) |
3957 | +{ |
3958 | + return client->dispatcher; |
3959 | +} |
3960 | + |
3961 | + |
3962 | +/* |
3963 | + * Signals the client the server has been located. |
3964 | + */ |
3965 | +void |
3966 | +geis_dbus_client_server_located(GeisDBusClient client) |
3967 | +{ |
3968 | + _client_connect(client, geis_dbus_locator_server_address(client->locator)); |
3969 | +} |
3970 | + |
3971 | + |
3972 | +/* |
3973 | + * Signals the client the server has been dislocated. |
3974 | + */ |
3975 | +void |
3976 | +geis_dbus_client_server_dislocated(GeisDBusClient client) |
3977 | +{ |
3978 | + GeisEvent event = geis_event_new(GEIS_EVENT_ERROR); |
3979 | + client->state = GEIS_DBUS_CLIENT_DISCONNECTED; |
3980 | + geis_post_event(client->geis, event); |
3981 | +} |
3982 | + |
3983 | + |
3984 | +/* |
3985 | + * Requests a subscription on the remote end. |
3986 | + */ |
3987 | +GeisStatus |
3988 | +geis_dbus_client_subscribe(GeisDBusClient client, |
3989 | + GeisSubscription subscription) |
3990 | +{ |
3991 | + GeisStatus status = GEIS_STATUS_SUCCESS; |
3992 | + |
3993 | + if (client->state == GEIS_DBUS_CLIENT_CONNECTED) |
3994 | + { |
3995 | + _dbus_client_subscribe(client, subscription); |
3996 | + } |
3997 | + geis_subscription_bag_insert(client->subscription_bag, subscription); |
3998 | + |
3999 | + return status; |
4000 | +} |
4001 | + |
4002 | + |
4003 | +/* |
4004 | + * Destroys a subscription on the remote end. |
4005 | + */ |
4006 | +GeisStatus |
4007 | +geis_dbus_client_unsubscribe(GeisDBusClient client, |
4008 | + GeisSubscription subscription) |
4009 | +{ |
4010 | + GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; |
4011 | + if (geis_subscription_bag_find(client->subscription_bag, |
4012 | + geis_subscription_id(subscription))) |
4013 | + { |
4014 | + DBusMessage *msg; |
4015 | + DBusPendingCall *pending_return; |
4016 | + |
4017 | + msg = geis_dbus_subscription_destroy_call_message(subscription); |
4018 | + dbus_connection_send_with_reply(client->connection, msg, &pending_return, -1); |
4019 | + dbus_message_unref(msg); |
4020 | + if (!pending_return) |
4021 | + { |
4022 | + geis_error("error sending DBus CreateSubscription method call"); |
4023 | + goto final_exit; |
4024 | + } |
4025 | + |
4026 | + dbus_pending_call_set_notify(pending_return, |
4027 | + _geis_dbus_client_unsubscribe_reply, |
4028 | + client, 0); |
4029 | + geis_subscription_bag_remove(client->subscription_bag, subscription); |
4030 | + status = GEIS_STATUS_SUCCESS; |
4031 | + } |
4032 | + |
4033 | +final_exit: |
4034 | + return status; |
4035 | +} |
4036 | + |
4037 | + |
4038 | + |
4039 | + |
4040 | |
4041 | === added file 'libutouch-geis/backend/dbus/geis_dbus_client.h' |
4042 | --- libutouch-geis/backend/dbus/geis_dbus_client.h 1970-01-01 00:00:00 +0000 |
4043 | +++ libutouch-geis/backend/dbus/geis_dbus_client.h 2011-10-18 19:34:23 +0000 |
4044 | @@ -0,0 +1,97 @@ |
4045 | +/** |
4046 | + * @file geis_dbus_client.h |
4047 | + * @brief Interface for the GEIS DBus client. |
4048 | + * |
4049 | + * The GEIS DBus client offers remote GEIS functionality over a managed |
4050 | + * DBus connection. |
4051 | + * |
4052 | + * This header is for internal GEIS use only and contains no client |
4053 | + * (externally-visible) symbols. |
4054 | + */ |
4055 | + |
4056 | +/* |
4057 | + * Copyright 2011 Canonical Ltd. |
4058 | + * |
4059 | + * This library is free software; you can redistribute it and/or modify it under |
4060 | + * the terms of the GNU Lesser General Public License as published by the Free |
4061 | + * Software Foundation; either version 3 of the License, or (at your option) any |
4062 | + * later version. |
4063 | + * |
4064 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
4065 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
4066 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
4067 | + * details. |
4068 | + * |
4069 | + * You should have received a copy of the GNU General Public License |
4070 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4071 | + */ |
4072 | +#ifndef GEIS_DBUS_CLIENT_H_ |
4073 | +#define GEIS_DBUS_CLIENT_H_ |
4074 | + |
4075 | +#include "geis/geis.h" |
4076 | +#include "geis_dbus_dispatcher.h" |
4077 | + |
4078 | + |
4079 | +typedef struct GeisDBusClient *GeisDBusClient; |
4080 | + |
4081 | + |
4082 | +/** |
4083 | + * Creates a new %GeisDBusClient object. |
4084 | + */ |
4085 | +GeisDBusClient |
4086 | +geis_dbus_client_new(Geis geis); |
4087 | + |
4088 | +/** |
4089 | + * Destroys a %GeisDBusClient. |
4090 | + * |
4091 | + * @param[in] client A GeisDBusClient. |
4092 | + */ |
4093 | +void |
4094 | +geis_dbus_client_delete(GeisDBusClient client); |
4095 | + |
4096 | +/** |
4097 | + * Gets the client dispatcher. |
4098 | + * |
4099 | + * @param[in] client A GeisDBusClient. |
4100 | + */ |
4101 | +GeisDBusDispatcher |
4102 | +geis_dbus_client_dispatcher(GeisDBusClient client); |
4103 | + |
4104 | +/** |
4105 | + * Signals the client the server has been located. |
4106 | + * |
4107 | + * @param[in] client A GeisDBusClient. |
4108 | + */ |
4109 | +void |
4110 | +geis_dbus_client_server_located(GeisDBusClient client); |
4111 | + |
4112 | +/** |
4113 | + * Signals the client the server has been dislocated. |
4114 | + * |
4115 | + * @param[in] client A GeisDBusClient. |
4116 | + */ |
4117 | +void |
4118 | +geis_dbus_client_server_dislocated(GeisDBusClient client); |
4119 | + |
4120 | +/** |
4121 | + * Cerates a subscription on the remote end. |
4122 | + * |
4123 | + * @param[in] client The client-side of the DBus connection. |
4124 | + * @param[in] subscription The local subscription object. |
4125 | + */ |
4126 | +GeisStatus |
4127 | +geis_dbus_client_subscribe(GeisDBusClient client, |
4128 | + GeisSubscription subscription); |
4129 | + |
4130 | +/** |
4131 | + * Deactivates a subscription on the remote end. |
4132 | + * |
4133 | + * @param[in] client The client-side of the DBus connection. |
4134 | + * @param[in] subscription The local subscription object. |
4135 | + */ |
4136 | +GeisStatus |
4137 | +geis_dbus_client_unsubscribe(GeisDBusClient client, |
4138 | + GeisSubscription subscription); |
4139 | + |
4140 | + |
4141 | +#endif /* GEIS_DBUS_CLIENT_H_ */ |
4142 | |
4143 | === added file 'libutouch-geis/backend/dbus/geis_dbus_locator.c' |
4144 | --- libutouch-geis/backend/dbus/geis_dbus_locator.c 1970-01-01 00:00:00 +0000 |
4145 | +++ libutouch-geis/backend/dbus/geis_dbus_locator.c 2011-10-18 19:34:23 +0000 |
4146 | @@ -0,0 +1,270 @@ |
4147 | +/** |
4148 | + * @file geis_dbus_locator.c |
4149 | + * @brief Implementation of the GEIS DBus locator. |
4150 | + */ |
4151 | + |
4152 | +/* |
4153 | + * Copyright 2011 Canonical Ltd. |
4154 | + * |
4155 | + * This library is free software; you can redistribute it and/or modify it under |
4156 | + * the terms of the GNU Lesser General Public License as published by the Free |
4157 | + * Software Foundation; either version 3 of the License, or (at your option) any |
4158 | + * later version. |
4159 | + * |
4160 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
4161 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
4162 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
4163 | + * details. |
4164 | + * |
4165 | + * You should have received a copy of the GNU General Public License |
4166 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4167 | + */ |
4168 | +#include "geis_config.h" |
4169 | +#include "geis_dbus_locator.h" |
4170 | + |
4171 | +#include <dbus/dbus.h> |
4172 | +#include "geis_dbus.h" |
4173 | +#include "geis_logging.h" |
4174 | +#include <stdio.h> |
4175 | +#include <stdlib.h> |
4176 | +#include <string.h> |
4177 | + |
4178 | + |
4179 | +typedef enum GeisDBusLocatorState |
4180 | +{ |
4181 | + GEIS_DBUS_LOCATOR_STATE_INITIALIZING, |
4182 | + GEIS_DBUS_LOCATOR_STATE_LOCATING, |
4183 | + GEIS_DBUS_LOCATOR_STATE_WAITING, |
4184 | + GEIS_DBUS_LOCATOR_STATE_FINALIZING |
4185 | +} GeisDBusLocatorState; |
4186 | + |
4187 | + |
4188 | +struct GeisDBusLocator |
4189 | +{ |
4190 | + GeisDBusClient client; |
4191 | + GeisDBusLocatorState state; |
4192 | + DBusConnection *session_bus; |
4193 | + char *server_address; |
4194 | + dbus_uint32_t serial; |
4195 | +}; |
4196 | + |
4197 | + |
4198 | +/* |
4199 | + * Performs the act of actually locating the server. |
4200 | + */ |
4201 | +static void |
4202 | +_locator_find_server(GeisDBusLocator locator) |
4203 | +{ |
4204 | + locator->state = GEIS_DBUS_LOCATOR_STATE_LOCATING; |
4205 | + DBusMessage *msg = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE, |
4206 | + GEIS_DBUS_SERVICE_PATH, |
4207 | + GEIS_DBUS_SERVICE_INTERFACE, |
4208 | + GEIS_DBUS_GET_SERVER_ADDRESS); |
4209 | + dbus_connection_send(locator->session_bus, msg, &locator->serial); |
4210 | + dbus_message_unref(msg); |
4211 | +} |
4212 | + |
4213 | + |
4214 | +/* |
4215 | + * A generic message handler function. |
4216 | + */ |
4217 | +static DBusHandlerResult |
4218 | +_locator_message_handler(DBusConnection *connection GEIS_UNUSED, |
4219 | + DBusMessage *message, |
4220 | + void *user_data) |
4221 | +{ |
4222 | + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
4223 | + GeisDBusLocator locator = (GeisDBusLocator)user_data; |
4224 | + int type = dbus_message_get_type(message); |
4225 | + |
4226 | + if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) |
4227 | + { |
4228 | + char *name; |
4229 | + char *old_owner; |
4230 | + char *new_owner; |
4231 | + dbus_message_get_args(message, NULL, |
4232 | + DBUS_TYPE_STRING, &name, |
4233 | + DBUS_TYPE_STRING, &old_owner, |
4234 | + DBUS_TYPE_STRING, &new_owner, |
4235 | + DBUS_TYPE_INVALID); |
4236 | + if (strlen(old_owner)) |
4237 | + { |
4238 | + geis_debug("%s has gone away", name); |
4239 | + geis_dbus_client_server_dislocated(locator->client); |
4240 | + result = DBUS_HANDLER_RESULT_HANDLED; |
4241 | + } |
4242 | + else if (strlen(new_owner)) |
4243 | + { |
4244 | + geis_debug("%s has appeared", name); |
4245 | + _locator_find_server(locator); |
4246 | + result = DBUS_HANDLER_RESULT_HANDLED; |
4247 | + } |
4248 | + } |
4249 | + else if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN) |
4250 | + { |
4251 | + if (locator->serial == dbus_message_get_reply_serial(message)) |
4252 | + { |
4253 | + const char *s = NULL; |
4254 | + dbus_message_get_args(message, NULL, |
4255 | + DBUS_TYPE_STRING, &s, |
4256 | + DBUS_TYPE_INVALID); |
4257 | + locator->server_address = strdup(s); |
4258 | + geis_dbus_client_server_located(locator->client); |
4259 | + result = DBUS_HANDLER_RESULT_HANDLED; |
4260 | + } |
4261 | + } |
4262 | + else if (type == DBUS_MESSAGE_TYPE_ERROR) |
4263 | + { |
4264 | + if (dbus_message_is_error(message, DBUS_ERROR_SERVICE_UNKNOWN)) |
4265 | + { |
4266 | + geis_warning("server not found!"); |
4267 | + geis_dbus_client_server_dislocated(locator->client); |
4268 | + result = DBUS_HANDLER_RESULT_HANDLED; |
4269 | + } |
4270 | + else |
4271 | + { |
4272 | + const char *str = NULL; |
4273 | + dbus_message_get_args(message, NULL, |
4274 | + DBUS_TYPE_STRING, &str, |
4275 | + DBUS_TYPE_INVALID); |
4276 | + geis_warning("error %s: %s", dbus_message_get_error_name(message), str); |
4277 | + } |
4278 | + } |
4279 | + |
4280 | + return result; |
4281 | +} |
4282 | + |
4283 | + |
4284 | +/* |
4285 | + * Adds the locator watches to the dispatcher watch list. |
4286 | + */ |
4287 | +static dbus_bool_t |
4288 | +_locator_add_watch(DBusWatch *watch, void *data) |
4289 | +{ |
4290 | + dbus_bool_t status = TRUE; |
4291 | + GeisDBusLocator locator = (GeisDBusLocator)data; |
4292 | + GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client); |
4293 | + |
4294 | + geis_dbus_dispatcher_register(dispatcher, locator->session_bus, watch); |
4295 | + return status; |
4296 | +} |
4297 | + |
4298 | + |
4299 | +/* |
4300 | + * Toggles the enabled/disabled status of the locator watches. |
4301 | + */ |
4302 | +static void |
4303 | +_locator_toggle_watch(DBusWatch *watch, void *data) |
4304 | +{ |
4305 | + GeisDBusLocator locator = (GeisDBusLocator)data; |
4306 | + GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client); |
4307 | + |
4308 | + geis_dbus_dispatcher_toggle_watch(dispatcher, watch); |
4309 | +} |
4310 | + |
4311 | + |
4312 | +/* |
4313 | + * Removes the locator watches from the dispatcher watch list. |
4314 | + */ |
4315 | +static void |
4316 | +_locator_remove_watch(DBusWatch *watch, void *data) |
4317 | +{ |
4318 | + GeisDBusLocator locator = (GeisDBusLocator)data; |
4319 | + GeisDBusDispatcher dispatcher = geis_dbus_client_dispatcher(locator->client); |
4320 | + |
4321 | + geis_dbus_dispatcher_unregister(dispatcher, watch); |
4322 | +} |
4323 | + |
4324 | + |
4325 | +/* |
4326 | + * Creates a new GeisDBusLocator object. |
4327 | + */ |
4328 | +GeisDBusLocator |
4329 | +geis_dbus_locator_new(GeisDBusClient client) |
4330 | +{ |
4331 | + GeisDBusLocator locator = calloc(1, sizeof(struct GeisDBusLocator)); |
4332 | + if (!locator) |
4333 | + { |
4334 | + goto final_exit; |
4335 | + } |
4336 | + |
4337 | + locator->client = client; |
4338 | + locator->state = GEIS_DBUS_LOCATOR_STATE_INITIALIZING; |
4339 | + |
4340 | + /* Connect to the DBus session bus. */ |
4341 | + DBusError error = DBUS_ERROR_INIT; |
4342 | + locator->session_bus = dbus_bus_get(DBUS_BUS_SESSION, &error); |
4343 | + if (!locator->session_bus || dbus_error_is_set(&error)) |
4344 | + { |
4345 | + char msg[512]; |
4346 | + snprintf(msg, sizeof(msg), "error %s connecting to session bus: %s", |
4347 | + error.name, error.message); |
4348 | + geis_error("%s", msg); |
4349 | + goto unwind_error; |
4350 | + } |
4351 | + |
4352 | + /* Integrate with the app event loop via the GEIS multiplexor. */ |
4353 | + dbus_connection_set_watch_functions(locator->session_bus, |
4354 | + _locator_add_watch, |
4355 | + _locator_remove_watch, |
4356 | + _locator_toggle_watch, |
4357 | + locator, 0); |
4358 | + |
4359 | + /* Look for server-connect and server-disconnect messages. */ |
4360 | + dbus_bus_add_match(locator->session_bus, |
4361 | + "type='signal',sender='" DBUS_SERVICE_DBUS "'," \ |
4362 | + "interface='" DBUS_INTERFACE_DBUS "'," \ |
4363 | + "member='NameOwnerChanged'," \ |
4364 | + "arg0='" GEIS_DBUS_SERVICE_INTERFACE "'", |
4365 | + &error); |
4366 | + if (dbus_error_is_set(&error)) |
4367 | + { |
4368 | + char msg[512]; |
4369 | + snprintf(msg, sizeof(msg), "error %s adding match to session bus: %s", |
4370 | + error.name, error.message); |
4371 | + geis_error("%s", msg); |
4372 | + goto unwind_error; |
4373 | + } |
4374 | + |
4375 | + /* Install a handler for any and all messages. */ |
4376 | + dbus_connection_add_filter(locator->session_bus, |
4377 | + _locator_message_handler, |
4378 | + locator, 0); |
4379 | + |
4380 | + /* OK, go eh? */ |
4381 | + _locator_find_server(locator); |
4382 | + |
4383 | +unwind_error: |
4384 | + dbus_error_free(&error); |
4385 | +final_exit: |
4386 | + return locator; |
4387 | +} |
4388 | + |
4389 | + |
4390 | +/* |
4391 | + * Destroys a %GeisDBusLocator object. |
4392 | + */ |
4393 | +void |
4394 | +geis_dbus_locator_delete(GeisDBusLocator locator) |
4395 | +{ |
4396 | + if (locator) |
4397 | + { |
4398 | + if (locator->server_address) |
4399 | + { |
4400 | + free(locator->server_address); |
4401 | + } |
4402 | + if (locator->session_bus) |
4403 | + { |
4404 | + dbus_connection_unref(locator->session_bus); |
4405 | + } |
4406 | + free(locator); |
4407 | + } |
4408 | +} |
4409 | + |
4410 | + |
4411 | +char * |
4412 | +geis_dbus_locator_server_address(GeisDBusLocator locator) |
4413 | +{ |
4414 | + return locator->server_address; |
4415 | +} |
4416 | + |
4417 | |
4418 | === added file 'libutouch-geis/backend/dbus/geis_dbus_locator.h' |
4419 | --- libutouch-geis/backend/dbus/geis_dbus_locator.h 1970-01-01 00:00:00 +0000 |
4420 | +++ libutouch-geis/backend/dbus/geis_dbus_locator.h 2011-10-18 19:34:23 +0000 |
4421 | @@ -0,0 +1,62 @@ |
4422 | +/** |
4423 | + * @file geis_dbus_locator.h |
4424 | + * @brief Interface for the GEIS DBus locator. |
4425 | + * |
4426 | + * The GEIS DBus locator makes the location of the GEIS DBus server available |
4427 | + * over the DBus session bus. |
4428 | + * |
4429 | + * This header is for internal GEIS use only and contains no client |
4430 | + * (externally-visible) symbols. |
4431 | + */ |
4432 | + |
4433 | +/* |
4434 | + * Copyright 2011 Canonical Ltd. |
4435 | + * |
4436 | + * This library is free software; you can redistribute it and/or modify it under |
4437 | + * the terms of the GNU Lesser General Public License as published by the Free |
4438 | + * Software Foundation; either version 3 of the License, or (at your option) any |
4439 | + * later version. |
4440 | + * |
4441 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
4442 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
4443 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
4444 | + * details. |
4445 | + * |
4446 | + * You should have received a copy of the GNU General Public License |
4447 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4448 | + */ |
4449 | +#ifndef GEIS_DBUS_LOCATOR_H_ |
4450 | +#define GEIS_DBUS_LOCATOR_H_ |
4451 | + |
4452 | +#include "geis/geis.h" |
4453 | +#include "geis_dbus_client.h" |
4454 | + |
4455 | + |
4456 | +typedef struct GeisDBusLocator *GeisDBusLocator; |
4457 | + |
4458 | + |
4459 | +/** |
4460 | + * Creates a new GeisDBusLocator object. |
4461 | + * |
4462 | + * @param[in] client A GEIS DBus CLient. |
4463 | + */ |
4464 | +GeisDBusLocator |
4465 | +geis_dbus_locator_new(GeisDBusClient client); |
4466 | + |
4467 | +/** |
4468 | + * Destroys a %GeisDBusLocator object. |
4469 | + * |
4470 | + * @param[in] locator A GeisDBusLocator. |
4471 | + */ |
4472 | +void |
4473 | +geis_dbus_locator_delete(GeisDBusLocator locator); |
4474 | + |
4475 | +/** |
4476 | + * Gets the currently located server address. |
4477 | + * |
4478 | + * @param[in] locator A GeisDBusLocator. |
4479 | + */ |
4480 | +char * |
4481 | +geis_dbus_locator_server_address(GeisDBusLocator locator); |
4482 | + |
4483 | +#endif /* GEIS_DBUS_LOCATOR_H_ */ |
4484 | |
4485 | === modified file 'libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c' |
4486 | --- libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2011-08-18 18:14:12 +0000 |
4487 | +++ libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2011-10-18 19:34:23 +0000 |
4488 | @@ -77,8 +77,8 @@ |
4489 | static GeisBackendToken _token_clone(GeisBackendToken); |
4490 | static void _token_finalize(GeisBackendToken); |
4491 | static void _token_compose(GeisBackendToken, GeisBackendToken); |
4492 | -static GeisStatus _token_activate(GeisBackendToken); |
4493 | -static GeisStatus _token_deactivate(GeisBackendToken); |
4494 | +static GeisStatus _token_activate(GeisBackendToken, GeisSubscription); |
4495 | +static GeisStatus _token_deactivate(GeisBackendToken, GeisSubscription); |
4496 | |
4497 | static struct GeisBackendTokenVtable _token_vtbl = { |
4498 | _token_clone, |
4499 | @@ -361,7 +361,8 @@ |
4500 | |
4501 | |
4502 | GeisStatus |
4503 | -_token_activate(GeisBackendToken gbtoken) |
4504 | +_token_activate(GeisBackendToken gbtoken, |
4505 | + GeisSubscription subscription GEIS_UNUSED) |
4506 | { |
4507 | GeisStatus status = GEIS_STATUS_SUCCESS; |
4508 | TestBackendToken token = _tbtoken_from_token(gbtoken); |
4509 | @@ -371,7 +372,8 @@ |
4510 | |
4511 | |
4512 | GeisStatus |
4513 | -_token_deactivate(GeisBackendToken gbtoken GEIS_UNUSED) |
4514 | +_token_deactivate(GeisBackendToken gbtoken GEIS_UNUSED, |
4515 | + GeisSubscription subscription GEIS_UNUSED) |
4516 | { |
4517 | GeisStatus status = GEIS_STATUS_SUCCESS; |
4518 | return status; |
4519 | @@ -381,7 +383,7 @@ |
4520 | __attribute__((constructor)) |
4521 | static void _register_test_fixture() |
4522 | { |
4523 | - geis_register_backend(GEIS_INIT_UTOUCH_MOCK_ENGINE, |
4524 | + geis_register_backend(GEIS_INIT_UTOUCH_MOCK_BACKEND, |
4525 | sizeof(struct GeisBackendTestFixture), |
4526 | &tf_vtbl); |
4527 | } |
4528 | |
4529 | === modified file 'libutouch-geis/backend/xcb/geis_xcb_backend.c' |
4530 | --- libutouch-geis/backend/xcb/geis_xcb_backend.c 2011-09-02 15:52:27 +0000 |
4531 | +++ libutouch-geis/backend/xcb/geis_xcb_backend.c 2011-10-18 19:34:23 +0000 |
4532 | @@ -105,7 +105,7 @@ |
4533 | static void _construct(void *mem, Geis geis); |
4534 | static void _finalize(GeisBackend g); |
4535 | static GeisBackendToken _create_token(GeisBackend be, GeisBackendTokenInitState); |
4536 | -static void _fd_callback(int fd, GeisBackendMultiplexorEvent ev, void *ctx); |
4537 | +static void _fd_callback(int fd, GeisBackendMultiplexorActivity ev, void *ctx); |
4538 | |
4539 | |
4540 | static struct GeisBackendVtable be_vtbl = { |
4541 | @@ -116,7 +116,7 @@ |
4542 | |
4543 | |
4544 | /* A handy little table to map grail types to geis gesture classes. */ |
4545 | -struct GrailTypeToGeisClass |
4546 | +static struct GrailTypeToGeisClass |
4547 | { |
4548 | GeisInteger grail_type; |
4549 | GeisGestureClass geis_class; |
4550 | @@ -156,7 +156,8 @@ |
4551 | { GRAIL_TYPE_MTOUCH, NULL } |
4552 | }; |
4553 | |
4554 | -GeisSize s_grail_type_map_size = sizeof(s_grail_type_map) / sizeof(struct GrailTypeToGeisClass); |
4555 | +static GeisSize s_grail_type_map_size = sizeof(s_grail_type_map) |
4556 | + / sizeof(struct GrailTypeToGeisClass); |
4557 | |
4558 | static void |
4559 | _set_grail_type_class(GeisInteger grail_type, GeisGestureClass geis_class) |
4560 | @@ -653,7 +654,8 @@ |
4561 | } |
4562 | |
4563 | be->xcb_fd = xcb_get_file_descriptor(be->xcb_connection); |
4564 | - geis_multiplex_fd(be->geis, be->xcb_fd, _fd_callback, be); |
4565 | + geis_multiplex_fd(be->geis, be->xcb_fd, GEIS_BE_MX_READ_AVAILABLE, |
4566 | + _fd_callback, be); |
4567 | |
4568 | be->sub_table = geis_xcb_backend_sub_table_new(); |
4569 | |
4570 | @@ -933,9 +935,9 @@ |
4571 | |
4572 | /** @todo implement this */ |
4573 | void |
4574 | -_fd_callback(int fd GEIS_UNUSED, |
4575 | - GeisBackendMultiplexorEvent ev GEIS_UNUSED, |
4576 | - void *ctx) |
4577 | +_fd_callback(int fd GEIS_UNUSED, |
4578 | + GeisBackendMultiplexorActivity ev GEIS_UNUSED, |
4579 | + void *ctx) |
4580 | { |
4581 | GeisXcbBackend be = (GeisXcbBackend)ctx; |
4582 | _xcb_dispatch(be); |
4583 | @@ -1022,7 +1024,7 @@ |
4584 | __attribute__((constructor)) |
4585 | static void _register_xcb_backend() |
4586 | { |
4587 | - geis_register_backend(GEIS_INIT_UTOUCH_XCB, |
4588 | + geis_register_backend(GEIS_INIT_UTOUCH_XCB_BACKEND, |
4589 | sizeof(struct GeisXcbBackend), |
4590 | &be_vtbl); |
4591 | } |
4592 | |
4593 | === modified file 'libutouch-geis/backend/xcb/geis_xcb_backend_token.c' |
4594 | --- libutouch-geis/backend/xcb/geis_xcb_backend_token.c 2011-08-29 18:41:20 +0000 |
4595 | +++ libutouch-geis/backend/xcb/geis_xcb_backend_token.c 2011-10-18 19:34:23 +0000 |
4596 | @@ -55,8 +55,8 @@ |
4597 | static GeisBackendToken _token_clone(GeisBackendToken); |
4598 | static void _token_finalize(GeisBackendToken); |
4599 | static void _token_compose(GeisBackendToken, GeisBackendToken); |
4600 | -static GeisStatus _token_activate(GeisBackendToken); |
4601 | -static GeisStatus _token_deactivate(GeisBackendToken); |
4602 | +static GeisStatus _token_activate(GeisBackendToken, GeisSubscription); |
4603 | +static GeisStatus _token_deactivate(GeisBackendToken, GeisSubscription); |
4604 | |
4605 | static struct GeisBackendTokenVtable _token_vtbl = { |
4606 | _token_clone, |
4607 | @@ -317,7 +317,7 @@ |
4608 | * various back end subscriptions appropriately. |
4609 | */ |
4610 | static GeisStatus |
4611 | -_token_activate(GeisBackendToken token) |
4612 | +_token_activate(GeisBackendToken token, GeisSubscription subscripton GEIS_UNUSED) |
4613 | { |
4614 | GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; |
4615 | XcbBackendToken t = _xcb_token_from_geis_token(token); |
4616 | @@ -338,7 +338,7 @@ |
4617 | * various back end subscriptions appropriately. |
4618 | */ |
4619 | static GeisStatus |
4620 | -_token_deactivate(GeisBackendToken token) |
4621 | +_token_deactivate(GeisBackendToken token, GeisSubscription sub GEIS_UNUSED) |
4622 | { |
4623 | GeisStatus status = GEIS_STATUS_SUCCESS; |
4624 | XcbBackendToken t = _xcb_token_from_geis_token(token); |
4625 | |
4626 | === modified file 'libutouch-geis/backend/xcb/grail_gestures.c' |
4627 | --- libutouch-geis/backend/xcb/grail_gestures.c 2011-07-22 15:54:50 +0000 |
4628 | +++ libutouch-geis/backend/xcb/grail_gestures.c 2011-10-18 19:34:23 +0000 |
4629 | @@ -505,7 +505,7 @@ |
4630 | (char *)grail_class->name); |
4631 | geis_frame_add_attr(frame, attr); |
4632 | |
4633 | - attr = geis_attr_new("geis gesture class id", |
4634 | + attr = geis_attr_new(GEIS_CLASS_ATTRIBUTE_ID, |
4635 | GEIS_ATTR_TYPE_INTEGER, |
4636 | (void *)&grail_class->geis_class_id); |
4637 | geis_frame_add_attr(frame, attr); |
4638 | |
4639 | === modified file 'libutouch-geis/geis.c' |
4640 | --- libutouch-geis/geis.c 2011-08-21 16:28:27 +0000 |
4641 | +++ libutouch-geis/geis.c 2011-10-18 19:34:23 +0000 |
4642 | @@ -32,6 +32,7 @@ |
4643 | #include "geis_attr.h" |
4644 | #include "geis_backend.h" |
4645 | #include "geis_class.h" |
4646 | +#include "server/geis_dbus_server.h" /* @TODO replace me */ |
4647 | #include "geis_device.h" |
4648 | #include "geis_backend_multiplexor.h" |
4649 | #include "geis_error.h" |
4650 | @@ -45,16 +46,6 @@ |
4651 | |
4652 | |
4653 | /* |
4654 | - * An internal struct to collect filterable attributes for facilities. |
4655 | - */ |
4656 | -typedef struct FilterableAttributeBag |
4657 | -{ |
4658 | - GeisFilterableAttribute store; |
4659 | - GeisSize size; |
4660 | - GeisSize count; |
4661 | -} *FilterableAttributeBag; |
4662 | - |
4663 | -/* |
4664 | * An internal structure to track processing callbacks in some order. |
4665 | */ |
4666 | typedef struct GeisProcessingEntry *GeisProcessingEntry; |
4667 | @@ -78,6 +69,8 @@ |
4668 | GeisSubBag subscription_bag; |
4669 | GeisBackendMultiplexor backend_multiplexor; |
4670 | GeisBackend backend; |
4671 | + GeisBoolean backend_pending; |
4672 | + GeisDBusServer server; /* @TODO: replace me */ |
4673 | GeisEventQueue input_event_queue; |
4674 | int input_event_signal_pipe[2]; |
4675 | GeisProcessingEntry processing_callbacks; |
4676 | @@ -200,12 +193,14 @@ |
4677 | * Filters and transforms raw gesture events into cooked gesture events. |
4678 | */ |
4679 | static void |
4680 | -_input_event_handler(int fd, GeisBackendMultiplexorEvent mux_ev, void *context) |
4681 | +_input_event_handler(int fd, |
4682 | + GeisBackendMultiplexorActivity activity, |
4683 | + void *context) |
4684 | { |
4685 | Geis geis = (Geis)context; |
4686 | GeisProcessingEntry cb; |
4687 | |
4688 | - if (mux_ev == GEIS_BE_MX_READ_AVAILABLE) |
4689 | + if (activity & GEIS_BE_MX_READ_AVAILABLE) |
4690 | { |
4691 | GeisEvent event; |
4692 | |
4693 | @@ -234,6 +229,20 @@ |
4694 | handled = _class_event_handler(geis, event); |
4695 | break; |
4696 | |
4697 | + case GEIS_EVENT_INIT_COMPLETE: |
4698 | + geis->backend_pending = GEIS_FALSE; |
4699 | + break; |
4700 | + |
4701 | + case GEIS_EVENT_ERROR: |
4702 | + if (geis->backend_pending) |
4703 | + { |
4704 | + geis->backend = geis_backend_by_name(geis, |
4705 | + GEIS_INIT_UTOUCH_XCB_BACKEND); |
4706 | + geis->backend_pending = GEIS_FALSE; |
4707 | + handled = GEIS_TRUE; |
4708 | + } |
4709 | + break; |
4710 | + |
4711 | default: |
4712 | break; |
4713 | } |
4714 | @@ -273,93 +282,6 @@ |
4715 | |
4716 | |
4717 | /* |
4718 | - * Constructs a new filterable attribute bag. |
4719 | - */ |
4720 | -static FilterableAttributeBag |
4721 | -_filterable_attribute_bag_new() |
4722 | -{ |
4723 | - FilterableAttributeBag bag = calloc(1, sizeof(struct FilterableAttributeBag)); |
4724 | - if (!bag) |
4725 | - { |
4726 | - geis_error("failed to allocate filterable attribute bag"); |
4727 | - goto final_exit; |
4728 | - } |
4729 | - |
4730 | - bag->size = 2; |
4731 | - bag->count = 0; |
4732 | - |
4733 | - bag->store = calloc(1, sizeof(struct GeisFilterableAttribute)); |
4734 | - if (!bag) |
4735 | - { |
4736 | - geis_error("failed to allocate filterable attribute bag store"); |
4737 | - goto unwind_bag; |
4738 | - } |
4739 | - goto final_exit; |
4740 | - |
4741 | -unwind_bag: |
4742 | - free(bag); |
4743 | - bag = NULL; |
4744 | -final_exit: |
4745 | - return bag; |
4746 | -} |
4747 | - |
4748 | - |
4749 | -/* |
4750 | - * Destroys a filterable attribute bag. |
4751 | - */ |
4752 | -static void |
4753 | -_filterable_attribute_bag_delete(FilterableAttributeBag bag) |
4754 | -{ |
4755 | - if (bag) |
4756 | - { |
4757 | - GeisSize i; |
4758 | - for (i = 0; i < bag->count; ++i) |
4759 | - { |
4760 | - free((char *)bag->store[i].name); |
4761 | - } |
4762 | - free(bag->store); |
4763 | - } |
4764 | - free(bag); |
4765 | -} |
4766 | - |
4767 | - |
4768 | -static void |
4769 | -_filterable_attribute_copy(GeisFilterableAttribute src, |
4770 | - GeisFilterableAttribute dst) |
4771 | -{ |
4772 | - dst->name = strdup(src->name); |
4773 | - dst->type = src->type; |
4774 | - dst->add_term_callback = src->add_term_callback; |
4775 | - dst->add_term_context = src->add_term_context; |
4776 | -} |
4777 | - |
4778 | - |
4779 | -static void |
4780 | -_filterable_attribute_bag_insert(FilterableAttributeBag bag, |
4781 | - GeisFilterableAttribute fa) |
4782 | -{ |
4783 | - GeisSize new_count = bag->count + 1; |
4784 | - if (new_count >= bag->size) |
4785 | - { |
4786 | - GeisSize new_size = bag->size * 2; |
4787 | - GeisSize allocation_size = new_size * sizeof(struct GeisFilterableAttribute); |
4788 | - GeisFilterableAttribute new_store = realloc(bag->store, allocation_size); |
4789 | - if (!new_store) |
4790 | - { |
4791 | - geis_error("failed to reallocate filterable attribute bag store"); |
4792 | - } |
4793 | - else |
4794 | - { |
4795 | - bag->store = new_store; |
4796 | - bag->size = new_size; |
4797 | - } |
4798 | - } |
4799 | - _filterable_attribute_copy(fa, &bag->store[bag->count]); |
4800 | - bag->count = new_count; |
4801 | -} |
4802 | - |
4803 | - |
4804 | -/* |
4805 | * Applies the back end callback to the back end token for each filterable |
4806 | * attribute with a name matching the argument. |
4807 | */ |
4808 | @@ -371,13 +293,16 @@ |
4809 | void *value) |
4810 | { |
4811 | GeisStatus status = GEIS_STATUS_SUCCESS; |
4812 | - GeisSize i; |
4813 | - for (i = 0; i < bag->count; ++i) |
4814 | + GeisFilterableAttributeBagIter it; |
4815 | + for (it = geis_filterable_attribute_bag_begin(bag); |
4816 | + it != geis_filterable_attribute_bag_end(bag); |
4817 | + it = geis_filterable_attribute_bag_next(bag, it)) |
4818 | { |
4819 | - GeisFilterableAttribute fa = &bag->store[i]; |
4820 | - if (0 == strcmp(fa->name, name)) |
4821 | + if (0 == strcmp(it->name, name) && it->add_term_callback) |
4822 | { |
4823 | - status = fa->add_term_callback(token, fa->add_term_context, name, op, value); |
4824 | + status = it->add_term_callback(token, |
4825 | + it->add_term_context, |
4826 | + name, op, value); |
4827 | } |
4828 | } |
4829 | return status; |
4830 | @@ -389,11 +314,11 @@ |
4831 | */ |
4832 | GeisStatus |
4833 | geis_filterable_attribute_foreach(Geis geis, |
4834 | - GeisFilterFacility facility, |
4835 | - GeisBackendToken token, |
4836 | - GeisString name, |
4837 | - GeisFilterOperation op, |
4838 | - void *value) |
4839 | + GeisFilterFacility facility, |
4840 | + GeisBackendToken token, |
4841 | + GeisString name, |
4842 | + GeisFilterOperation op, |
4843 | + void *value) |
4844 | { |
4845 | GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; |
4846 | switch (facility) |
4847 | @@ -470,6 +395,7 @@ |
4848 | } |
4849 | geis_backend_multiplexor_add_fd(geis->backend_multiplexor, |
4850 | geis->input_event_signal_pipe[0], |
4851 | + GEIS_BE_MX_READ_AVAILABLE, |
4852 | _input_event_handler, |
4853 | geis); |
4854 | |
4855 | @@ -482,7 +408,7 @@ |
4856 | } |
4857 | geis->output_event_callback = _default_output_event_callback; |
4858 | |
4859 | - geis->class_filterable_attributes = _filterable_attribute_bag_new(); |
4860 | + geis->class_filterable_attributes = geis_filterable_attribute_bag_new(); |
4861 | if (!geis->class_filterable_attributes) |
4862 | { |
4863 | geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); |
4864 | @@ -499,7 +425,7 @@ |
4865 | } |
4866 | geis->class_event_callback = _default_output_event_callback; |
4867 | |
4868 | - geis->device_filterable_attributes = _filterable_attribute_bag_new(); |
4869 | + geis->device_filterable_attributes = geis_filterable_attribute_bag_new(); |
4870 | if (!geis->device_filterable_attributes) |
4871 | { |
4872 | geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR); |
4873 | @@ -516,13 +442,13 @@ |
4874 | } |
4875 | geis->device_event_callback = _default_output_event_callback; |
4876 | |
4877 | - geis->region_filterable_attributes = _filterable_attribute_bag_new(); |
4878 | + geis->region_filterable_attributes = geis_filterable_attribute_bag_new(); |
4879 | if (!geis->region_filterable_attributes) |
4880 | { |
4881 | goto unwind_device_bag; |
4882 | } |
4883 | |
4884 | - geis->special_filterable_attributes = _filterable_attribute_bag_new(); |
4885 | + geis->special_filterable_attributes = geis_filterable_attribute_bag_new(); |
4886 | if (!geis->special_filterable_attributes) |
4887 | { |
4888 | goto unwind_region_attrs; |
4889 | @@ -531,15 +457,15 @@ |
4890 | goto final_exit; |
4891 | |
4892 | unwind_region_attrs: |
4893 | - _filterable_attribute_bag_delete(geis->region_filterable_attributes); |
4894 | + geis_filterable_attribute_bag_delete(geis->region_filterable_attributes); |
4895 | unwind_device_bag: |
4896 | geis_device_bag_delete(geis->devices); |
4897 | unwind_device_attrs: |
4898 | - _filterable_attribute_bag_delete(geis->device_filterable_attributes); |
4899 | + geis_filterable_attribute_bag_delete(geis->device_filterable_attributes); |
4900 | unwind_class_bag: |
4901 | geis_gesture_class_bag_delete(geis->gesture_classes); |
4902 | unwind_class_attrs: |
4903 | - _filterable_attribute_bag_delete(geis->class_filterable_attributes); |
4904 | + geis_filterable_attribute_bag_delete(geis->class_filterable_attributes); |
4905 | unwind_output_queue: |
4906 | geis_event_queue_delete(geis->output_event_queue); |
4907 | unwind_input_signal_pipe: |
4908 | @@ -564,6 +490,7 @@ |
4909 | { |
4910 | BACK_END_TYPE_NONE, |
4911 | BACK_END_TYPE_MOCK_ENGINE, |
4912 | + BACK_END_TYPE_DBUS, |
4913 | BACK_END_TYPE_XCB |
4914 | } BackendType; |
4915 | |
4916 | @@ -580,7 +507,7 @@ |
4917 | { |
4918 | if (0 == strcmp(init_arg_name, GEIS_INIT_SERVICE_PROVIDER)) |
4919 | { |
4920 | - geis_debug("initializing GEIS server"); |
4921 | + geis->server = geis_dbus_server_new(geis); |
4922 | } |
4923 | else if (0 == strcmp(init_arg_name, GEIS_INIT_TRACK_DEVICES)) |
4924 | { |
4925 | @@ -590,7 +517,7 @@ |
4926 | { |
4927 | /* no longer supported */ |
4928 | } |
4929 | - else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_MOCK_ENGINE)) |
4930 | + else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_MOCK_BACKEND)) |
4931 | { |
4932 | if (back_end_type != BACK_END_TYPE_NONE) |
4933 | { |
4934 | @@ -598,7 +525,15 @@ |
4935 | } |
4936 | back_end_type = BACK_END_TYPE_MOCK_ENGINE; |
4937 | } |
4938 | - else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_XCB)) |
4939 | + else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_DBUS_BACKEND)) |
4940 | + { |
4941 | + if (back_end_type != BACK_END_TYPE_NONE) |
4942 | + { |
4943 | + geis_error("multiple back ends requested, only using last request"); |
4944 | + } |
4945 | + back_end_type = BACK_END_TYPE_DBUS; |
4946 | + } |
4947 | + else if (0 == strcmp(init_arg_name, GEIS_INIT_UTOUCH_XCB_BACKEND)) |
4948 | { |
4949 | if (back_end_type != BACK_END_TYPE_NONE) |
4950 | { |
4951 | @@ -612,16 +547,22 @@ |
4952 | |
4953 | if (back_end_type == BACK_END_TYPE_MOCK_ENGINE) |
4954 | { |
4955 | - geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_MOCK_ENGINE); |
4956 | - } |
4957 | - else if (back_end_type ==BACK_END_TYPE_XCB) |
4958 | - { |
4959 | - geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_XCB); |
4960 | + geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_MOCK_BACKEND); |
4961 | + } |
4962 | + else if (back_end_type == BACK_END_TYPE_DBUS) |
4963 | + { |
4964 | + geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_DBUS_BACKEND); |
4965 | + geis->backend_pending = GEIS_TRUE; |
4966 | + } |
4967 | + else if (back_end_type == BACK_END_TYPE_XCB) |
4968 | + { |
4969 | + geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_XCB_BACKEND); |
4970 | } |
4971 | else |
4972 | { |
4973 | - geis_warning("back end not specified, defaulting to XCB"); |
4974 | - geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_XCB); |
4975 | + geis_warning("back end not specified, defaulting to DBus"); |
4976 | + geis->backend = geis_backend_by_name(geis, GEIS_INIT_UTOUCH_DBUS_BACKEND); |
4977 | + geis->backend_pending = GEIS_TRUE; |
4978 | } |
4979 | if (!geis->backend) |
4980 | { |
4981 | @@ -681,16 +622,18 @@ |
4982 | } |
4983 | |
4984 | geis_gesture_flick_delete(geis->flick); |
4985 | - _filterable_attribute_bag_delete(geis->special_filterable_attributes); |
4986 | - _filterable_attribute_bag_delete(geis->region_filterable_attributes); |
4987 | + geis_filterable_attribute_bag_delete(geis->special_filterable_attributes); |
4988 | + geis_filterable_attribute_bag_delete(geis->region_filterable_attributes); |
4989 | geis_device_bag_delete(geis->devices); |
4990 | - _filterable_attribute_bag_delete(geis->device_filterable_attributes); |
4991 | + geis_filterable_attribute_bag_delete(geis->device_filterable_attributes); |
4992 | geis_gesture_class_bag_delete(geis->gesture_classes); |
4993 | - _filterable_attribute_bag_delete(geis->class_filterable_attributes); |
4994 | + geis_filterable_attribute_bag_delete(geis->class_filterable_attributes); |
4995 | geis_event_queue_delete(geis->output_event_queue); |
4996 | close(geis->input_event_signal_pipe[0]); |
4997 | close(geis->input_event_signal_pipe[1]); |
4998 | geis_event_queue_delete(geis->input_event_queue); |
4999 | + if (geis->server) |
5000 | + geis_dbus_server_delete(geis->server); |
Added a trunk synch to resolve some merge conflicts.