nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #include <gio/gio.h> |
2 | #include <stdlib.h> |
||
3 | |||
4 | /* ---------------------------------------------------------------------------------------------------- */ |
||
5 | |||
6 | /* The object we want to export */ |
||
7 | typedef struct _MyObjectClass MyObjectClass; |
||
8 | typedef struct _MyObject MyObject; |
||
9 | |||
10 | struct _MyObjectClass |
||
11 | { |
||
12 | GObjectClass parent_class; |
||
13 | }; |
||
14 | |||
15 | struct _MyObject |
||
16 | { |
||
17 | GObject parent_instance; |
||
18 | |||
19 | gint count; |
||
20 | gchar *name; |
||
21 | }; |
||
22 | |||
23 | enum |
||
24 | { |
||
25 | PROP_0, |
||
26 | PROP_COUNT, |
||
27 | PROP_NAME |
||
28 | }; |
||
29 | |||
30 | static GType my_object_get_type (void); |
||
31 | G_DEFINE_TYPE (MyObject, my_object, G_TYPE_OBJECT); |
||
32 | |||
33 | static void |
||
34 | my_object_finalize (GObject *object) |
||
35 | { |
||
36 | MyObject *myobj = (MyObject*)object; |
||
37 | |||
38 | g_free (myobj->name); |
||
39 | |||
40 | G_OBJECT_CLASS (my_object_parent_class)->finalize (object); |
||
41 | } |
||
42 | |||
43 | static void |
||
44 | my_object_init (MyObject *object) |
||
45 | { |
||
46 | object->count = 0; |
||
47 | object->name = NULL; |
||
48 | } |
||
49 | |||
50 | static void |
||
51 | my_object_get_property (GObject *object, |
||
52 | guint prop_id, |
||
53 | GValue *value, |
||
54 | GParamSpec *pspec) |
||
55 | { |
||
56 | MyObject *myobj = (MyObject*)object; |
||
57 | |||
58 | switch (prop_id) |
||
59 | { |
||
60 | case PROP_COUNT: |
||
61 | g_value_set_int (value, myobj->count); |
||
62 | break; |
||
63 | |||
64 | case PROP_NAME: |
||
65 | g_value_set_string (value, myobj->name); |
||
66 | break; |
||
67 | |||
68 | default: |
||
69 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
||
70 | } |
||
71 | } |
||
72 | |||
73 | static void |
||
74 | my_object_set_property (GObject *object, |
||
75 | guint prop_id, |
||
76 | const GValue *value, |
||
77 | GParamSpec *pspec) |
||
78 | { |
||
79 | MyObject *myobj = (MyObject*)object; |
||
80 | |||
81 | switch (prop_id) |
||
82 | { |
||
83 | case PROP_COUNT: |
||
84 | myobj->count = g_value_get_int (value); |
||
85 | break; |
||
86 | |||
87 | case PROP_NAME: |
||
88 | g_free (myobj->name); |
||
89 | myobj->name = g_value_dup_string (value); |
||
90 | break; |
||
91 | |||
92 | default: |
||
93 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
||
94 | } |
||
95 | } |
||
96 | |||
97 | static void |
||
98 | my_object_class_init (MyObjectClass *class) |
||
99 | { |
||
100 | GObjectClass *gobject_class = G_OBJECT_CLASS (class); |
||
101 | |||
102 | gobject_class->finalize = my_object_finalize; |
||
103 | gobject_class->set_property = my_object_set_property; |
||
104 | gobject_class->get_property = my_object_get_property; |
||
105 | |||
106 | g_object_class_install_property (gobject_class, |
||
107 | PROP_COUNT, |
||
108 | g_param_spec_int ("count", |
||
109 | "Count", |
||
110 | "Count", |
||
111 | 0, 99999, 0, |
||
112 | G_PARAM_READWRITE)); |
||
113 | |||
114 | g_object_class_install_property (gobject_class, |
||
115 | PROP_NAME, |
||
116 | g_param_spec_string ("name", |
||
117 | "Name", |
||
118 | "Name", |
||
119 | NULL, |
||
120 | G_PARAM_READWRITE)); |
||
121 | } |
||
122 | |||
123 | /* A method that we want to export */ |
||
124 | static void |
||
125 | my_object_change_count (MyObject *myobj, |
||
126 | gint change) |
||
127 | { |
||
128 | myobj->count = 2 * myobj->count + change; |
||
129 | |||
130 | g_object_notify (G_OBJECT (myobj), "count"); |
||
131 | } |
||
132 | |||
133 | /* ---------------------------------------------------------------------------------------------------- */ |
||
134 | |||
135 | static GDBusNodeInfo *introspection_data = NULL; |
||
136 | |||
137 | /* Introspection data for the service we are exporting */ |
||
138 | static const gchar introspection_xml[] = |
||
139 | "<node>" |
||
140 | " <interface name='org.myorg.MyObject'>" |
||
141 | " <method name='ChangeCount'>" |
||
142 | " <arg type='i' name='change' direction='in'/>" |
||
143 | " </method>" |
||
144 | " <property type='i' name='Count' access='read'/>" |
||
145 | " <property type='s' name='Name' access='readwrite'/>" |
||
146 | " </interface>" |
||
147 | "</node>"; |
||
148 | |||
149 | |||
150 | static void |
||
151 | handle_method_call (GDBusConnection *connection, |
||
152 | const gchar *sender, |
||
153 | const gchar *object_path, |
||
154 | const gchar *interface_name, |
||
155 | const gchar *method_name, |
||
156 | GVariant *parameters, |
||
157 | GDBusMethodInvocation *invocation, |
||
158 | gpointer user_data) |
||
159 | { |
||
160 | MyObject *myobj = user_data; |
||
161 | |||
162 | if (g_strcmp0 (method_name, "ChangeCount") == 0) |
||
163 | { |
||
164 | gint change; |
||
165 | g_variant_get (parameters, "(i)", &change); |
||
166 | |||
167 | my_object_change_count (myobj, change); |
||
168 | |||
169 | g_dbus_method_invocation_return_value (invocation, NULL); |
||
170 | } |
||
171 | } |
||
172 | |||
173 | static GVariant * |
||
174 | handle_get_property (GDBusConnection *connection, |
||
175 | const gchar *sender, |
||
176 | const gchar *object_path, |
||
177 | const gchar *interface_name, |
||
178 | const gchar *property_name, |
||
179 | GError **error, |
||
180 | gpointer user_data) |
||
181 | { |
||
182 | GVariant *ret; |
||
183 | MyObject *myobj = user_data; |
||
184 | |||
185 | ret = NULL; |
||
186 | if (g_strcmp0 (property_name, "Count") == 0) |
||
187 | { |
||
188 | ret = g_variant_new_int32 (myobj->count); |
||
189 | } |
||
190 | else if (g_strcmp0 (property_name, "Name") == 0) |
||
191 | { |
||
192 | ret = g_variant_new_string (myobj->name ? myobj->name : ""); |
||
193 | } |
||
194 | |||
195 | return ret; |
||
196 | } |
||
197 | |||
198 | static gboolean |
||
199 | handle_set_property (GDBusConnection *connection, |
||
200 | const gchar *sender, |
||
201 | const gchar *object_path, |
||
202 | const gchar *interface_name, |
||
203 | const gchar *property_name, |
||
204 | GVariant *value, |
||
205 | GError **error, |
||
206 | gpointer user_data) |
||
207 | { |
||
208 | MyObject *myobj = user_data; |
||
209 | |||
210 | if (g_strcmp0 (property_name, "Count") == 0) |
||
211 | { |
||
212 | g_object_set (myobj, "count", g_variant_get_int32 (value), NULL); |
||
213 | } |
||
214 | else if (g_strcmp0 (property_name, "Name") == 0) |
||
215 | { |
||
216 | g_object_set (myobj, "name", g_variant_get_string (value, NULL), NULL); |
||
217 | } |
||
218 | |||
219 | return TRUE; |
||
220 | } |
||
221 | |||
222 | |||
223 | /* for now */ |
||
224 | static const GDBusInterfaceVTable interface_vtable = |
||
225 | { |
||
226 | handle_method_call, |
||
227 | handle_get_property, |
||
228 | handle_set_property |
||
229 | }; |
||
230 | |||
231 | static void |
||
232 | send_property_change (GObject *obj, |
||
233 | GParamSpec *pspec, |
||
234 | GDBusConnection *connection) |
||
235 | { |
||
236 | GVariantBuilder *builder; |
||
237 | GVariantBuilder *invalidated_builder; |
||
238 | MyObject *myobj = (MyObject *)obj; |
||
239 | |||
240 | builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY); |
||
241 | invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); |
||
242 | |||
243 | if (g_strcmp0 (pspec->name, "count") == 0) |
||
244 | g_variant_builder_add (builder, |
||
245 | "{sv}", |
||
246 | "Count", g_variant_new_int32 (myobj->count)); |
||
247 | else if (g_strcmp0 (pspec->name, "name") == 0) |
||
248 | g_variant_builder_add (builder, |
||
249 | "{sv}", |
||
250 | "Name", g_variant_new_string (myobj->name ? myobj->name : "")); |
||
251 | |||
252 | g_dbus_connection_emit_signal (connection, |
||
253 | NULL, |
||
254 | "/org/myorg/MyObject", |
||
255 | "org.freedesktop.DBus.Properties", |
||
256 | "PropertiesChanged", |
||
257 | g_variant_new ("(sa{sv}as)", |
||
258 | "org.myorg.MyObject", |
||
259 | builder, |
||
260 | invalidated_builder), |
||
261 | NULL); |
||
262 | } |
||
263 | |||
264 | static void |
||
265 | on_bus_acquired (GDBusConnection *connection, |
||
266 | const gchar *name, |
||
267 | gpointer user_data) |
||
268 | { |
||
269 | MyObject *myobj = user_data; |
||
270 | guint registration_id; |
||
271 | |||
272 | g_signal_connect (myobj, "notify", |
||
273 | G_CALLBACK (send_property_change), connection); |
||
274 | registration_id = g_dbus_connection_register_object (connection, |
||
275 | "/org/myorg/MyObject", |
||
276 | introspection_data->interfaces[0], |
||
277 | &interface_vtable, |
||
278 | myobj, |
||
279 | NULL, /* user_data_free_func */ |
||
280 | NULL); /* GError** */ |
||
281 | g_assert (registration_id > 0); |
||
282 | } |
||
283 | |||
284 | static void |
||
285 | on_name_acquired (GDBusConnection *connection, |
||
286 | const gchar *name, |
||
287 | gpointer user_data) |
||
288 | { |
||
289 | } |
||
290 | |||
291 | static void |
||
292 | on_name_lost (GDBusConnection *connection, |
||
293 | const gchar *name, |
||
294 | gpointer user_data) |
||
295 | { |
||
296 | exit (1); |
||
297 | } |
||
298 | |||
299 | int |
||
300 | main (int argc, char *argv[]) |
||
301 | { |
||
302 | guint owner_id; |
||
303 | GMainLoop *loop; |
||
304 | MyObject *myobj; |
||
305 | |||
306 | /* We are lazy here - we don't want to manually provide |
||
307 | * the introspection data structures - so we just build |
||
308 | * them from XML. |
||
309 | */ |
||
310 | introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); |
||
311 | g_assert (introspection_data != NULL); |
||
312 | |||
313 | myobj = g_object_new (my_object_get_type (), NULL); |
||
314 | |||
315 | owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, |
||
316 | "org.myorg.MyObject", |
||
317 | G_BUS_NAME_OWNER_FLAGS_NONE, |
||
318 | on_bus_acquired, |
||
319 | on_name_acquired, |
||
320 | on_name_lost, |
||
321 | myobj, |
||
322 | NULL); |
||
323 | |||
324 | loop = g_main_loop_new (NULL, FALSE); |
||
325 | g_main_loop_run (loop); |
||
326 | |||
327 | g_bus_unown_name (owner_id); |
||
328 | |||
329 | g_dbus_node_info_unref (introspection_data); |
||
330 | |||
331 | g_object_unref (myobj); |
||
332 | |||
333 | return 0; |
||
334 | } |