-DEFUN ("dbus-register-service", Fdbus_register_service, Sdbus_register_service,
- 2, MANY, 0,
- doc: /* Register known name SERVICE on the D-Bus BUS.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-SERVICE is the D-Bus service name that should be registered. It must
-be a known name.
-
-FLAGS are keywords, which control how the service name is registered.
-The following keywords are recognized:
-
-`:allow-replacement': Allow another service to become the primary
-owner if requested.
-
-`:replace-existing': Request to replace the current primary owner.
-
-`:do-not-queue': If we can not become the primary owner do not place
-us in the queue.
-
-The function returns a keyword, indicating the result of the
-operation. One of the following keywords is returned:
-
-`:primary-owner': Service has become the primary owner of the
-requested name.
-
-`:in-queue': Service could not become the primary owner and has been
-placed in the queue.
-
-`:exists': Service is already in the queue.
-
-`:already-owner': Service is already the primary owner.
-
-Example:
-
-\(dbus-register-service :session dbus-service-emacs)
-
- => :primary-owner.
-
-\(dbus-register-service
- :session "org.freedesktop.TextEditor"
- dbus-service-allow-replacement dbus-service-replace-existing)
-
- => :already-owner.
-
-usage: (dbus-register-service BUS SERVICE &rest FLAGS) */)
- (ptrdiff_t nargs, Lisp_Object *args)
-{
- Lisp_Object bus, service;
- DBusConnection *connection;
- ptrdiff_t i;
- unsigned int value;
- unsigned int flags = 0;
- int result;
- DBusError derror;
-
- bus = args[0];
- service = args[1];
-
- /* Check parameters. */
- CHECK_STRING (service);
-
- /* Process flags. */
- for (i = 2; i < nargs; ++i) {
- value = ((EQ (args[i], QCdbus_request_name_replace_existing))
- ? DBUS_NAME_FLAG_REPLACE_EXISTING
- : (EQ (args[i], QCdbus_request_name_allow_replacement))
- ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT
- : (EQ (args[i], QCdbus_request_name_do_not_queue))
- ? DBUS_NAME_FLAG_DO_NOT_QUEUE
- : -1);
- if (value == -1)
- XD_SIGNAL2 (build_string ("Unrecognized name request flag"), args[i]);
- flags |= value;
- }
-
- /* Open a connection to the bus. */
- connection = xd_initialize (bus, TRUE);
-
- /* Request the known name from the bus. */
- dbus_error_init (&derror);
- result = dbus_bus_request_name (connection, SSDATA (service), flags,
- &derror);
- if (dbus_error_is_set (&derror))
- XD_ERROR (derror);
-
- /* Cleanup. */
- dbus_error_free (&derror);
-
- /* Return object. */
- switch (result)
- {
- case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
- return QCdbus_request_name_reply_primary_owner;
- case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
- return QCdbus_request_name_reply_in_queue;
- case DBUS_REQUEST_NAME_REPLY_EXISTS:
- return QCdbus_request_name_reply_exists;
- case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
- return QCdbus_request_name_reply_already_owner;
- default:
- /* This should not happen. */
- XD_SIGNAL2 (build_string ("Could not register service"), service);
- }
-}
-
-DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
- 6, MANY, 0,
- doc: /* Register for signal SIGNAL on the D-Bus BUS.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-SERVICE is the D-Bus service name used by the sending D-Bus object.
-It can be either a known name or the unique name of the D-Bus object
-sending the signal. When SERVICE is nil, related signals from all
-D-Bus objects shall be accepted.
-
-PATH is the D-Bus object path SERVICE is registered. It can also be
-nil if the path name of incoming signals shall not be checked.
-
-INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
-HANDLER is a Lisp function to be called when the signal is received.
-It must accept as arguments the values SIGNAL is sending.
-
-All other arguments ARGS, if specified, must be strings. They stand
-for the respective arguments of the signal in their order, and are
-used for filtering as well. A nil argument might be used to preserve
-the order.
-
-INTERFACE, SIGNAL and HANDLER must not be nil. Example:
-
-\(defun my-signal-handler (device)
- (message "Device %s added" device))
-
-\(dbus-register-signal
- :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
- "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
-
- => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
- ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
-
-`dbus-register-signal' returns an object, which can be used in
-`dbus-unregister-object' for removing the registration.
-
-usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARGS) */)
- (ptrdiff_t nargs, Lisp_Object *args)
-{
- Lisp_Object bus, service, path, interface, signal, handler;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
- Lisp_Object uname, key, key1, value;
- DBusConnection *connection;
- ptrdiff_t i;
- char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
- int rulelen;
- DBusError derror;
-
- /* Check parameters. */
- bus = args[0];
- service = args[1];
- path = args[2];
- interface = args[3];
- signal = args[4];
- handler = args[5];
-
- if (!NILP (service)) CHECK_STRING (service);
- if (!NILP (path)) CHECK_STRING (path);
- CHECK_STRING (interface);
- CHECK_STRING (signal);
- if (!FUNCTIONP (handler))
- wrong_type_argument (Qinvalid_function, handler);
- GCPRO6 (bus, service, path, interface, signal, handler);
-
- /* Retrieve unique name of service. If service is a known name, we
- will register for the corresponding unique name, if any. Signals
- are sent always with the unique name as sender. Note: the unique
- name of "org.freedesktop.DBus" is that string itself. */
- if ((STRINGP (service))
- && (SBYTES (service) > 0)
- && (strcmp (SSDATA (service), DBUS_SERVICE_DBUS) != 0)
- && (strncmp (SSDATA (service), ":", 1) != 0))
- uname = call2 (intern ("dbus-get-name-owner"), bus, service);
- else
- uname = service;
-
- /* Create a matching rule if the unique name exists (when no
- wildcard). */
- if (NILP (uname) || (SBYTES (uname) > 0))
- {
- /* Open a connection to the bus. */
- connection = xd_initialize (bus, TRUE);
-
- /* Create a rule to receive related signals. */
- rulelen = snprintf (rule, sizeof rule,
- "type='signal',interface='%s',member='%s'",
- SDATA (interface),
- SDATA (signal));
- if (! (0 <= rulelen && rulelen < sizeof rule))
- string_overflow ();
-
- /* Add unique name and path to the rule if they are non-nil. */
- if (!NILP (uname))
- {
- int len = snprintf (rule + rulelen, sizeof rule - rulelen,
- ",sender='%s'", SDATA (uname));
- if (! (0 <= len && len < sizeof rule - rulelen))
- string_overflow ();
- rulelen += len;
- }
-
- if (!NILP (path))
- {
- int len = snprintf (rule + rulelen, sizeof rule - rulelen,
- ",path='%s'", SDATA (path));
- if (! (0 <= len && len < sizeof rule - rulelen))
- string_overflow ();
- rulelen += len;
- }
-
- /* Add arguments to the rule if they are non-nil. */
- for (i = 6; i < nargs; ++i)
- if (!NILP (args[i]))
- {
- int len;
- CHECK_STRING (args[i]);
- len = snprintf (rule + rulelen, sizeof rule - rulelen,
- ",arg%"pD"d='%s'", i - 6, SDATA (args[i]));
- if (! (0 <= len && len < sizeof rule - rulelen))
- string_overflow ();
- rulelen += len;
- }
-
- /* Add the rule to the bus. */
- dbus_error_init (&derror);
- dbus_bus_add_match (connection, rule, &derror);
- if (dbus_error_is_set (&derror))
- {
- UNGCPRO;
- XD_ERROR (derror);
- }
-
- /* Cleanup. */
- dbus_error_free (&derror);
-
- XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
- }
-
- /* Create a hash table entry. */
- key = list3 (bus, interface, signal);
- key1 = list5 (uname, service, path, handler, build_string (rule));
- value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
-
- if (NILP (Fmember (key1, value)))
- Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
-
- /* Return object. */
- RETURN_UNGCPRO (list2 (key, list3 (service, path, handler)));
-}
-
-DEFUN ("dbus-register-method", Fdbus_register_method, Sdbus_register_method,
- 6, 7, 0,
- doc: /* Register for method METHOD on the D-Bus BUS.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-SERVICE is the D-Bus service name of the D-Bus object METHOD is
-registered for. It must be a known name (See discussion of
-DONT-REGISTER-SERVICE below).
-
-PATH is the D-Bus object path SERVICE is registered (See discussion of
-DONT-REGISTER-SERVICE below). INTERFACE is the interface offered by
-SERVICE. It must provide METHOD. HANDLER is a Lisp function to be
-called when a method call is received. It must accept the input
-arguments of METHOD. The return value of HANDLER is used for
-composing the returning D-Bus message.
-
-When DONT-REGISTER-SERVICE is non-nil, the known name SERVICE is not
-registered. This means that other D-Bus clients have no way of
-noticing the newly registered method. When interfaces are constructed
-incrementally by adding single methods or properties at a time,
-DONT-REGISTER-SERVICE can be used to prevent other clients from
-discovering the still incomplete interface.*/)
- (Lisp_Object bus, Lisp_Object service, Lisp_Object path,
- Lisp_Object interface, Lisp_Object method, Lisp_Object handler,
- Lisp_Object dont_register_service)
-{
- Lisp_Object key, key1, value;
- Lisp_Object args[2] = { bus, service };
-
- /* Check parameters. */
- CHECK_STRING (service);
- CHECK_STRING (path);
- CHECK_STRING (interface);
- CHECK_STRING (method);
- if (!FUNCTIONP (handler))
- wrong_type_argument (Qinvalid_function, handler);
- /* TODO: We must check for a valid service name, otherwise there is
- a segmentation fault. */
-
- /* Request the name. */
- if (NILP (dont_register_service))
- Fdbus_register_service (2, args);
-
- /* Create a hash table entry. We use nil for the unique name,
- because the method might be called from anybody. */
- key = list3 (bus, interface, method);
- key1 = list4 (Qnil, service, path, handler);
- value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
-
- if (NILP (Fmember (key1, value)))
- Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
-
- /* Return object. */
- return list2 (key, list3 (service, path, handler));
-}
-