Mercurial > emacs
comparison src/dbusbind.c @ 87175:30175fd3b679
* dbusbind.c (xd_read_message): Generate an event for every
registered handler. There might be several handlers registered
for the same signal.
(Fdbus_register_signal): Don't overwrite a registration for the
same signal. Add a new registration if handlers are different.
(Vdbus_registered_functions_table): Rework doc string.
author | Michael Albinus <michael.albinus@gmx.de> |
---|---|
date | Sat, 08 Dec 2007 12:53:37 +0000 |
parents | e0ab56e63db8 |
children | e0d7140e5b0e |
comparison
equal
deleted
inserted
replaced
87174:b042a563846d | 87175:30175fd3b679 |
---|---|
541 symbol, either :system or :session. */ | 541 symbol, either :system or :session. */ |
542 Lisp_Object | 542 Lisp_Object |
543 xd_read_message (bus) | 543 xd_read_message (bus) |
544 Lisp_Object bus; | 544 Lisp_Object bus; |
545 { | 545 { |
546 Lisp_Object key; | 546 Lisp_Object args, key, value; |
547 struct gcpro gcpro1; | 547 struct gcpro gcpro1; |
548 static struct input_event event; | 548 static struct input_event event; |
549 DBusConnection *connection; | 549 DBusConnection *connection; |
550 DBusMessage *dmessage; | 550 DBusMessage *dmessage; |
551 DBusMessageIter iter; | 551 DBusMessageIter iter; |
552 uint dtype; | 552 uint dtype; |
553 char service[DBUS_MAXIMUM_NAME_LENGTH]; | 553 char uname[DBUS_MAXIMUM_NAME_LENGTH]; |
554 char path[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; /* Unlimited in D-Bus spec. */ | 554 char path[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; /* Unlimited in D-Bus spec. */ |
555 char interface[DBUS_MAXIMUM_NAME_LENGTH]; | 555 char interface[DBUS_MAXIMUM_NAME_LENGTH]; |
556 char member[DBUS_MAXIMUM_NAME_LENGTH]; | 556 char member[DBUS_MAXIMUM_NAME_LENGTH]; |
557 | 557 |
558 /* Open a connection to the bus. */ | 558 /* Open a connection to the bus. */ |
564 | 564 |
565 /* Return if there is no queued message. */ | 565 /* Return if there is no queued message. */ |
566 if (dmessage == NULL) | 566 if (dmessage == NULL) |
567 return; | 567 return; |
568 | 568 |
569 /* There is a message in the queue. Construct the D-Bus event. */ | |
570 XD_DEBUG_MESSAGE ("Event received"); | 569 XD_DEBUG_MESSAGE ("Event received"); |
571 EVENT_INIT (event); | |
572 | |
573 event.kind = DBUS_EVENT; | |
574 event.frame_or_window = Qnil; | |
575 | 570 |
576 /* Collect the parameters. */ | 571 /* Collect the parameters. */ |
577 event.arg = Qnil; | 572 args = Qnil; |
578 GCPRO1 (event.arg); | 573 GCPRO1 (args); |
579 | 574 |
580 if (!dbus_message_iter_init (dmessage, &iter)) | 575 if (!dbus_message_iter_init (dmessage, &iter)) |
581 { | 576 { |
582 UNGCPRO; | 577 UNGCPRO; |
583 XD_DEBUG_MESSAGE ("Cannot read event"); | 578 XD_DEBUG_MESSAGE ("Cannot read event"); |
585 } | 580 } |
586 | 581 |
587 /* Loop over the resulting parameters. Construct a list. */ | 582 /* Loop over the resulting parameters. Construct a list. */ |
588 while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) | 583 while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) |
589 { | 584 { |
590 event.arg = Fcons (xd_retrieve_arg (dtype, &iter), event.arg); | 585 args = Fcons (xd_retrieve_arg (dtype, &iter), args); |
591 dbus_message_iter_next (&iter); | 586 dbus_message_iter_next (&iter); |
592 } | 587 } |
593 | 588 |
594 /* The arguments are stored in reverse order. Reorder them. */ | 589 /* The arguments are stored in reverse order. Reorder them. */ |
595 event.arg = Fnreverse (event.arg); | 590 args = Fnreverse (args); |
596 | 591 |
597 /* Read service, object path, interface and member from the message. | 592 /* Read unique name, object path, interface and member from the |
598 The service is always the unique name of the sending object. */ | 593 message. */ |
599 strcpy (service, dbus_message_get_sender (dmessage)); | 594 strcpy (uname, dbus_message_get_sender (dmessage)); |
600 strcpy (path, dbus_message_get_path (dmessage)); | 595 strcpy (path, dbus_message_get_path (dmessage)); |
601 strcpy (interface, dbus_message_get_interface (dmessage)); | 596 strcpy (interface, dbus_message_get_interface (dmessage)); |
602 strcpy (member, dbus_message_get_member (dmessage)); | 597 strcpy (member, dbus_message_get_member (dmessage)); |
603 | 598 |
604 /* Add the registered function of the message. */ | 599 /* Search for a registered function of the message. */ |
605 key = list5 (bus, | 600 key = list3 (bus, build_string (interface), build_string (member)); |
606 (service == NULL ? Qnil : build_string (service)), | 601 value = Fgethash (key, Vdbus_registered_functions_table, Qnil); |
607 (path == NULL ? Qnil : build_string (path)), | 602 |
608 (interface == NULL ? Qnil : build_string (interface)), | 603 /* Loop over the registered functions. Construct an event. */ |
609 (member == NULL ? Qnil : build_string (member))); | 604 while (!NILP (value)) |
610 event.arg = Fcons (Fgethash (key, Vdbus_registered_functions_table, Qnil), | 605 { |
611 event.arg); | 606 key = XCAR (value); |
612 | 607 /* key has the structure (SERVICE UNAME PATH HANDLER). */ |
613 /* Add service, path, interface and member to the event. */ | 608 if (((uname == NULL) || (NILP (XCAR (XCDR (key)))) || |
614 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)), | 609 (strcmp (uname, SDATA (XCAR (XCDR (key)))) == 0)) && |
615 event.arg); | 610 ((path == NULL) || (NILP (XCAR (XCDR (XCDR (key))))) || |
616 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)), | 611 (strcmp (path, SDATA (XCAR (XCDR (XCDR (key))))) == 0)) && |
617 event.arg); | 612 (!NILP (XCAR (XCDR (XCDR (XCDR (key))))))) |
618 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)), | 613 { |
619 event.arg); | 614 EVENT_INIT (event); |
620 event.arg = Fcons ((service == NULL ? Qnil : build_string (service)), | 615 event.kind = DBUS_EVENT; |
621 event.arg); | 616 event.frame_or_window = Qnil; |
622 | 617 event.arg = Fcons (XCAR (XCDR (XCDR (XCDR (key)))), args); |
623 /* Add the bus symbol to the event. */ | 618 |
624 event.arg = Fcons (bus, event.arg); | 619 /* Add uname, path, interface and member to the event. */ |
625 | 620 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)), |
626 /* Store it into the input event queue. */ | 621 event.arg); |
627 kbd_buffer_store_event (&event); | 622 event.arg = Fcons ((interface == NULL |
623 ? Qnil : build_string (interface)), | |
624 event.arg); | |
625 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)), | |
626 event.arg); | |
627 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)), | |
628 event.arg); | |
629 | |
630 /* Add the bus symbol to the event. */ | |
631 event.arg = Fcons (bus, event.arg); | |
632 | |
633 /* Store it into the input event queue. */ | |
634 kbd_buffer_store_event (&event); | |
635 } | |
636 value = XCDR (value); | |
637 } | |
628 | 638 |
629 /* Cleanup. */ | 639 /* Cleanup. */ |
630 dbus_message_unref (dmessage); | 640 dbus_message_unref (dmessage); |
631 UNGCPRO; | 641 UNGCPRO; |
632 } | 642 } |
681 `dbus-register-signal' returns an object, which can be used in | 691 `dbus-register-signal' returns an object, which can be used in |
682 `dbus-unregister-signal' for removing the registration. */) | 692 `dbus-unregister-signal' for removing the registration. */) |
683 (bus, service, path, interface, signal, handler) | 693 (bus, service, path, interface, signal, handler) |
684 Lisp_Object bus, service, path, interface, signal, handler; | 694 Lisp_Object bus, service, path, interface, signal, handler; |
685 { | 695 { |
686 Lisp_Object unique_name, key; | 696 Lisp_Object unique_name, key, value; |
687 DBusConnection *connection; | 697 DBusConnection *connection; |
688 char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; | 698 char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; |
689 DBusError derror; | 699 DBusError derror; |
690 | 700 |
691 /* Check parameters. */ | 701 /* Check parameters. */ |
699 /* Retrieve unique name of service. If service is a known name, we | 709 /* Retrieve unique name of service. If service is a known name, we |
700 will register for the corresponding unique name, if any. Signals | 710 will register for the corresponding unique name, if any. Signals |
701 are sent always with the unique name as sender. Note: the unique | 711 are sent always with the unique name as sender. Note: the unique |
702 name of "org.freedesktop.DBus" is that string itself. */ | 712 name of "org.freedesktop.DBus" is that string itself. */ |
703 if ((!NILP (service)) && | 713 if ((!NILP (service)) && |
714 (strlen (SDATA (service)) > 0) && | |
704 (strcmp (SDATA (service), DBUS_SERVICE_DBUS) != 0) && | 715 (strcmp (SDATA (service), DBUS_SERVICE_DBUS) != 0) && |
705 (strncmp (SDATA (service), ":", 1) != 0)) | 716 (strncmp (SDATA (service), ":", 1) != 0)) |
706 unique_name = call2 (intern ("dbus-get-name-owner"), bus, service); | 717 unique_name = call2 (intern ("dbus-get-name-owner"), bus, service); |
707 else | 718 else |
708 unique_name = service; | 719 unique_name = service; |
730 XD_ERROR (derror); | 741 XD_ERROR (derror); |
731 | 742 |
732 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule); | 743 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule); |
733 | 744 |
734 /* Create a hash table entry. */ | 745 /* Create a hash table entry. */ |
735 key = list5 (bus, unique_name, path, interface, signal); | 746 key = list3 (bus, interface, signal); |
736 Fputhash (key, handler, Vdbus_registered_functions_table); | 747 value = Fgethash (key, Vdbus_registered_functions_table, Qnil); |
737 XD_DEBUG_MESSAGE ("\"%s\" registered with handler \"%s\"", | 748 |
738 SDATA (format2 ("%s", key, Qnil)), | 749 if (NILP (Fmember (list4 (service, unique_name, path, handler), value))) |
739 SDATA (format2 ("%s", handler, Qnil))); | 750 Fputhash (key, |
751 Fcons (list4 (service, unique_name, path, handler), value), | |
752 Vdbus_registered_functions_table); | |
740 | 753 |
741 /* Return key. */ | 754 /* Return key. */ |
742 return key; | 755 return key; |
743 } | 756 } |
744 | 757 |
758 /* The current implementation removes ALL registered functions for a | |
759 given signal. Shouldn't be a problem in general, but there might | |
760 be cases it is not desired. Maybe we can refine the | |
761 implementation. */ | |
745 DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal, Sdbus_unregister_signal, | 762 DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal, Sdbus_unregister_signal, |
746 1, 1, 0, | 763 1, 1, 0, |
747 doc: /* Unregister OBJECT from the D-Bus. | 764 doc: /* Unregister OBJECT from the D-Bus. |
748 OBJECT must be the result of a preceding `dbus-register-signal' call. */) | 765 OBJECT must be the result of a preceding `dbus-register-signal' call. */) |
749 (object) | 766 (object) |
795 QCdbus_session_bus = intern (":session"); | 812 QCdbus_session_bus = intern (":session"); |
796 staticpro (&QCdbus_session_bus); | 813 staticpro (&QCdbus_session_bus); |
797 | 814 |
798 DEFVAR_LISP ("dbus-registered-functions-table", &Vdbus_registered_functions_table, | 815 DEFVAR_LISP ("dbus-registered-functions-table", &Vdbus_registered_functions_table, |
799 doc: /* Hash table of registered functions for D-Bus. | 816 doc: /* Hash table of registered functions for D-Bus. |
800 The key in the hash table is the list (BUS SERVICE PATH MEMBER INTERFACE). | 817 The key in the hash table is the list (BUS MEMBER INTERFACE). BUS is |
801 BUS is either the symbol `:system' or the symbol `:session'. SERVICE | 818 either the symbol `:system' or the symbol `:session'. INTERFACE is a |
802 and PATH are the unique name and the object path of the sending object. | 819 string which denotes a D-Bus interface, and MEMBER, also a string, is |
803 INTERFACE is a string which denotes a D-Bus interface, and MEMBER, | 820 either a method or a signal INTERFACE is offering. All arguments but |
804 also a string, is either a method or a signal INTERFACE is offering. | 821 BUS must not be nil. |
805 All arguments but BUS can be nil, which means a wild card then. | 822 |
806 | 823 The value in the hash table is a list of triple lists |
807 The value in the hash table a the function to be called when a D-Bus | 824 \((SERVICE UNAME PATH HANDLER) (SERVICE UNAME PATH HANDLER) ...). |
808 message, which matches the key criteria, arrives. */); | 825 SERVICE is the service name as registered, UNAME is the corresponding |
826 unique name. PATH is the object path of the sending object. All of | |
827 them be nil, which means a wildcard then. HANDLER is the function to | |
828 be called when a D-Bus message, which matches the key criteria, | |
829 arrives. */); | |
809 /* We initialize Vdbus_registered_functions_table in dbus.el, | 830 /* We initialize Vdbus_registered_functions_table in dbus.el, |
810 because we need to define a hash table function first. */ | 831 because we need to define a hash table function first. */ |
811 Vdbus_registered_functions_table = Qnil; | 832 Vdbus_registered_functions_table = Qnil; |
812 | 833 |
813 DEFVAR_LISP ("dbus-debug", &Vdbus_debug, | 834 DEFVAR_LISP ("dbus-debug", &Vdbus_debug, |