1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains code that interface with a2jmidid through D-Bus
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <dbus/dbus.h>
31 #include "a2j_proxy.hpp"
32 #include "Patchage.hpp"
33 #include "globals.hpp"
34 #include "dbus_helpers.h"
36 #define A2J_SERVICE "org.gna.home.a2jmidid"
37 #define A2J_OBJECT "/"
38 #define A2J_IFACE_CONTROL "org.gna.home.a2jmidid.control"
43 const std::string
& msg
)
45 g_app
->error_msg((std::string
)"[A2J] " + msg
);
51 const std::string
& msg
)
53 g_app
->info_msg((std::string
)"[A2J] " + msg
);
64 DBusConnection
* connection
,
65 DBusMessage
* message
,
70 bool response_expected
,
73 DBusMessage
** reply_ptr_ptr
,
79 std::string
& jack_client_name_ref
);
84 bool _server_responding
;
85 std::string _jack_client_name
;
88 a2j_proxy::a2j_proxy()
90 _impl_ptr
= new a2j_proxy_impl
;
94 a2j_proxy::~a2j_proxy()
100 a2j_proxy::get_jack_client_name()
102 return _impl_ptr
->_jack_client_name
.c_str();
106 a2j_proxy_impl::init()
110 _server_responding
= false;
112 patchage_dbus_add_match("type='signal',interface='" DBUS_INTERFACE_DBUS
"',member=NameOwnerChanged,arg0='" A2J_SERVICE
"'");
113 patchage_dbus_add_match("type='signal',interface='" A2J_IFACE_CONTROL
"',member=bridge_started");
114 patchage_dbus_add_match("type='signal',interface='" A2J_IFACE_CONTROL
"',member=bridge_stopped");
116 patchage_dbus_add_filter(dbus_message_hook
, this);
118 // get jack client name
119 // calling any method to updates server responding status
120 // this also actiavtes a2j object if it not activated already
121 get_jack_client_name(_jack_client_name
);
125 status
= A2J_STATUS_BRIDGE_STARTED
;
129 if (!_server_responding
)
131 status
= A2J_STATUS_NO_RESPONSE
;
135 status
= A2J_STATUS_BRIDGE_STOPPED
;
139 g_app
->set_a2j_status(status
);
143 a2j_proxy_impl::dbus_message_hook(
144 DBusConnection
* connection
,
145 DBusMessage
* message
,
148 const char * object_name
;
149 const char * old_owner
;
150 const char * new_owner
;
153 //a2j_proxy_impl * me = reinterpret_cast<a2j_proxy_impl *>(proxy);
155 //info_msg("dbus_message_hook() called.");
157 // Handle signals we have subscribed for in attach()
159 if (dbus_message_is_signal(message
, DBUS_INTERFACE_DBUS
, "NameOwnerChanged"))
161 if (!dbus_message_get_args(
162 message
, &g_dbus_error
,
163 DBUS_TYPE_STRING
, &object_name
,
164 DBUS_TYPE_STRING
, &old_owner
,
165 DBUS_TYPE_STRING
, &new_owner
,
168 error_msg(str(boost::format("dbus_message_get_args() failed to extract NameOwnerChanged signal arguments (%s)") % g_dbus_error
.message
));
169 dbus_error_free(&g_dbus_error
);
170 return DBUS_HANDLER_RESULT_HANDLED
;
173 if ((std::string
)object_name
!= A2J_SERVICE
)
175 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
178 if (old_owner
[0] == '\0')
180 info_msg((std::string
)"A2J activated.");
181 g_app
->set_a2j_status(A2J_STATUS_BRIDGE_STOPPED
);
183 else if (new_owner
[0] == '\0')
185 info_msg((std::string
)"A2J deactivated.");
186 g_app
->set_a2j_status(A2J_STATUS_NO_RESPONSE
);
189 return DBUS_HANDLER_RESULT_HANDLED
;
192 if (dbus_message_is_signal(message
, A2J_IFACE_CONTROL
, "bridge_started"))
194 info_msg("bridge started.");
195 g_app
->set_a2j_status(A2J_STATUS_BRIDGE_STARTED
);
197 return DBUS_HANDLER_RESULT_HANDLED
;
200 if (dbus_message_is_signal(message
, A2J_IFACE_CONTROL
, "bridge_stopped"))
202 info_msg("bridge stopped.");
203 g_app
->set_a2j_status(A2J_STATUS_BRIDGE_STOPPED
);
205 return DBUS_HANDLER_RESULT_HANDLED
;
208 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
212 a2j_proxy_impl::call(
213 bool response_expected
,
216 DBusMessage
** reply_ptr_ptr
,
222 va_start(ap
, in_type
);
224 _server_responding
= patchage_dbus_call_valist(
236 return _server_responding
;
240 a2j_proxy_impl::get_jack_client_name(
241 std::string
& jack_client_name_ref
)
243 DBusMessage
* reply_ptr
;
244 const char * jack_client_name
;
246 if (!call(true, A2J_IFACE_CONTROL
, "get_jack_client_name", &reply_ptr
, DBUS_TYPE_INVALID
))
251 if (!dbus_message_get_args(reply_ptr
, &g_dbus_error
, DBUS_TYPE_STRING
, &jack_client_name
, DBUS_TYPE_INVALID
))
253 dbus_message_unref(reply_ptr
);
254 dbus_error_free(&g_dbus_error
);
255 error_msg("decoding reply of get_jack_client_name failed.");
259 jack_client_name_ref
= jack_client_name
;
261 dbus_message_unref(reply_ptr
);
267 a2j_proxy::map_jack_port(
268 const char * jack_port_name
,
269 std::string
& alsa_client_name_ref
,
270 std::string
& alsa_port_name_ref
,
271 uint32_t& alsa_client_id_ref
)
273 DBusMessage
* reply_ptr
;
274 dbus_uint32_t alsa_client_id
;
275 dbus_uint32_t alsa_port_id
;
276 const char * alsa_client_name
;
277 const char * alsa_port_name
;
279 if (!_impl_ptr
->call(
282 "map_jack_port_to_alsa",
291 if (!dbus_message_get_args(
304 dbus_message_unref(reply_ptr
);
305 dbus_error_free(&g_dbus_error
);
306 error_msg("decoding reply of map_jack_port_to_alsa failed.");
310 alsa_client_name_ref
= alsa_client_name
;
311 alsa_port_name_ref
= alsa_port_name
;
312 alsa_client_id_ref
= alsa_client_id
;
314 dbus_message_unref(reply_ptr
);
320 a2j_proxy_impl::is_started()
322 DBusMessage
* reply_ptr
;
325 if (!call(true, A2J_IFACE_CONTROL
, "is_started", &reply_ptr
, DBUS_TYPE_INVALID
))
330 if (!dbus_message_get_args(reply_ptr
, &g_dbus_error
, DBUS_TYPE_BOOLEAN
, &started
, DBUS_TYPE_INVALID
))
332 dbus_message_unref(reply_ptr
);
333 dbus_error_free(&g_dbus_error
);
334 error_msg("decoding reply of is_started failed.");
338 dbus_message_unref(reply_ptr
);
344 a2j_proxy::start_bridge()
346 DBusMessage
* reply_ptr
;
348 if (!_impl_ptr
->call(true, A2J_IFACE_CONTROL
, "start", &reply_ptr
, DBUS_TYPE_INVALID
))
353 dbus_message_unref(reply_ptr
);
357 a2j_proxy::stop_bridge()
359 DBusMessage
* reply_ptr
;
361 if (!_impl_ptr
->call(true, A2J_IFACE_CONTROL
, "stop", &reply_ptr
, DBUS_TYPE_INVALID
))
366 dbus_message_unref(reply_ptr
);