aboutsummaryrefslogtreecommitdiffstats
path: root/src/dbusbind.c
diff options
context:
space:
mode:
authorMichael Albinus2007-12-04 21:29:40 +0000
committerMichael Albinus2007-12-04 21:29:40 +0000
commit39abdd4a8a738492cc7d28c252895a868dc6c168 (patch)
treecbd03de63818effdf4da4a158c8982c374b598cb /src/dbusbind.c
parent5363d8eaa64bf0e7a8dc0dc960fd3cf9436dc5a9 (diff)
downloademacs-39abdd4a8a738492cc7d28c252895a868dc6c168.tar.gz
emacs-39abdd4a8a738492cc7d28c252895a868dc6c168.zip
* dbusbind.c (QCdbus_system_bus, QCdbus_session_bus): Renamed from
Qdbus_system_bus and Qdbus_session_bus, respectively. (Vdbus_intern_symbols): Removed. (Vdbus_registered_functions_table): New hash table. (XD_SYMBOL_INTERN_SYMBOL): Removed. (xd_read_message, Fdbus_register_signal, Fdbus_unregister_signal): Rewritten in order to manage registered functions by hash table Vdbus_registered_functions_table.
Diffstat (limited to 'src/dbusbind.c')
-rw-r--r--src/dbusbind.c202
1 files changed, 94 insertions, 108 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 311aee550f6..d0b538da29c 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -40,10 +40,10 @@ Lisp_Object Qdbus_unregister_signal;
40Lisp_Object Qdbus_error; 40Lisp_Object Qdbus_error;
41 41
42/* Lisp symbols of the system and session buses. */ 42/* Lisp symbols of the system and session buses. */
43Lisp_Object Qdbus_system_bus, Qdbus_session_bus; 43Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
44 44
45/* Obarray which keeps interned symbols. */ 45/* Hash table which keeps function definitions. */
46Lisp_Object Vdbus_intern_symbols; 46Lisp_Object Vdbus_registered_functions_table;
47 47
48/* Whether to debug D-Bus. */ 48/* Whether to debug D-Bus. */
49Lisp_Object Vdbus_debug; 49Lisp_Object Vdbus_debug;
@@ -52,41 +52,6 @@ Lisp_Object Vdbus_debug;
52/* We use "xd_" and "XD_" as prefix for all internal symbols, because 52/* We use "xd_" and "XD_" as prefix for all internal symbols, because
53 we don't want to poison other namespaces with "dbus_". */ 53 we don't want to poison other namespaces with "dbus_". */
54 54
55/* Create a new interned symbol which represents a function handler.
56 bus is a Lisp symbol, either :system or :session. interface and
57 member are both Lisp strings.
58
59 D-Bus sends messages, which are captured by Emacs in the main loop,
60 converted into an event then. Emacs must identify a message from
61 D-Bus, in order to call the right Lisp function when the event is
62 handled in the event handler function of dbus.el.
63
64 A D-Bus message is determined at least by the D-Bus bus it is
65 raised from (system bus or session bus), the interface and the
66 method the message belongs to. There could be even more properties
67 for determination, but that isn't implemented yet.
68
69 The approach is to create a new interned Lisp symbol once there is
70 a registration request for a given signal, which is a special D-Bus
71 message. The symbol's name is a concatenation of the bus name,
72 interface name and method name of the signal; the function cell is
73 the Lisp function to be called when such a signal arrives. Since
74 this code runs in the main loop, receiving input, it must be
75 performant. */
76#define XD_SYMBOL_INTERN_SYMBOL(symbol, bus, interface, member) \
77 { \
78 XD_DEBUG_VALID_LISP_OBJECT_P (bus); \
79 XD_DEBUG_VALID_LISP_OBJECT_P (interface); \
80 XD_DEBUG_VALID_LISP_OBJECT_P (member); \
81 char s[1024]; \
82 strcpy (s, SDATA (SYMBOL_NAME (bus))); \
83 strcat (s, "."); \
84 strcat (s, SDATA (interface)); \
85 strcat (s, "."); \
86 strcat (s, SDATA (member)); \
87 symbol = Fintern (build_string (s), Vdbus_intern_symbols); \
88 }
89
90/* Raise a Lisp error from a D-Bus error. */ 55/* Raise a Lisp error from a D-Bus error. */
91#define XD_ERROR(error) \ 56#define XD_ERROR(error) \
92 { \ 57 { \
@@ -248,13 +213,13 @@ xd_initialize (bus)
248 213
249 /* Parameter check. */ 214 /* Parameter check. */
250 CHECK_SYMBOL (bus); 215 CHECK_SYMBOL (bus);
251 if (!((EQ (bus, Qdbus_system_bus)) || (EQ (bus, Qdbus_session_bus)))) 216 if (!((EQ (bus, QCdbus_system_bus)) || (EQ (bus, QCdbus_session_bus))))
252 xsignal2 (Qdbus_error, build_string ("Wrong bus name"), bus); 217 xsignal2 (Qdbus_error, build_string ("Wrong bus name"), bus);
253 218
254 /* Open a connection to the bus. */ 219 /* Open a connection to the bus. */
255 dbus_error_init (&derror); 220 dbus_error_init (&derror);
256 221
257 if (EQ (bus, Qdbus_system_bus)) 222 if (EQ (bus, QCdbus_system_bus))
258 connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror); 223 connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
259 else 224 else
260 connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); 225 connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
@@ -577,14 +542,20 @@ void
577xd_read_message (bus) 542xd_read_message (bus)
578 Lisp_Object bus; 543 Lisp_Object bus;
579{ 544{
580 Lisp_Object symbol; 545 Lisp_Object key;
581 struct gcpro gcpro1; 546 struct gcpro gcpro1;
582 static struct input_event event; 547 static struct input_event event;
583 DBusConnection *connection; 548 DBusConnection *connection;
584 DBusMessage *dmessage; 549 DBusMessage *dmessage;
585 DBusMessageIter iter; 550 DBusMessageIter iter;
586 uint dtype; 551 uint dtype;
587 char s1[1024], s2[1024]; 552 char service[1024], path[1024], interface[1024], member[1024];
553
554 /* Vdbus_registered_functions_table will be made as hash table in
555 dbus.el. When it isn't loaded yet, it doesn't make sense to
556 handle D-Bus messages. */
557 if (!HASH_TABLE_P (Vdbus_registered_functions_table))
558 return;
588 559
589 /* Open a connection to the bus. */ 560 /* Open a connection to the bus. */
590 connection = xd_initialize (bus); 561 connection = xd_initialize (bus);
@@ -625,23 +596,32 @@ xd_read_message (bus)
625 /* The arguments are stored in reverse order. Reorder them. */ 596 /* The arguments are stored in reverse order. Reorder them. */
626 event.arg = Fnreverse (event.arg); 597 event.arg = Fnreverse (event.arg);
627 598
628 /* Add the object path of the sender of the message. */ 599 /* Read service, object path interface and member from the
629 strcpy (s1, dbus_message_get_path (dmessage)); 600 message. */
630 event.arg = Fcons ((s1 == NULL ? Qnil : build_string (s1)), event.arg); 601 strcpy (service, dbus_message_get_sender (dmessage));
631 602 strcpy (path, dbus_message_get_path (dmessage));
632 /* Add the unique name of the sender of the message. */ 603 strcpy (interface, dbus_message_get_interface (dmessage));
633 strcpy (s2, dbus_message_get_sender (dmessage)); 604 strcpy (member, dbus_message_get_member (dmessage));
634 event.arg = Fcons ((s2 == NULL ? Qnil : build_string (s2)), event.arg); 605
635 606 /* Add them to the event. */
636 /* Add the interned symbol the message is raised from (signal) or 607 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
637 for (method). */ 608 event.arg);
638 strcpy (s1, dbus_message_get_interface (dmessage)); 609 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
639 strcpy (s2, dbus_message_get_member (dmessage)); 610 event.arg);
640 XD_SYMBOL_INTERN_SYMBOL 611 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
641 (symbol, bus, 612 event.arg);
642 (s1 == NULL ? Qnil : build_string (s1)), 613 event.arg = Fcons ((service == NULL ? Qnil : build_string (service)),
643 (s2 == NULL ? Qnil : build_string (s2))); 614 event.arg);
644 event.arg = Fcons (symbol, event.arg); 615
616 /* Add the bus symbol to the event. */
617 event.arg = Fcons (bus, event.arg);
618
619 /* Add the registered function of the message. */
620 key = list3 (bus,
621 (interface == NULL ? Qnil : build_string (interface)),
622 (member == NULL ? Qnil : build_string (member)));
623 event.arg = Fcons (Fgethash (key, Vdbus_registered_functions_table, Qnil),
624 event.arg);
645 625
646 /* Store it into the input event queue. */ 626 /* Store it into the input event queue. */
647 kbd_buffer_store_event (&event); 627 kbd_buffer_store_event (&event);
@@ -655,8 +635,8 @@ xd_read_message (bus)
655void 635void
656xd_read_queued_messages () 636xd_read_queued_messages ()
657{ 637{
658 xd_read_message (Qdbus_system_bus); 638 xd_read_message (QCdbus_system_bus);
659 xd_read_message (Qdbus_session_bus); 639 xd_read_message (QCdbus_session_bus);
660} 640}
661 641
662DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal, 642DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
@@ -665,85 +645,81 @@ DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
665 645
666BUS is either the symbol `:system' or the symbol `:session'. 646BUS is either the symbol `:system' or the symbol `:session'.
667 647
668SERVICE is the D-Bus service name to be used. PATH is the D-Bus 648SERVICE is the D-Bus service name used by the sending D-Bus object.
669object path SERVICE is registered. INTERFACE is an interface offered 649It can be either a known name or the unique name of the D-Bus object
670by SERVICE. It must provide SIGNAL. 650sending the signal. When SERVICE is nil, related signals from all
651D-Bus objects shall be accepted.
671 652
672HANDLER is a Lisp function to be called when the signal is received. 653PATH is the D-Bus object path SERVICE is registered. It can also be
673It must accept as arguments the values SIGNAL is sending. 654nil if the path name of incoming signals shall not be checked.
674 655
675Example: 656INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
657HANDLER is a Lisp function to be called when the signal is received.
658It must accept as arguments the values SIGNAL is sending. INTERFACE,
659SIGNAL and HANDLER must not be nil. Example:
676 660
677\(defun my-signal-handler (device) 661\(defun my-signal-handler (device)
678 (message "Device %s added" device)) 662 (message "Device %s added" device))
679 663
680\(dbus-register-signal 664\(dbus-register-signal
681 :system "DeviceAdded" "org.freedesktop.Hal" 665 :system "DeviceAdded"
666 (dbus-get-name-owner :system "org.freedesktop.Hal")
682 "/org/freedesktop/Hal/Manager" "org.freedesktop.Hal.Manager" 667 "/org/freedesktop/Hal/Manager" "org.freedesktop.Hal.Manager"
683 'my-signal-handler) 668 'my-signal-handler)
684 669
685 => org.freedesktop.Hal.Manager.DeviceAdded 670 => (:system "org.freedesktop.Hal.Manager" "DeviceAdded")
686 671
687`dbus-register-signal' returns an object, which can be used in 672`dbus-register-signal' returns an object, which can be used in
688`dbus-unregister-signal' for removing the registration. */) 673`dbus-unregister-signal' for removing the registration. */)
689 (bus, signal, service, path, interface, handler) 674 (bus, signal, service, path, interface, handler)
690 Lisp_Object bus, signal, service, path, interface, handler; 675 Lisp_Object bus, signal, service, path, interface, handler;
691{ 676{
692 Lisp_Object name_owner, result; 677 Lisp_Object key;
693 DBusConnection *connection; 678 DBusConnection *connection;
694 DBusError derror;
695 char rule[1024]; 679 char rule[1024];
680 DBusError derror;
696 681
697 /* Check parameters. */ 682 /* Check parameters. */
698 CHECK_SYMBOL (bus); 683 CHECK_SYMBOL (bus);
699 CHECK_STRING (signal); 684 CHECK_STRING (signal);
700 CHECK_STRING (service); 685 if (!NILP (service)) CHECK_STRING (service);
701 CHECK_STRING (path); 686 if (!NILP (path)) CHECK_STRING (path);
702 CHECK_STRING (interface); 687 CHECK_STRING (interface);
703 CHECK_SYMBOL (handler); 688 CHECK_SYMBOL (handler);
704 689
705 /* Open a connection to the bus. */ 690 /* Open a connection to the bus. */
706 connection = xd_initialize (bus); 691 connection = xd_initialize (bus);
707 692
708#if 0 693 /* Create a rule to receive related signals. */
709 /* TODO: Get name owner. This is the sending service name. */
710 name_owner = call2 (intern ("dbus-get-name-owner"), bus, service);
711#endif
712
713 /* Add a rule to the bus in order to receive related signals. */
714 dbus_error_init (&derror);
715 sprintf (rule, 694 sprintf (rule,
716 "type='signal',interface='%s',member=%s%", 695 "type='signal',interface='%s',member=%s%",
717 SDATA (interface), 696 SDATA (interface),
718 SDATA (signal)); 697 SDATA (signal));
719#if 0
720 /* TODO: We need better checks when we want use sender and path. */
721 sprintf (rule,
722 "type='signal',sender='%s',path='%s',interface='%s',member=%s%",
723 SDATA (name_owner),
724 SDATA (path),
725 SDATA (interface),
726 SDATA (signal));
727#endif
728 dbus_bus_add_match (connection, rule, &derror);
729 698
699 /* Add service and path to the rule if they are non-nil. */
700 if (!NILP (service))
701 sprintf (rule, "%s,sender='%s'%", rule, SDATA (service));
702
703 if (!NILP (path))
704 sprintf (rule, "%s,path='%s'", rule, SDATA (path));
705
706 /* Add the rule to the bus. */
707 dbus_error_init (&derror);
708 dbus_bus_add_match (connection, rule, &derror);
730 if (dbus_error_is_set (&derror)) 709 if (dbus_error_is_set (&derror))
731 XD_ERROR (derror); 710 XD_ERROR (derror);
732 711
733 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule); 712 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
734 713
735 /* Create a new protected symbol, which has the complete name of the 714 /* Create a hash table entry. */
736 signal. The function cell is taken from the handler. */ 715 key = list3 (bus, interface, signal);
737 result = Qnil; 716 Fputhash (key, handler, Vdbus_registered_functions_table);
738
739 XD_SYMBOL_INTERN_SYMBOL (result, bus, interface, signal);
740 Ffset (result, Fsymbol_function (handler));
741 XD_DEBUG_MESSAGE ("\"%s\" registered with handler \"%s\"", 717 XD_DEBUG_MESSAGE ("\"%s\" registered with handler \"%s\"",
742 SDATA (format2 ("%s", result, Qnil)), 718 SDATA (format2 ("%s", key, Qnil)),
743 SDATA (format2 ("%s", Fsymbol_function (result), Qnil))); 719 SDATA (format2 ("%s", handler, Qnil)));
744 720
745 /* Return. */ 721 /* Return key. */
746 return result; 722 return key;
747} 723}
748 724
749DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal, Sdbus_unregister_signal, 725DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal, Sdbus_unregister_signal,
@@ -762,7 +738,7 @@ OBJECT must be the result of a preceding `dbus-register-signal' call. */)
762 SDATA (format2 ("%s", Fsymbol_function (object), Qnil))); 738 SDATA (format2 ("%s", Fsymbol_function (object), Qnil)));
763 739
764 /* Unintern the signal symbol. */ 740 /* Unintern the signal symbol. */
765 Funintern (object, Vdbus_intern_symbols); 741 Fremhash (object, Vdbus_registered_functions_table);
766 742
767 /* Return. */ 743 /* Return. */
768 return Qnil; 744 return Qnil;
@@ -800,17 +776,27 @@ syms_of_dbusbind ()
800 Fput (Qdbus_error, Qerror_message, 776 Fput (Qdbus_error, Qerror_message,
801 build_string ("D-Bus error")); 777 build_string ("D-Bus error"));
802 778
803 Qdbus_system_bus = intern (":system"); 779 QCdbus_system_bus = intern (":system");
804 staticpro (&Qdbus_system_bus); 780 staticpro (&QCdbus_system_bus);
781
782 QCdbus_session_bus = intern (":session");
783 staticpro (&QCdbus_session_bus);
805 784
806 Qdbus_session_bus = intern (":session"); 785 DEFVAR_LISP ("dbus-registered-functions-table", &Vdbus_registered_functions_table,
807 staticpro (&Qdbus_session_bus); 786 doc: /* Hash table of registered functions for D-Bus.
787The key in the hash table is the list (BUS INTERFACE MEMBER). BUS is
788either the symbol `:system' or the symbol `:session'. INTERFACE is a
789string which denotes a D-Bus interface, and MEMBER, also a string, is
790either a method or a signal INTERFACE is offering.
808 791
809 Vdbus_intern_symbols = Fmake_vector (make_number (64), 0); 792The value in the hash table a the function to be called when a D-Bus
810 staticpro (&Vdbus_intern_symbols); 793message, which matches the key criteria, arrives. */);
794 /* We initialize Vdbus_registered_functions_table in dbus.el,
795 because we need to define a hash table function first. */
796 Vdbus_registered_functions_table = Qnil;
811 797
812 DEFVAR_LISP ("dbus-debug", &Vdbus_debug, 798 DEFVAR_LISP ("dbus-debug", &Vdbus_debug,
813 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */); 799 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
814#ifdef DBUS_DEBUG 800#ifdef DBUS_DEBUG
815 Vdbus_debug = Qt; 801 Vdbus_debug = Qt;
816#else 802#else