switch from bld.new_task_gen() to bld()
[jack2.git] / dbus / jackdbus.c
bloba03c8e3c2b0cd82f5f27cef8b71fa706d5696938
1 /* -*- Mode: C ; c-basic-offset: 4 -*- */
2 /*
3 Copyright (C) 2007,2008,2010 Nedko Arnaudov
4 Copyright (C) 2007-2008 Juuso Alasuutari
5 Copyright (C) 2008 Marc-Olivier Barre
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #if defined(HAVE_CONFIG_H)
23 #include "config.h"
24 #endif
26 #include <stdbool.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/stat.h>
32 #include <signal.h>
33 #include <dbus/dbus.h>
34 #include <pthread.h>
35 #include <unistd.h>
37 #include "config.h"
39 #include "jackdbus.h"
40 #include "controller.h"
41 #include "jack/jack.h"
42 #include "jack/jslist.h"
43 #include "jack/control.h"
44 #include "sigsegv.h"
45 #include "svnversion.h"
47 static char * g_log_filename;
48 static ino_t g_log_file_ino;
49 FILE *g_logfile;
50 char *g_jackdbus_config_dir;
51 size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */
52 char *g_jackdbus_log_dir;
53 size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */
54 int g_exit_command;
55 DBusConnection *g_connection;
57 void
58 jack_dbus_send_signal(
59 const char *sender_object_path,
60 const char *iface,
61 const char *signal_name,
62 int first_arg_type,
63 ...)
65 DBusMessage *message_ptr;
66 va_list ap;
68 va_start(ap, first_arg_type);
70 message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name);
71 if (message_ptr == NULL)
73 jack_error("dbus_message_new_signal() failed.");
74 goto exit;
77 if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap))
79 jack_error("dbus_message_append_args_valist() failed.");
80 goto unref;
83 /* Add message to outgoing message queue */
84 if (!dbus_connection_send(g_connection, message_ptr, NULL))
86 jack_error("dbus_connection_send() failed.");
87 goto unref;
90 unref:
91 dbus_message_unref(message_ptr);
93 exit:
94 va_end(ap);
98 * Send a method return.
100 * If call->reply is NULL (i.e. a message construct method failed
101 * due to lack of memory) attempt to send a void method return.
103 static
104 void
105 jack_dbus_send_method_return(
106 struct jack_dbus_method_call * call)
108 if (call->message == NULL)
110 /* async call */
111 return;
114 if (call->reply)
116 retry_send:
117 if (!dbus_connection_send (call->connection, call->reply, NULL))
119 jack_error ("Ran out of memory trying to queue method return");
122 dbus_connection_flush (call->connection);
123 dbus_message_unref (call->reply);
124 call->reply = NULL;
126 else
128 jack_error ("send_method_return() called with a NULL message,"
129 " trying to construct a void return...");
131 if ((call->reply = dbus_message_new_method_return (call->message)))
133 goto retry_send;
135 else
137 jack_error ("Failed to construct method return!");
142 #define object_ptr ((struct jack_dbus_object_descriptor *)data)
145 * The D-Bus message handler for object path /org/jackaudio/Controller.
147 DBusHandlerResult
148 jack_dbus_message_handler(
149 DBusConnection *connection,
150 DBusMessage *message,
151 void *data)
153 struct jack_dbus_method_call call;
154 const char *interface_name;
155 struct jack_dbus_interface_descriptor ** interface_ptr_ptr;
157 /* Check if the message is a method call. If not, ignore it. */
158 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
160 goto handled;
163 /* Get the invoked method's name and make sure it's non-NULL. */
164 if (!(call.method_name = dbus_message_get_member (message)))
166 jack_dbus_error(
167 &call,
168 JACK_DBUS_ERROR_UNKNOWN_METHOD,
169 "Received method call with empty method name");
170 goto send_return;
173 /* Initialize our data. */
174 call.context = object_ptr->context;
175 call.connection = connection;
176 call.message = message;
177 call.reply = NULL;
179 /* Check if there's an interface specified for this method call. */
180 interface_name = dbus_message_get_interface (message);
181 if (interface_name != NULL)
183 /* Check if we can match the interface and method.
184 * The inteface handler functions only return false if the
185 * method name was unknown, otherwise they run the specified
186 * method and return TRUE.
189 interface_ptr_ptr = object_ptr->interfaces;
191 while (*interface_ptr_ptr != NULL)
193 if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0)
195 if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
197 break;
200 goto send_return;
203 interface_ptr_ptr++;
206 else
208 /* No interface was specified so we have to try them all. This is
209 * dictated by the D-Bus specification which states that method calls
210 * omitting the interface must never be rejected.
213 interface_ptr_ptr = object_ptr->interfaces;
215 while (*interface_ptr_ptr != NULL)
217 if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
219 goto send_return;
222 interface_ptr_ptr++;
226 jack_dbus_error(
227 &call,
228 JACK_DBUS_ERROR_UNKNOWN_METHOD,
229 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
230 call.method_name,
231 dbus_message_get_signature(message),
232 interface_name);
234 send_return:
235 jack_dbus_send_method_return(&call);
237 handled:
238 return DBUS_HANDLER_RESULT_HANDLED;
241 void
242 jack_dbus_message_handler_unregister(
243 DBusConnection *connection,
244 void *data)
246 jack_info ("Message handler was unregistered");
249 #undef object_ptr
252 * Check if the supplied method name exists in org.jackaudio.JackConfigure,
253 * if it does execute it and return TRUE. Otherwise return FALSE.
255 bool
256 jack_dbus_run_method(
257 struct jack_dbus_method_call *call,
258 const struct jack_dbus_interface_method_descriptor * methods)
260 const struct jack_dbus_interface_method_descriptor * method_ptr;
262 method_ptr = methods;
264 while (method_ptr->name != NULL)
266 if (strcmp(call->method_name, method_ptr->name) == 0)
268 method_ptr->handler(call);
269 return TRUE;
272 method_ptr++;
275 return FALSE;
279 * Read arguments from a method call.
280 * If the operation fails construct an error and return false,
281 * otherwise return true.
283 bool
284 jack_dbus_get_method_args(
285 struct jack_dbus_method_call *call,
286 int type,
287 ...)
289 va_list args;
290 DBusError error;
291 bool retval = true;
293 va_start (args, type);
294 dbus_error_init (&error);
296 if (!dbus_message_get_args_valist (call->message, &error, type, args))
298 jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
299 "Invalid arguments to method \"%s\"",
300 call->method_name);
301 retval = false;
304 dbus_error_free (&error);
305 va_end (args);
307 return retval;
311 * Read a string and a variant argument from a method call.
312 * If the operation fails construct an error and return false,
313 * otherwise return true.
315 bool
316 jack_dbus_get_method_args_string_and_variant(
317 struct jack_dbus_method_call *call,
318 const char **arg1,
319 message_arg_t *arg2,
320 int *type_ptr)
322 DBusMessageIter iter, sub_iter;
324 /* First we want a string... */
325 if (dbus_message_iter_init (call->message, &iter)
326 && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
328 dbus_message_iter_get_basic (&iter, arg1);
329 dbus_message_iter_next (&iter);
331 /* ...and then a variant. */
332 if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT)
334 dbus_message_iter_recurse (&iter, &sub_iter);
335 dbus_message_iter_get_basic (&sub_iter, arg2);
336 *type_ptr = dbus_message_iter_get_arg_type (&sub_iter);
338 /* Got what we wanted. */
339 return true;
343 jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
344 "Invalid arguments to method \"%s\"",
345 call->method_name);
347 return false;
351 * Read two strings and a variant argument from a method call.
352 * If the operation fails construct an error and return false,
353 * otherwise return true.
355 bool
356 jack_dbus_get_method_args_two_strings_and_variant(
357 struct jack_dbus_method_call *call,
358 const char **arg1,
359 const char **arg2,
360 message_arg_t *arg3,
361 int *type_ptr)
363 DBusMessageIter iter, sub_iter;
365 /* First we want a string... */
366 if (dbus_message_iter_init (call->message, &iter)
367 && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
369 dbus_message_iter_get_basic (&iter, arg1);
370 dbus_message_iter_next (&iter);
372 /* ...and then a second string. */
373 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
375 return false;
378 /* Got what we wanted. */
379 dbus_message_iter_get_basic (&iter, arg2);
380 dbus_message_iter_next (&iter);
382 /* ...and then a variant. */
383 if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT)
385 dbus_message_iter_recurse (&iter, &sub_iter);
386 dbus_message_iter_get_basic (&sub_iter, arg3);
387 *type_ptr = dbus_message_iter_get_arg_type (&sub_iter);
389 /* Got what we wanted. */
390 return true;
394 jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
395 "Invalid arguments to method \"%s\"",
396 call->method_name);
398 return false;
402 * Append a variant type to a D-Bus message.
403 * Return false if something fails, true otherwise.
405 bool
406 jack_dbus_message_append_variant(
407 DBusMessageIter *iter,
408 int type,
409 const char *signature,
410 message_arg_t *arg)
412 DBusMessageIter sub_iter;
414 /* Open a variant container. */
415 if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter))
417 goto fail;
420 /* Append the supplied value. */
421 if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg))
423 dbus_message_iter_close_container (iter, &sub_iter);
424 goto fail;
427 /* Close the container. */
428 if (!dbus_message_iter_close_container (iter, &sub_iter))
430 goto fail;
433 return true;
435 fail:
436 return false;
440 * Construct an empty method return message.
442 * The operation can only fail due to lack of memory, in which case
443 * there's no sense in trying to construct an error return. Instead,
444 * call->reply will be set to NULL and handled in send_method_return().
446 void
447 jack_dbus_construct_method_return_empty(
448 struct jack_dbus_method_call * call)
450 call->reply = dbus_message_new_method_return (call->message);
452 if (call->reply == NULL)
454 jack_error ("Ran out of memory trying to construct method return");
459 * Construct a method return which holds a single argument or, if
460 * the type parameter is DBUS_TYPE_INVALID, no arguments at all
461 * (a void message).
463 * The operation can only fail due to lack of memory, in which case
464 * there's no sense in trying to construct an error return. Instead,
465 * call->reply will be set to NULL and handled in send_method_return().
467 void
468 jack_dbus_construct_method_return_single(
469 struct jack_dbus_method_call *call,
470 int type,
471 message_arg_t arg)
473 DBusMessageIter iter;
474 call->reply = dbus_message_new_method_return (call->message);
476 if (call->reply == NULL)
478 goto fail_no_mem;
481 /* Void method return requested by caller. */
482 if (type == DBUS_TYPE_INVALID)
484 return;
487 /* Prevent crash on NULL input string. */
488 else if (type == DBUS_TYPE_STRING && arg.string == NULL)
490 arg.string = "";
493 dbus_message_iter_init_append (call->reply, &iter);
495 if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg))
497 dbus_message_unref (call->reply);
498 call->reply = NULL;
499 goto fail_no_mem;
502 return;
504 fail_no_mem:
505 jack_error ("Ran out of memory trying to construct method return");
509 * Construct a method return which holds an array of strings.
511 * The operation can only fail due to lack of memory, in which case
512 * there's no sense in trying to construct an error return. Instead,
513 * call->reply will be set to NULL and handled in send_method_return().
515 void
516 jack_dbus_construct_method_return_array_of_strings(
517 struct jack_dbus_method_call *call,
518 unsigned int num_members,
519 const char **array)
521 DBusMessageIter iter, sub_iter;
522 unsigned int i;
524 call->reply = dbus_message_new_method_return (call->message);
525 if (!call->reply)
527 goto fail;
530 dbus_message_iter_init_append (call->reply, &iter);
532 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
534 goto fail_unref;
537 for (i = 0; i < num_members; ++i)
539 if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i]))
541 dbus_message_iter_close_container (&iter, &sub_iter);
542 goto fail_unref;
546 if (!dbus_message_iter_close_container (&iter, &sub_iter))
548 goto fail_unref;
551 return;
553 fail_unref:
554 dbus_message_unref (call->reply);
555 call->reply = NULL;
557 fail:
558 jack_error ("Ran out of memory trying to construct method return");
561 static bool jack_dbus_log_open(void)
563 struct stat st;
564 int ret;
565 int retry;
567 if (g_logfile != NULL)
569 ret = stat(g_log_filename, &st);
570 if (ret != 0 || g_log_file_ino != st.st_ino)
572 fclose(g_logfile);
574 else
576 return true;
580 for (retry = 0; retry < 10; retry++)
582 g_logfile = fopen(g_log_filename, "a");
583 if (g_logfile == NULL)
585 fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", g_log_filename, errno, strerror(errno));
586 return false;
589 ret = stat(g_log_filename, &st);
590 if (ret == 0)
592 g_log_file_ino = st.st_ino;
593 return true;
596 fclose(g_logfile);
597 g_logfile = NULL;
600 fprintf(stderr, "Cannot stat just opened jackdbus log file \"%s\": %d (%s). %d retries\n", g_log_filename, errno, strerror(errno), retry);
601 return false;
604 void
605 jack_dbus_info_callback(const char *msg)
607 time_t timestamp;
608 char timestamp_str[26];
610 time(&timestamp);
611 ctime_r(&timestamp, timestamp_str);
612 timestamp_str[24] = 0;
614 if (jack_dbus_log_open())
616 fprintf(g_logfile, "%s: %s\n", timestamp_str, msg);
617 fflush(g_logfile);
621 #define ANSI_BOLD_ON "\033[1m"
622 #define ANSI_BOLD_OFF "\033[22m"
623 #define ANSI_COLOR_RED "\033[31m"
624 #define ANSI_RESET "\033[0m"
626 void
627 jack_dbus_error_callback(const char *msg)
629 time_t timestamp;
630 char timestamp_str[26];
632 time(&timestamp);
633 ctime_r(&timestamp, timestamp_str);
634 timestamp_str[24] = 0;
636 if (jack_dbus_log_open())
638 fprintf(g_logfile, "%s: " ANSI_BOLD_ON ANSI_COLOR_RED "ERROR: %s" ANSI_RESET "\n", timestamp_str, msg);
639 fflush(g_logfile);
643 bool
644 ensure_dir_exist(const char *dirname, int mode)
646 struct stat st;
647 if (stat(dirname, &st) != 0)
649 if (errno == ENOENT)
651 printf("Directory \"%s\" does not exist. Creating...\n", dirname);
652 if (mkdir(dirname, mode) != 0)
654 fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno));
655 return false;
658 else
660 fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno));
661 return false;
664 else
666 if (!S_ISDIR(st.st_mode))
668 fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname);
669 return false;
672 return true;
675 char *
676 pathname_cat(const char *pathname_a, const char *pathname_b)
678 char *pathname;
679 int pathname_a_len, pathname_b_len, pathname_len;
680 pathname_a_len = strlen(pathname_a);
681 pathname_b_len = strlen(pathname_b);
682 pathname = malloc(pathname_a_len + pathname_b_len + 1);
683 if (pathname == NULL)
685 fprintf(stderr, "Out of memory\n");
686 return NULL;
688 memcpy(pathname, pathname_a, pathname_a_len);
689 memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len);
690 pathname_len = pathname_a_len + pathname_b_len;
691 pathname[pathname_len] = 0;
692 return pathname;
695 bool
696 paths_init()
698 const char *home_dir, *xdg_config_home, *xdg_log_home;
700 home_dir = getenv("HOME");
701 if (home_dir == NULL)
703 fprintf(stderr, "Environment variable HOME not set\n");
704 goto fail;
707 xdg_config_home = getenv("XDG_CONFIG_HOME");
708 if (xdg_config_home == NULL)
710 if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail;
713 if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail;
715 if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail;
716 if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail;
718 if (!ensure_dir_exist(xdg_config_home, 0700))
720 goto fail;
723 if (!ensure_dir_exist(xdg_log_home, 0700))
725 goto fail;
728 if (!ensure_dir_exist(g_jackdbus_config_dir, 0700))
730 free(g_jackdbus_config_dir);
731 goto fail;
733 g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir);
735 if (!ensure_dir_exist(g_jackdbus_log_dir, 0700))
737 free(g_jackdbus_log_dir);
738 goto fail;
740 g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir);
742 return true;
744 fail:
745 return false;
748 void
749 paths_uninit()
751 free(g_jackdbus_config_dir);
752 free(g_jackdbus_log_dir);
755 static bool log_init(void)
757 size_t log_len;
759 log_len = strlen(JACKDBUS_LOG);
761 g_log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1);
762 if (g_log_filename == NULL)
764 fprintf(stderr, "Out of memory\n");
765 return false;
768 memcpy(g_log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len);
769 memcpy(g_log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len);
770 g_log_filename[g_jackdbus_log_dir_len + log_len] = 0;
772 if (!jack_dbus_log_open())
774 return false;
777 return true;
780 static void log_uninit(void)
782 if (g_logfile != NULL)
784 fclose(g_logfile);
787 free(g_log_filename);
790 void
791 jack_dbus_error(
792 void *dbus_call_context_ptr,
793 const char *error_name,
794 const char *format,
795 ...)
797 va_list ap;
798 char buffer[300];
800 va_start(ap, format);
802 vsnprintf(buffer, sizeof(buffer), format, ap);
804 jack_error_callback(buffer);
805 if (dbus_call_context_ptr != NULL)
807 if (((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply != NULL)
809 dbus_message_unref(((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply);
810 ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = NULL;
813 ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error(
814 ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message,
815 error_name,
816 buffer);
819 va_end(ap);
822 void
823 jack_dbus_only_error(
824 void *dbus_call_context_ptr,
825 const char *error_name,
826 const char *format,
827 ...)
829 va_list ap;
830 char buffer[300];
832 va_start(ap, format);
834 vsnprintf(buffer, sizeof(buffer), format, ap);
836 if (((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply != NULL)
838 dbus_message_unref(((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply);
839 ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = NULL;
842 ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error(
843 ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message,
844 error_name,
845 buffer);
847 va_end(ap);
851 main (int argc, char **argv)
853 DBusError error;
854 int ret;
855 void *controller_ptr;
856 struct stat st;
857 char timestamp_str[26];
859 st.st_mtime = 0;
860 stat(argv[0], &st);
861 ctime_r(&st.st_mtime, timestamp_str);
862 timestamp_str[24] = 0;
864 if (!jack_controller_settings_init())
866 ret = 1;
867 goto fail;
870 if (argc != 2 || strcmp(argv[1], "auto") != 0)
872 ret = 0;
873 fprintf(
874 stderr,
875 "jackdbus should be auto-executed by D-Bus message bus daemon.\n"
876 "If you want to run it manually anyway, specify \"auto\" as only parameter\n");
877 goto fail_uninit_xml;
880 if (!paths_init())
882 ret = 1;
883 goto fail_uninit_xml;
886 if (!log_init())
888 ret = 1;
889 goto fail_uninit_paths;
892 #if !defined(DISABLE_SIGNAL_MAGIC)
893 jackctl_setup_signals(0);
894 #endif
896 jack_set_error_function(jack_dbus_error_callback);
897 jack_set_info_function(jack_dbus_info_callback);
899 /* setup our SIGSEGV magic that prints nice stack in our logfile */
900 setup_sigsegv();
902 jack_info("------------------");
903 jack_info("Controller activated. Version %s (%s) built on %s", jack_get_version_string(), SVN_VERSION, timestamp_str);
905 if (!dbus_threads_init_default())
907 jack_error("dbus_threads_init_default() failed");
908 ret = 1;
909 goto fail_uninit_log;
912 dbus_error_init (&error);
913 g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
914 if (dbus_error_is_set (&error))
916 jack_error("Cannot connect to D-Bus session bus: %s", error.message);
917 ret = 1;
918 goto fail_uninit_log;
921 ret = dbus_bus_request_name(
922 g_connection,
923 "org.jackaudio.service",
924 DBUS_NAME_FLAG_DO_NOT_QUEUE,
925 &error);
926 if (ret == -1)
928 jack_error("Cannot request service name: %s", error.message);
929 dbus_error_free(&error);
930 ret = 1;
931 goto fail_unref_connection;
933 else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
935 jack_error("Requested D-Bus service name already exists");
936 ret = 1;
937 goto fail_unref_connection;
940 controller_ptr = jack_controller_create(g_connection);
942 if (controller_ptr == NULL)
944 ret = 1;
945 goto fail_unref_connection;
948 jack_info("Listening for D-Bus messages");
950 g_exit_command = FALSE;
951 while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200))
953 jack_controller_run(controller_ptr);
956 jack_controller_destroy(controller_ptr);
958 jack_info("Controller deactivated.");
960 ret = 0;
962 fail_unref_connection:
963 dbus_connection_unref(g_connection);
965 fail_uninit_log:
966 log_uninit();
968 fail_uninit_paths:
969 paths_uninit();
971 fail_uninit_xml:
972 jack_controller_settings_uninit();
974 fail:
975 return ret;