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,