diff options
| author | Michael Albinus | 2007-12-04 21:29:40 +0000 |
|---|---|---|
| committer | Michael Albinus | 2007-12-04 21:29:40 +0000 |
| commit | 39abdd4a8a738492cc7d28c252895a868dc6c168 (patch) | |
| tree | cbd03de63818effdf4da4a158c8982c374b598cb /src | |
| parent | 5363d8eaa64bf0e7a8dc0dc960fd3cf9436dc5a9 (diff) | |
| download | emacs-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')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/dbusbind.c | 202 |
2 files changed, 105 insertions, 108 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 2e6cb471321..2f46ea446e4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2007-12-04 Michael Albinus <michael.albinus@gmx.de> | ||
| 2 | |||
| 3 | * dbusbind.c (QCdbus_system_bus, QCdbus_session_bus): Renamed from | ||
| 4 | Qdbus_system_bus and Qdbus_session_bus, respectively. | ||
| 5 | (Vdbus_intern_symbols): Removed. | ||
| 6 | (Vdbus_registered_functions_table): New hash table. | ||
| 7 | (XD_SYMBOL_INTERN_SYMBOL): Removed. | ||
| 8 | (xd_read_message, Fdbus_register_signal, Fdbus_unregister_signal): | ||
| 9 | Rewritten in order to manage registered functions by hash table | ||
| 10 | Vdbus_registered_functions_table. | ||
| 11 | |||
| 1 | 2007-12-03 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> | 12 | 2007-12-03 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> |
| 2 | 13 | ||
| 3 | * xterm.c: Update URL to Window Manager Specification in comment. | 14 | * xterm.c: Update URL to Window Manager Specification in comment. |
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; | |||
| 40 | Lisp_Object Qdbus_error; | 40 | Lisp_Object Qdbus_error; |
| 41 | 41 | ||
| 42 | /* Lisp symbols of the system and session buses. */ | 42 | /* Lisp symbols of the system and session buses. */ |
| 43 | Lisp_Object Qdbus_system_bus, Qdbus_session_bus; | 43 | Lisp_Object QCdbus_system_bus, QCdbus_session_bus; |
| 44 | 44 | ||
| 45 | /* Obarray which keeps interned symbols. */ | 45 | /* Hash table which keeps function definitions. */ |
| 46 | Lisp_Object Vdbus_intern_symbols; | 46 | Lisp_Object Vdbus_registered_functions_table; |
| 47 | 47 | ||
| 48 | /* Whether to debug D-Bus. */ | 48 | /* Whether to debug D-Bus. */ |
| 49 | Lisp_Object Vdbus_debug; | 49 | Lisp_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 | |||
| 577 | xd_read_message (bus) | 542 | xd_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) | |||
| 655 | void | 635 | void |
| 656 | xd_read_queued_messages () | 636 | xd_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 | ||
| 662 | DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal, | 642 | DEFUN ("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 | ||
| 666 | BUS is either the symbol `:system' or the symbol `:session'. | 646 | BUS is either the symbol `:system' or the symbol `:session'. |
| 667 | 647 | ||
| 668 | SERVICE is the D-Bus service name to be used. PATH is the D-Bus | 648 | SERVICE is the D-Bus service name used by the sending D-Bus object. |
| 669 | object path SERVICE is registered. INTERFACE is an interface offered | 649 | It can be either a known name or the unique name of the D-Bus object |
| 670 | by SERVICE. It must provide SIGNAL. | 650 | sending the signal. When SERVICE is nil, related signals from all |
| 651 | D-Bus objects shall be accepted. | ||
| 671 | 652 | ||
| 672 | HANDLER is a Lisp function to be called when the signal is received. | 653 | PATH is the D-Bus object path SERVICE is registered. It can also be |
| 673 | It must accept as arguments the values SIGNAL is sending. | 654 | nil if the path name of incoming signals shall not be checked. |
| 674 | 655 | ||
| 675 | Example: | 656 | INTERFACE is an interface offered by SERVICE. It must provide SIGNAL. |
| 657 | HANDLER is a Lisp function to be called when the signal is received. | ||
| 658 | It must accept as arguments the values SIGNAL is sending. INTERFACE, | ||
| 659 | SIGNAL 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 | ||
| 749 | DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal, Sdbus_unregister_signal, | 725 | DEFUN ("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. |
| 787 | The key in the hash table is the list (BUS INTERFACE MEMBER). BUS is | ||
| 788 | either the symbol `:system' or the symbol `:session'. INTERFACE is a | ||
| 789 | string which denotes a D-Bus interface, and MEMBER, also a string, is | ||
| 790 | either a method or a signal INTERFACE is offering. | ||
| 808 | 791 | ||
| 809 | Vdbus_intern_symbols = Fmake_vector (make_number (64), 0); | 792 | The value in the hash table a the function to be called when a D-Bus |
| 810 | staticpro (&Vdbus_intern_symbols); | 793 | message, 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 |