dbus 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,105 @@
1
+ /*--------------------------------------------------
2
+ * D-BUS bindings for Ruby
3
+ * (C) Copyright 2004 Leon Breedt
4
+ * (C) Copyright 2004 Provenco Group Ltd
5
+ *
6
+ * Licensed under the same terms as the D-BUS library
7
+ *--------------------------------------------------*/
8
+
9
+ #include "ruby-dbus.h"
10
+
11
+ VALUE mDBus;
12
+ VALUE mDBusBinding;
13
+ VALUE eDBusError;
14
+
15
+ /*
16
+ * call-seq:
17
+ * new => self
18
+ *
19
+ * The new method of this class is not available for invocation.
20
+ */
21
+ VALUE
22
+ rdbus_private_method(VALUE klass)
23
+ {
24
+ rb_raise(rb_eNoMethodError, "Method is unavailable to non-native methods");
25
+ return Qnil;
26
+ }
27
+
28
+ /*
29
+ * Initializes Glib GThreads for usage by D-BUS.
30
+ *
31
+ * This is only necessary for applications that will be using GThreads.
32
+ */
33
+ static VALUE
34
+ mDBusBinding_init_gthreads(VALUE klass)
35
+ {
36
+ dbus_g_thread_init();
37
+ return Qnil;
38
+ }
39
+
40
+ /*
41
+ * The DBus module contains all the classes and modules related to the D-BUS
42
+ * bindings.
43
+ *
44
+ * Some global D-BUS constants from dbus-shared.h[http://www.freedesktop.org/software/dbus/doc/api/html/dbus-shared_8h-source.html]
45
+ * and dbus-protocol.h[http://www.freedesktop.org/software/dbus/doc/api/html/dbus-protocol_8h-source.html] are also defined in this
46
+ * module.
47
+ *
48
+ * It is recommended that you use the classes in the DBus module instead of
49
+ * the classes in the DBus::Binding module unless you have more advanced
50
+ * needs.
51
+ *
52
+ * The DBus::Binding module classes map directly to the D-BUS C API.
53
+ */
54
+ void
55
+ Init_dbus()
56
+ {
57
+ mDBus = rb_define_module("DBus");
58
+ mDBusBinding = rb_define_module_under(mDBus, "Binding");
59
+ eDBusError = rb_define_class_under(mDBus, "DBusError", rb_eStandardError);
60
+
61
+ rb_define_const(mDBus, "BUS_SESSION", INT2FIX(DBUS_BUS_SESSION));
62
+ rb_define_const(mDBus, "BUS_SYSTEM", INT2FIX(DBUS_BUS_SYSTEM));
63
+ rb_define_const(mDBus, "BUS_ACTIVATION", INT2FIX(DBUS_BUS_ACTIVATION));
64
+
65
+ rb_define_const(mDBus, "DISPATCH_DATA_REMAINS", INT2FIX(DBUS_DISPATCH_DATA_REMAINS));
66
+ rb_define_const(mDBus, "DISPATCH_COMPLETE", INT2FIX(DBUS_DISPATCH_COMPLETE));
67
+ rb_define_const(mDBus, "DISPATCH_NEED_MEMORY", INT2FIX(DBUS_DISPATCH_NEED_MEMORY));
68
+
69
+ rb_define_const(mDBus, "SERVICE_FLAG_PROHIBIT_REPLACEMENT", INT2FIX(DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT));
70
+ rb_define_const(mDBus, "SERVICE_FLAG_REPLACE_EXISTING", INT2FIX(DBUS_SERVICE_FLAG_REPLACE_EXISTING));
71
+
72
+ rb_define_const(mDBus, "HANDLER_RESULT_HANDLED", INT2FIX(DBUS_HANDLER_RESULT_HANDLED));
73
+ rb_define_const(mDBus, "HANDLER_RESULT_NOT_YET_HANDLED", INT2FIX(DBUS_HANDLER_RESULT_NOT_YET_HANDLED));
74
+ rb_define_const(mDBus, "HANDLER_RESULT_NEED_MEMORY", INT2FIX(DBUS_HANDLER_RESULT_NEED_MEMORY));
75
+
76
+ rb_define_const(mDBus, "MESSAGE_TYPE_INVALID", INT2FIX(DBUS_MESSAGE_TYPE_INVALID));
77
+ rb_define_const(mDBus, "MESSAGE_TYPE_METHOD_CALL", INT2FIX(DBUS_MESSAGE_TYPE_METHOD_CALL));
78
+ rb_define_const(mDBus, "MESSAGE_TYPE_METHOD_RETURN", INT2FIX(DBUS_MESSAGE_TYPE_METHOD_RETURN));
79
+ rb_define_const(mDBus, "MESSAGE_TYPE_ERROR", INT2FIX(DBUS_MESSAGE_TYPE_ERROR));
80
+ rb_define_const(mDBus, "MESSAGE_TYPE_SIGNAL", INT2FIX(DBUS_MESSAGE_TYPE_SIGNAL));
81
+
82
+ rb_define_const(mDBus, "TYPE_INVALID", INT2FIX(DBUS_TYPE_INVALID));
83
+ rb_define_const(mDBus, "TYPE_NIL", INT2FIX(DBUS_TYPE_NIL));
84
+ rb_define_const(mDBus, "TYPE_BYTE", INT2FIX(DBUS_TYPE_BYTE));
85
+ rb_define_const(mDBus, "TYPE_BOOLEAN", INT2FIX(DBUS_TYPE_BOOLEAN));
86
+ rb_define_const(mDBus, "TYPE_INT32", INT2FIX(DBUS_TYPE_INT32));
87
+ rb_define_const(mDBus, "TYPE_UINT32", INT2FIX(DBUS_TYPE_UINT32));
88
+ rb_define_const(mDBus, "TYPE_INT64", INT2FIX(DBUS_TYPE_INT64));
89
+ rb_define_const(mDBus, "TYPE_UINT64", INT2FIX(DBUS_TYPE_UINT64));
90
+ rb_define_const(mDBus, "TYPE_DOUBLE", INT2FIX(DBUS_TYPE_DOUBLE));
91
+ rb_define_const(mDBus, "TYPE_STRING", INT2FIX(DBUS_TYPE_STRING));
92
+ rb_define_const(mDBus, "TYPE_CUSTOM", INT2FIX(DBUS_TYPE_CUSTOM));
93
+ rb_define_const(mDBus, "TYPE_ARRAY", INT2FIX(DBUS_TYPE_ARRAY));
94
+ rb_define_const(mDBus, "TYPE_DICT", INT2FIX(DBUS_TYPE_DICT));
95
+ rb_define_const(mDBus, "TYPE_OBJECT_PATH", INT2FIX(DBUS_TYPE_OBJECT_PATH));
96
+
97
+ rb_define_module_function(mDBusBinding, "init_gthreads", mDBusBinding_init_gthreads, 0);
98
+
99
+ Init_dbus_bus();
100
+ Init_dbus_connection();
101
+ Init_dbus_message();
102
+ Init_dbus_message_iter();
103
+ Init_dbus_pending_call();
104
+ Init_dbus_server();
105
+ }
@@ -0,0 +1,704 @@
1
+ /*--------------------------------------------------
2
+ * D-BUS bindings for Ruby
3
+ * (C) Copyright 2004 Leon Breedt
4
+ * (C) Copyright 2004 Provenco Group Ltd
5
+ *
6
+ * Licensed under the same terms as the D-BUS library
7
+ *--------------------------------------------------*/
8
+
9
+ #include "ruby-dbus.h"
10
+
11
+ static void _free_connection(DBusConnection *conn);
12
+
13
+ VALUE cDBusConnection;
14
+
15
+ RDBUS_GENERATE_NEW(cDBusConnection, DBusConnection *, _free_connection)
16
+ RDBUS_GENERATE_GET(DBusConnection)
17
+
18
+ /* Helpers */
19
+
20
+ static void
21
+ _free_connection(DBusConnection *conn)
22
+ {
23
+ dbus_connection_disconnect(conn);
24
+ dbus_connection_unref(conn);
25
+ }
26
+
27
+ /*
28
+ * call-seq:
29
+ * new(address) => connection
30
+ *
31
+ * Opens a connection to the D-BUS daemon located at the given +address+.
32
+ * An address is a string in the format <tt>type:param1=value1,param2=value2</tt>.
33
+ * DBusServer#get_address returns an address in this format.
34
+ *
35
+ * Example:
36
+ * unix:abstract=/tmp/dbus-X0XXgcf
37
+ *
38
+ * Returns a DBusConnection instance.
39
+ */
40
+ static VALUE
41
+ cDBusConnection_open(VALUE klass, VALUE address)
42
+ {
43
+ DBusConnection *conn;
44
+
45
+ conn = NULL;
46
+ RDBUS_TRY(conn = dbus_connection_open(StringValuePtr(address), &error));
47
+ RDBUS_RAISE_IF(conn == NULL, "failed to open D-BUS connection");
48
+ return RDBUS_NEW(cDBusConnection, conn);
49
+ }
50
+
51
+ /*
52
+ * call-seq:
53
+ * get_base_service => name
54
+ *
55
+ * Gets the base service name of the connection. This value can be used
56
+ * for the +destination+ field of a DBusMessage.
57
+ */
58
+ static VALUE
59
+ cDBusConnection_get_base_service(VALUE self)
60
+ {
61
+ return rb_str_new2(dbus_bus_get_base_service(CONN_GET(self)));
62
+ }
63
+
64
+ /*
65
+ * call-seq:
66
+ * setup_with_g_main => nil
67
+ *
68
+ * Sets up the watch and timeout functionality of the connection to
69
+ * integrate with the GLIB main loop.
70
+ */
71
+ static VALUE
72
+ cDBusConnection_setup_with_g_main(VALUE self)
73
+ {
74
+ dbus_connection_setup_with_g_main(CONN_GET(self), NULL);
75
+ return Qnil;
76
+ }
77
+
78
+ /*
79
+ * call-seq:
80
+ * disconnect => nil
81
+ *
82
+ * Disconnects this connection from the bus
83
+ */
84
+ static VALUE
85
+ cDBusConnection_disconnect(VALUE self)
86
+ {
87
+ dbus_connection_disconnect(CONN_GET(self));
88
+ return Qnil;
89
+ }
90
+
91
+ /*
92
+ * call-seq:
93
+ * get_is_connected => true | false
94
+ *
95
+ * Returns +true+ if this connection is connected to the bus
96
+ */
97
+ static VALUE
98
+ cDBusConnection_get_is_connected(VALUE self)
99
+ {
100
+ if (dbus_connection_get_is_connected(CONN_GET(self)))
101
+ return Qtrue;
102
+ return Qfalse;
103
+ }
104
+
105
+ /*
106
+ * call-seq:
107
+ * get_is_authenticated => true | false
108
+ *
109
+ * Returns +true+ if this connection was authenticated
110
+ */
111
+ static VALUE
112
+ cDBusConnection_get_is_authenticated(VALUE self)
113
+ {
114
+ if (dbus_connection_get_is_authenticated(CONN_GET(self)))
115
+ return Qtrue;
116
+ return Qfalse;
117
+ }
118
+
119
+ /*
120
+ * call-seq:
121
+ * flush => nil
122
+ *
123
+ * Blocks until the outgoing message queue is empty
124
+ */
125
+ static VALUE
126
+ cDBusConnection_flush(VALUE self)
127
+ {
128
+ dbus_connection_flush(CONN_GET(self));
129
+ return Qnil;
130
+ }
131
+
132
+ /*
133
+ * call-seq:
134
+ * borrow_message => message
135
+ *
136
+ * Returns the first message from the incoming message queue, while
137
+ * leaving it in the queue. While borrowed, nothing else can get at
138
+ * the message, so the message <i>has</i> to be returned with
139
+ * DBusConnection#return_message or stolen with DBusConnection#steal_borrowed_message.
140
+ *
141
+ * It is not recommended that you use this method, use the standard
142
+ * dispatching mechanisms instead.
143
+ */
144
+ static VALUE
145
+ cDBusConnection_borrow_message(VALUE self)
146
+ {
147
+ DBusMessage *message;
148
+
149
+ message = NULL;
150
+ message = dbus_connection_borrow_message(CONN_GET(self));
151
+ if (message == NULL)
152
+ return Qnil;
153
+ return RDBUS_NEW(cDBusMessage, message);
154
+ }
155
+
156
+ /*
157
+ * call-seq:
158
+ * return_message(message) => nil
159
+ *
160
+ * Returns a previously borrowed message to the queue
161
+ *
162
+ * It is not recommended that you use this method, use the standard
163
+ * dispatching mechanisms instead.
164
+ */
165
+ static VALUE
166
+ cDBusConnection_return_message(VALUE self, VALUE message)
167
+ {
168
+ dbus_connection_return_message(
169
+ CONN_GET(self),
170
+ RDBUS_GET(DBusMessage, message)
171
+ );
172
+ return Qnil;
173
+ }
174
+
175
+ /*
176
+ * call-seq:
177
+ * steal_borrowed_message(message) => nil
178
+ *
179
+ * Steals a previously borrowed message (in other words, take ownership
180
+ * of it and remove it from the queue).
181
+ *
182
+ * It is not recommended that you use this method, use the standard
183
+ * dispatching mechanisms instead.
184
+ */
185
+ static VALUE
186
+ cDBusConnection_steal_borrowed_message(VALUE self, VALUE message)
187
+ {
188
+ dbus_connection_steal_borrowed_message(
189
+ CONN_GET(self),
190
+ RDBUS_GET(DBusMessage, message)
191
+ );
192
+ return Qnil;
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * pop_message => message
198
+ *
199
+ * Pops the first message from the incoming message queue, removing it
200
+ * from the queue.
201
+ *
202
+ * It is not recommended that you use this method, use the standard
203
+ * dispatching mechanisms instead.
204
+ */
205
+ static VALUE
206
+ cDBusConnection_pop_message(VALUE self)
207
+ {
208
+ DBusMessage *message;
209
+
210
+ message = NULL;
211
+ message = dbus_connection_pop_message(CONN_GET(self));
212
+ if (message == NULL)
213
+ return Qnil;
214
+ return RDBUS_NEW(cDBusMessage, message);
215
+ }
216
+
217
+ /*
218
+ * call-seq:
219
+ * get_dispatch_status => status
220
+ *
221
+ * Returns the current status that would have been returned by
222
+ * DBusConnection#dispatch, without performing any message dispatching.
223
+ */
224
+ static VALUE
225
+ cDBusConnection_get_dispatch_status(VALUE self)
226
+ {
227
+ return INT2FIX(dbus_connection_get_dispatch_status(CONN_GET(self)));
228
+ }
229
+
230
+ /*
231
+ * call-seq:
232
+ * dispatch => status
233
+ *
234
+ * Processes buffered data, handles watches and queues zero or more
235
+ * incoming messages. Pops the first message on the incoming queue,
236
+ * processes it by calling into its handlers, and then unrefs it.
237
+ *
238
+ * Returns a status indicating whether more messages are available for
239
+ * dispatching, more memory is needed, or all data has been processed.
240
+ *
241
+ * It is not recommended that you use this directly, instead use the
242
+ * wrapper APIs in DBus::Object, DBus::ObjectTree or DBus::Service and
243
+ * integrate them with your mainloop.
244
+ */
245
+ static VALUE
246
+ cDBusConnection_dispatch(VALUE self)
247
+ {
248
+ return INT2FIX(dbus_connection_dispatch(CONN_GET(self)));
249
+ }
250
+
251
+ /*
252
+ * call-seq:
253
+ * send(message) => true | false
254
+ *
255
+ * Enqueues the given message for sending on the outgoing queue. Sending
256
+ * happens asynchronously unless you force the issue by calling DBusConnection#flush.
257
+ *
258
+ * Returns +false+ if the message could not be enqueued due to lack of
259
+ * memory, +true+ otherwise.
260
+ */
261
+ static VALUE
262
+ cDBusConnection_send(VALUE self, VALUE message)
263
+ {
264
+ if (dbus_connection_send(CONN_GET(self), RDBUS_GET(DBusMessage, message), NULL))
265
+ return Qtrue;
266
+ return Qfalse;
267
+ }
268
+
269
+ /*
270
+ * call-seq:
271
+ * send_with_reply(message, timeout_milliseconds) => [true|false, DBusPendingCall|nil]
272
+ *
273
+ * Enqueues the given message for sending on the outgoing queue. The timeout
274
+ * specified can also be <tt>-1</tt>, in which case a sane default value is
275
+ * used.
276
+ *
277
+ * If successfully queued, a <tt>[true, DBusPendingCall]</tt> tuple is returned.
278
+ * Otherwise, a <tt>[false, nil]</tt> tuple is returned.
279
+ *
280
+ * This method returns immediately.
281
+ */
282
+ static VALUE
283
+ cDBusConnection_send_with_reply(VALUE self, VALUE msg, VALUE timeout)
284
+ {
285
+ VALUE ary;
286
+ VALUE ret;
287
+ DBusPendingCall *call;
288
+
289
+ ary = Qnil;
290
+ ret = Qfalse;
291
+ call = NULL;
292
+ if (dbus_connection_send_with_reply(CONN_GET(self), MSG_GET(msg), &call,
293
+ NUM2INT(timeout)))
294
+ ret = Qtrue;
295
+ ary = rb_ary_new2(2);
296
+ rb_ary_push(ary, ret);
297
+ if (call != NULL)
298
+ rb_ary_push(ary, RDBUS_NEW(cDBusPendingCall, call));
299
+ else
300
+ rb_ary_push(ary, Qnil);
301
+ return ary;
302
+ }
303
+
304
+ /*
305
+ * call-seq:
306
+ * send_with_reply_and_block(message, timeout_milliseconds) => message
307
+ *
308
+ * Enqueues the given message for sending on the outgoing queue, and blocks
309
+ * for the given timeout until a reply is received, or the timeout expires,
310
+ * whichever comes first.
311
+ */
312
+ static VALUE
313
+ cDBusConnection_send_with_reply_and_block(VALUE self, VALUE msg, VALUE timeout)
314
+ {
315
+ DBusMessage *return_msg;
316
+
317
+ return_msg = NULL;
318
+ RDBUS_TRY(
319
+ return_msg = dbus_connection_send_with_reply_and_block(
320
+ CONN_GET(self), MSG_GET(msg), NUM2INT(timeout), &error)
321
+ )
322
+ if (return_msg == NULL)
323
+ return Qnil;
324
+ return RDBUS_NEW(cDBusMessage, return_msg);
325
+ }
326
+
327
+ /*
328
+ * call-seq:
329
+ * get_max_message_size => size
330
+ *
331
+ * Returns the maximum message size in bytes that this connection may
332
+ * receive
333
+ */
334
+ static VALUE
335
+ cDBusConnection_get_max_message_size(VALUE self)
336
+ {
337
+ return LONG2NUM(dbus_connection_get_max_message_size(CONN_GET(self)));
338
+ }
339
+
340
+ /*
341
+ * call-seq:
342
+ * set_max_message_size(value) => nil
343
+ *
344
+ * Sets the maximum message size in bytes that this connection may
345
+ * receive
346
+ */
347
+ static VALUE
348
+ cDBusConnection_set_max_message_size(VALUE self, VALUE size)
349
+ {
350
+ dbus_connection_set_max_message_size(CONN_GET(self), NUM2LONG(size));
351
+ return Qnil;
352
+ }
353
+
354
+ /*
355
+ * call-seq:
356
+ * get_max_received_size => size
357
+ *
358
+ * Returns the maximum number of bytes for all messages received on this
359
+ * connection, see DBusConnection#set_max_received_size for more details.
360
+ */
361
+ static VALUE
362
+ cDBusConnection_get_max_received_size(VALUE self)
363
+ {
364
+ return LONG2NUM(dbus_connection_get_max_received_size(CONN_GET(self)));
365
+ }
366
+
367
+
368
+ /*
369
+ * call-seq:
370
+ * set_max_received_size(size) => nil
371
+ *
372
+ * Sets the maximum number of bytes for all messages received on this
373
+ * connection. Messages count toward the maximum until they are garbage
374
+ * collected. When the maximum is reached, the connection will not read
375
+ * more data until some messages are garbage collected.
376
+ */
377
+ static VALUE
378
+ cDBusConnection_set_max_received_size(VALUE self, VALUE size)
379
+ {
380
+ dbus_connection_set_max_received_size(CONN_GET(self), NUM2LONG(size));
381
+ return Qnil;
382
+ }
383
+
384
+ /*
385
+ * call-seq:
386
+ * get_outgoing_size => size
387
+ *
388
+ * Returns the approximate size in bytes of all messages in the outgoing
389
+ * message queue.
390
+ */
391
+ static VALUE
392
+ cDBusConnection_get_outgoing_size(VALUE self)
393
+ {
394
+ return LONG2NUM(dbus_connection_get_outgoing_size(CONN_GET(self)));
395
+ }
396
+
397
+ static VALUE
398
+ _real_call_unregister_cb(VALUE args)
399
+ {
400
+ VALUE *argp = (VALUE*)args;
401
+ VALUE unregister_cb = argp[0];
402
+ return rb_funcall2(unregister_cb, rb_intern("call"), 1, argp+1);
403
+ }
404
+
405
+ static void
406
+ _on_object_path_unregister(DBusConnection *conn, void *user_data)
407
+ {
408
+ VALUE *data;
409
+ VALUE unregister_cb;
410
+ VALUE message_cb;
411
+ VALUE args[2];
412
+ int exc;
413
+
414
+ data = (VALUE *)user_data;
415
+ unregister_cb = data[0];
416
+ message_cb = data[1];
417
+ args[0] = unregister_cb;
418
+ args[1] = RDBUS_NEW(cDBusConnection, conn);
419
+
420
+ exc = 0;
421
+ rb_protect(_real_call_unregister_cb, (VALUE)args, &exc);
422
+
423
+ if (exc)
424
+ rb_warn("Unregister callback raised exception (ignored)");
425
+ rb_gc_unregister_address(&unregister_cb);
426
+ rb_gc_unregister_address(&message_cb);
427
+ ruby_xfree(data);
428
+ }
429
+
430
+ static VALUE
431
+ _real_call_message_cb(VALUE args)
432
+ {
433
+ VALUE *argp = (VALUE*)args;
434
+ VALUE message_cb = argp[0];
435
+ return rb_funcall2(message_cb, rb_intern("call"), 2, argp+1);
436
+ }
437
+
438
+ static DBusHandlerResult
439
+ _on_object_path_message(DBusConnection *conn, DBusMessage *msg, void *user_data)
440
+ {
441
+ VALUE *data;
442
+ VALUE message_cb;
443
+ VALUE ret;
444
+ VALUE args[3];
445
+ int exc;
446
+
447
+ data = (VALUE *)user_data;
448
+ message_cb = data[1];
449
+ args[0] = message_cb;
450
+ args[1] = RDBUS_NEW(cDBusConnection, conn);
451
+ args[2] = RDBUS_NEW(cDBusMessage, msg);
452
+
453
+ exc = 0;
454
+ ret = rb_protect(_real_call_message_cb, (VALUE)args, &exc);
455
+
456
+ if (exc)
457
+ rb_warn("Message callback raised exception (ignored)");
458
+ if (ret == Qnil)
459
+ return DBUS_HANDLER_RESULT_HANDLED;
460
+ return NUM2INT(ret);
461
+ }
462
+
463
+ /*
464
+ * call-seq:
465
+ * register_object_path(path, unregister_proc, message_proc)
466
+ *
467
+ * Registers a handler for the given path in the object hierarchy.
468
+ *
469
+ * The +unregister_proc+ block will be called when the object path is being
470
+ * unregistered with a +connection+ argument.
471
+ *
472
+ * The +message_proc+ block will be called for messages sent to the exact
473
+ * path specified, with the arguments +connection, message+.
474
+ *
475
+ * = Any exceptions thrown by your blocks will be silently ignored to ensure
476
+ * D-BUS integrity, so keep the handler blocks simple
477
+ */
478
+ static VALUE
479
+ cDBusConnection_register_object_path(VALUE self, VALUE path,
480
+ VALUE unregister_cb, VALUE message_cb)
481
+ {
482
+ DBusObjectPathVTable vtable;
483
+ VALUE *user_data;
484
+
485
+ vtable.unregister_function = _on_object_path_unregister;
486
+ vtable.message_function = _on_object_path_message;
487
+
488
+ user_data = ALLOC_N(VALUE, 2);
489
+ user_data[0] = unregister_cb;
490
+ user_data[1] = message_cb;
491
+
492
+ if (dbus_connection_register_object_path(CONN_GET(self), StringValuePtr(path),
493
+ &vtable, (void *)user_data))
494
+ {
495
+ rb_gc_register_address(&unregister_cb);
496
+ rb_gc_register_address(&message_cb);
497
+ return Qtrue;
498
+ }
499
+ ruby_xfree(user_data);
500
+ return Qfalse;
501
+ }
502
+
503
+ /*
504
+ * call-seq:
505
+ * register_fallback(path, unregister_proc, message_proc)
506
+ *
507
+ * Registers a fallback handler for a section of the object hierarchy.
508
+ *
509
+ * The +unregister_proc+ block will be called when the object path is being
510
+ * unregistered with a +connection+ argument.
511
+ *
512
+ * The +message_proc+ block will be called for messages at or below the
513
+ * given object path, with the arguments +connection, message+.
514
+ *
515
+ * = Any exceptions thrown by your blocks will be silently ignored to ensure
516
+ * D-BUS integrity, so keep the handler blocks simple
517
+ */
518
+ static VALUE
519
+ cDBusConnection_register_fallback(VALUE self, VALUE path,
520
+ VALUE unregister_cb, VALUE message_cb)
521
+ {
522
+ DBusObjectPathVTable vtable;
523
+ VALUE *user_data;
524
+
525
+ vtable.unregister_function = _on_object_path_unregister;
526
+ vtable.message_function = _on_object_path_message;
527
+
528
+ user_data = ALLOC_N(VALUE, 2);
529
+ user_data[0] = unregister_cb;
530
+ user_data[1] = message_cb;
531
+ if (dbus_connection_register_fallback(CONN_GET(self), StringValuePtr(path),
532
+ &vtable, (void *)user_data))
533
+ {
534
+ rb_gc_register_address(&unregister_cb);
535
+ rb_gc_register_address(&message_cb);
536
+ return Qtrue;
537
+ }
538
+ ruby_xfree(user_data);
539
+ return Qfalse;
540
+ }
541
+
542
+ static void
543
+ _free_filter_data(void *user_data)
544
+ {
545
+ VALUE *data = (VALUE*)user_data;
546
+ VALUE filter_cb = data[0];
547
+ rb_gc_unregister_address(&filter_cb);
548
+ ruby_xfree(data);
549
+ }
550
+
551
+ static VALUE
552
+ _real_call_filter_cb(VALUE args)
553
+ {
554
+ VALUE *argp = (VALUE*)args;
555
+ VALUE filter_cb = argp[0];
556
+ return rb_funcall2(filter_cb, rb_intern("call"), 2, argp+1);
557
+ }
558
+
559
+ static DBusHandlerResult
560
+ _on_filter_message(DBusConnection *conn, DBusMessage *msg, void *user_data)
561
+ {
562
+ VALUE *data;
563
+ VALUE filter_cb;
564
+ VALUE ret;
565
+ VALUE args[3];
566
+ int exc;
567
+
568
+ data = (VALUE*)user_data;
569
+ filter_cb = data[0];
570
+ args[0] = filter_cb;
571
+ args[1] = RDBUS_NEW(cDBusConnection, conn);
572
+ args[2] = RDBUS_NEW(cDBusMessage, msg);
573
+
574
+ exc = 0;
575
+ ret = rb_protect(_real_call_filter_cb, (VALUE)args, &exc);
576
+
577
+ if (exc)
578
+ rb_warn("Filter callback raised exception (ignored)");
579
+ if (ret == Qnil)
580
+ return DBUS_HANDLER_RESULT_HANDLED;
581
+ return NUM2INT(ret);
582
+ }
583
+
584
+ /*
585
+ * call-seq:
586
+ * add_filter(filter_proc) => true | false
587
+ *
588
+ * Adds a message filter on this connection.
589
+ *
590
+ * The +filter_proc+ block will be called for all incoming messages,
591
+ * before any handlers registered using DBusConnection#register_object_path
592
+ * or DBusConnection#register_fallback.
593
+ *
594
+ * The same filter block can be added more than once, in which case it
595
+ * will be called more than once.
596
+ *
597
+ * Returns +true+ if the filter was added, +false+ if there was not enough
598
+ * memory.
599
+ */
600
+ static VALUE
601
+ cDBusConnection_add_filter(VALUE self, VALUE filter_cb)
602
+ {
603
+ VALUE *data;
604
+
605
+ data = ALLOC_N(VALUE, 1);
606
+ data[0] = filter_cb;
607
+ if (dbus_connection_add_filter(CONN_GET(self), _on_filter_message,
608
+ (void*)data, _free_filter_data))
609
+ {
610
+ rb_gc_register_address(&filter_cb);
611
+ return Qtrue;
612
+ }
613
+ ruby_xfree(data);
614
+ return Qfalse;
615
+ }
616
+
617
+ /*
618
+ * call-seq:
619
+ * list_registered(parent_path) => array
620
+ *
621
+ * Returns a list of registered object path and fallback handlers for
622
+ * the given parent path.
623
+ */
624
+ static VALUE
625
+ cDBusConnection_list_registered(VALUE self, VALUE parent_path)
626
+ {
627
+ char **entries;
628
+ VALUE ret;
629
+
630
+ ret = rb_ary_new();
631
+ entries = NULL;
632
+ if (dbus_connection_list_registered(CONN_GET(self),
633
+ StringValuePtr(parent_path), &entries) && entries != NULL)
634
+ {
635
+ int i = 0;
636
+ while (entries[i] != NULL)
637
+ rb_ary_push(ret, rb_str_new2(entries[i++]));
638
+ dbus_free_string_array(entries);
639
+ }
640
+ return ret;
641
+ }
642
+
643
+ /*
644
+ * Document-module: DBus::Binding
645
+ *
646
+ * The DBus::Binding module contains the internal binding classes that
647
+ * map directly to the D-BUS C API.
648
+ */
649
+
650
+ /*
651
+ * Document-class: DBus::Binding::DBusConnection
652
+ *
653
+ * DBusConnection implements a connection to a D-BUS daemon. D-BUS messages
654
+ * are sent and received using this connection.
655
+ *
656
+ * The recommended way of obtaining a DBusConnection instance for normal
657
+ * usage is to use DBus::Binding#bus_get to obtain a connection to one of the
658
+ * well-known message buses.
659
+ *
660
+ * Messages are sent and received when the DBusConnection#dispatch method is
661
+ * called, however, the recommended way to use this is to integrate into an
662
+ * existing main loop such as that of GLib by using DBusConnection#setup_with_g_main,
663
+ * as this hides all the low level internals of dispatching and watch/timeout
664
+ * monitoring from you.
665
+ */
666
+ void
667
+ Init_dbus_connection()
668
+ {
669
+ cDBusConnection = rb_define_class_under(mDBusBinding, "DBusConnection", rb_cObject);
670
+
671
+ rb_define_singleton_method(cDBusConnection, "open", cDBusConnection_open, 1);
672
+ rb_define_singleton_method(cDBusConnection, "new", cDBusConnection_open, 1);
673
+
674
+ rb_define_method(cDBusConnection, "get_base_service", cDBusConnection_get_base_service, 0);
675
+ rb_define_method(cDBusConnection, "setup_with_g_main", cDBusConnection_setup_with_g_main, 0);
676
+ rb_define_method(cDBusConnection, "disconnect", cDBusConnection_disconnect, 0);
677
+ rb_define_method(cDBusConnection, "get_is_connected", cDBusConnection_get_is_connected, 0);
678
+ rb_define_method(cDBusConnection, "get_is_authenticated", cDBusConnection_get_is_authenticated, 0);
679
+ rb_define_method(cDBusConnection, "flush", cDBusConnection_flush, 0);
680
+
681
+ rb_define_method(cDBusConnection, "borrow_message", cDBusConnection_borrow_message, 0);
682
+ rb_define_method(cDBusConnection, "return_message", cDBusConnection_return_message, 1);
683
+ rb_define_method(cDBusConnection, "steal_borrowed_message", cDBusConnection_steal_borrowed_message, 1);
684
+ rb_define_method(cDBusConnection, "pop_message", cDBusConnection_pop_message, 0);
685
+
686
+ rb_define_method(cDBusConnection, "get_dispatch_status", cDBusConnection_get_dispatch_status, 0);
687
+ rb_define_method(cDBusConnection, "dispatch", cDBusConnection_dispatch, 0);
688
+
689
+ rb_define_method(cDBusConnection, "send", cDBusConnection_send, 1);
690
+ rb_define_method(cDBusConnection, "send_with_reply", cDBusConnection_send_with_reply, 2);
691
+ rb_define_method(cDBusConnection, "send_with_reply_and_block", cDBusConnection_send_with_reply_and_block, 2);
692
+
693
+ rb_define_method(cDBusConnection, "add_filter", cDBusConnection_add_filter, 1);
694
+
695
+ rb_define_method(cDBusConnection, "get_max_message_size", cDBusConnection_get_max_message_size, 0);
696
+ rb_define_method(cDBusConnection, "set_max_message_size", cDBusConnection_set_max_message_size, 1);
697
+ rb_define_method(cDBusConnection, "get_max_received_size", cDBusConnection_get_max_received_size, 0);
698
+ rb_define_method(cDBusConnection, "set_max_received_size", cDBusConnection_set_max_received_size, 1);
699
+ rb_define_method(cDBusConnection, "get_outgoing_size", cDBusConnection_get_outgoing_size, 0);
700
+
701
+ rb_define_method(cDBusConnection, "register_object_path", cDBusConnection_register_object_path, 3);
702
+ rb_define_method(cDBusConnection, "register_fallback", cDBusConnection_register_fallback, 3);
703
+ rb_define_method(cDBusConnection, "list_registered", cDBusConnection_list_registered, 1);
704
+ }