dbus 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }