1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * ALSA SEQ < - > JACK MIDI bridge
5 * Copyright (c) 2007,2008 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2007-2008 Juuso Alasuutari
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <dbus/dbus.h>
29 #include "dbus_internal.h"
30 #include "dbus_iface_control.h"
34 void *dbus_call_context_ptr
,
35 const char *error_name
,
44 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
46 a2j_error("%s", buffer
);
47 if (dbus_call_context_ptr
!= NULL
)
49 ((struct a2j_dbus_method_call
*)dbus_call_context_ptr
)->reply
= dbus_message_new_error(
50 ((struct a2j_dbus_method_call
*)dbus_call_context_ptr
)->message
,
59 * Send a method return.
61 * If call->reply is NULL (i.e. a message construct method failed
62 * due to lack of memory) attempt to send a void method return.
66 a2j_dbus_send_method_return(
67 struct a2j_dbus_method_call
* call
)
69 if (call
->reply
== NULL
)
71 a2j_debug("send_method_return() called with a NULL message, trying to construct a void return...");
73 call
->reply
= dbus_message_new_method_return(call
->message
);
74 if (call
->reply
== NULL
)
76 a2j_error("Failed to construct method return!");
81 if (!dbus_connection_send(call
->connection
, call
->reply
, NULL
))
83 a2j_error("Ran out of memory trying to queue method return");
86 dbus_connection_flush(call
->connection
);
87 dbus_message_unref(call
->reply
);
92 * Construct a method return which holds a single argument or, if
93 * the type parameter is DBUS_TYPE_INVALID, no arguments at all
96 * The operation can only fail due to lack of memory, in which case
97 * there's no sense in trying to construct an error return. Instead,
98 * call->reply will be set to NULL and handled in send_method_return().
101 a2j_dbus_construct_method_return_single(
102 struct a2j_dbus_method_call
* call_ptr
,
106 DBusMessageIter iter
;
108 call_ptr
->reply
= dbus_message_new_method_return(call_ptr
->message
);
109 if (call_ptr
->reply
== NULL
)
114 dbus_message_iter_init_append(call_ptr
->reply
, &iter
);
116 if (!dbus_message_iter_append_basic(&iter
, type
, arg
))
118 dbus_message_unref(call_ptr
->reply
);
119 call_ptr
->reply
= NULL
;
126 a2j_error("Ran out of memory trying to construct method return");
129 #define descriptor_ptr ((struct a2j_dbus_object_descriptor *)data)
132 a2j_dbus_message_handler(
133 DBusConnection
* connection
,
134 DBusMessage
* message
,
137 struct a2j_dbus_method_call call
;
138 const char *interface_name
;
139 struct a2j_dbus_interface_descriptor
** interface_ptr_ptr
;
141 /* Check if the message is a method call. If not, ignore it. */
142 if (dbus_message_get_type (message
) != DBUS_MESSAGE_TYPE_METHOD_CALL
)
147 /* Get the invoked method's name and make sure it's non-NULL. */
148 if (!(call
.method_name
= dbus_message_get_member (message
)))
152 A2J_DBUS_ERROR_UNKNOWN_METHOD
,
153 "Received method call with empty method name");
157 /* Initialize our data. */
158 call
.context
= descriptor_ptr
->context
;
159 call
.connection
= connection
;
160 call
.message
= message
;
163 /* Check if there's an interface specified for this method call. */
164 interface_name
= dbus_message_get_interface (message
);
165 if (interface_name
!= NULL
)
167 /* Check if we can match the interface and method.
168 * The inteface handler functions only return false if the
169 * method name was unknown, otherwise they run the specified
170 * method and return TRUE.
173 interface_ptr_ptr
= descriptor_ptr
->interfaces
;
175 while (*interface_ptr_ptr
!= NULL
)
177 if (strcmp(interface_name
, (*interface_ptr_ptr
)->name
) == 0)
179 if (!(*interface_ptr_ptr
)->handler(&call
, (*interface_ptr_ptr
)->methods
))
192 /* No interface was specified so we have to try them all. This is
193 * dictated by the D-Bus specification which states that method calls
194 * omitting the interface must never be rejected.
197 interface_ptr_ptr
= descriptor_ptr
->interfaces
;
199 while (*interface_ptr_ptr
!= NULL
)
201 if ((*interface_ptr_ptr
)->handler(&call
, (*interface_ptr_ptr
)->methods
))
212 A2J_DBUS_ERROR_UNKNOWN_METHOD
,
213 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
215 dbus_message_get_signature(message
),
219 a2j_dbus_send_method_return(&call
);
222 return DBUS_HANDLER_RESULT_HANDLED
;
226 a2j_dbus_message_handler_unregister(
227 DBusConnection
*connection
,
230 a2j_debug("Message handler was unregistered");
233 #undef descriptor_ptr
236 * Check if the supplied method name exists in method descriptor,
237 * if it does execute it and return TRUE. Otherwise return FALSE.
241 struct a2j_dbus_method_call
*call
,
242 const struct a2j_dbus_interface_method_descriptor
* methods
)
244 const struct a2j_dbus_interface_method_descriptor
* method_ptr
;
246 method_ptr
= methods
;
248 while (method_ptr
->name
!= NULL
)
250 if (strcmp(call
->method_name
, method_ptr
->name
) == 0)
252 method_ptr
->handler(call
);
262 static DBusConnection
* g_dbus_connection_ptr
;
263 static struct a2j_dbus_object_descriptor g_a2j_dbus_object_descriptor
;
264 struct a2j_dbus_interface_descriptor
* g_a2j_dbus_interfaces
[] =
266 &g_a2j_iface_introspectable
,
267 &g_a2j_iface_control
,
272 a2j_dbus_is_available()
274 return g_dbus_connection_ptr
!= NULL
;
280 DBusError dbus_error
;
282 DBusObjectPathVTable vtable
=
284 a2j_dbus_message_handler_unregister
,
285 a2j_dbus_message_handler
,
289 dbus_error_init(&dbus_error
);
290 g_dbus_connection_ptr
= dbus_bus_get(DBUS_BUS_SESSION
, &dbus_error
);
291 if (dbus_error_is_set(&dbus_error
))
293 a2j_error("Failed to get bus: %s", dbus_error
.message
);
297 dbus_connection_set_exit_on_disconnect(g_dbus_connection_ptr
, FALSE
);
299 a2j_debug("D-Bus unique name is '%s'", dbus_bus_get_unique_name(g_dbus_connection_ptr
));
301 ret
= dbus_bus_request_name(g_dbus_connection_ptr
, A2J_DBUS_SERVICE_NAME
, DBUS_NAME_FLAG_DO_NOT_QUEUE
, &dbus_error
);
304 a2j_error("Failed to acquire bus name: %s", dbus_error
.message
);
305 goto fail_unref_dbus_connection
;
308 if (ret
== DBUS_REQUEST_NAME_REPLY_EXISTS
)
310 a2j_error("Requested bus name already exists");
311 goto fail_unref_dbus_connection
;
314 g_a2j_dbus_object_descriptor
.context
= NULL
;
315 g_a2j_dbus_object_descriptor
.interfaces
= g_a2j_dbus_interfaces
;
317 if (!dbus_connection_register_object_path(
318 g_dbus_connection_ptr
,
319 A2J_DBUS_OBJECT_PATH
,
321 &g_a2j_dbus_object_descriptor
))
323 a2j_error("Ran out of memory trying to register D-Bus object path");
324 goto fail_unref_dbus_connection
;
329 fail_unref_dbus_connection
:
330 dbus_connection_unref(g_dbus_connection_ptr
);
331 g_dbus_connection_ptr
= NULL
;
340 int timeout_milliseconds
)
342 return dbus_connection_read_write_dispatch(g_dbus_connection_ptr
, timeout_milliseconds
);
348 dbus_connection_unref(g_dbus_connection_ptr
);
349 g_dbus_connection_ptr
= NULL
;
355 const char * interface
,
361 DBusMessage
* message_ptr
;
363 a2j_debug("Sending signal %s.%s from %s", interface
, name
, path
);
365 if (!a2j_dbus_is_available())
367 a2j_error("Internal error: cannot send D-Bus signal without D-Bus being initialized");
371 message_ptr
= dbus_message_new_signal (path
, interface
, name
);
373 if (message_ptr
== NULL
)
375 a2j_error("Ran out of memory trying to create new signal");
380 if (dbus_message_append_args_valist(message_ptr
, type
, ap
))
382 if (!dbus_connection_send(g_dbus_connection_ptr
, message_ptr
, NULL
))
384 a2j_error("Ran out of memory trying to queue signal");
387 dbus_connection_flush(g_dbus_connection_ptr
);
391 a2j_error("Ran out of memory trying to append signal argument(s)");
395 dbus_message_unref(message_ptr
);