jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3253 lines
78KB

  1. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  2. /*
  3. Copyright (C) 2007,2008 Nedko Arnaudov
  4. Copyright (C) 2007-2008 Juuso Alasuutari
  5. Copyright (C) 2008 Marc-Olivier Barre
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include <stdbool.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <sys/stat.h>
  23. #include <signal.h>
  24. #include <dbus/dbus.h>
  25. #include <pthread.h>
  26. #include <unistd.h>
  27. #include "config.h"
  28. #include "jackdbus.h"
  29. #include "controller.h"
  30. #include "jack/jack.h"
  31. #include "jack/jslist.h"
  32. #include "jack/control.h"
  33. FILE *g_logfile;
  34. char *g_jackdbus_config_dir;
  35. size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */
  36. char *g_jackdbus_log_dir;
  37. size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */
  38. int g_exit_command;
  39. DBusConnection *g_connection;
  40. void
  41. jack_dbus_send_signal(
  42. const char *sender_object_path,
  43. const char *iface,
  44. const char *signal_name,
  45. int first_arg_type,
  46. ...)
  47. {
  48. DBusMessage *message_ptr;
  49. va_list ap;
  50. va_start(ap, first_arg_type);
  51. message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name);
  52. if (message_ptr == NULL)
  53. {
  54. jack_error("dbus_message_new_signal() failed.");
  55. goto exit;
  56. }
  57. if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap))
  58. {
  59. jack_error("dbus_message_append_args_valist() failed.");
  60. goto unref;
  61. }
  62. /* Add message to outgoing message queue */
  63. if (!dbus_connection_send(g_connection, message_ptr, NULL))
  64. {
  65. jack_error("dbus_connection_send() failed.");
  66. goto unref;
  67. }
  68. unref:
  69. dbus_message_unref(message_ptr);
  70. exit:
  71. va_end(ap);
  72. }
  73. /*
  74. * Send a method return.
  75. *
  76. * If call->reply is NULL (i.e. a message construct method failed
  77. * due to lack of memory) attempt to send a void method return.
  78. */
  79. static
  80. void
  81. jack_dbus_send_method_return(
  82. struct jack_dbus_method_call * call)
  83. {
  84. if (call->reply)
  85. {
  86. retry_send:
  87. if (!dbus_connection_send (call->connection, call->reply, NULL))
  88. {
  89. jack_error ("Ran out of memory trying to queue method return");
  90. }
  91. dbus_connection_flush (call->connection);
  92. dbus_message_unref (call->reply);
  93. call->reply = NULL;
  94. }
  95. else
  96. {
  97. jack_error ("send_method_return() called with a NULL message,"
  98. " trying to construct a void return...");
  99. if ((call->reply = dbus_message_new_method_return (call->message)))
  100. {
  101. goto retry_send;
  102. }
  103. else
  104. {
  105. jack_error ("Failed to construct method return!");
  106. }
  107. }
  108. }
  109. #define object_ptr ((struct jack_dbus_object_descriptor *)data)
  110. /*
  111. * The D-Bus message handler for object path /org/jackaudio/Controller.
  112. */
  113. DBusHandlerResult
  114. jack_dbus_message_handler(
  115. DBusConnection *connection,
  116. DBusMessage *message,
  117. void *data)
  118. {
  119. struct jack_dbus_method_call call;
  120. const char *interface_name;
  121. struct jack_dbus_interface_descriptor ** interface_ptr_ptr;
  122. /* Check if the message is a method call. If not, ignore it. */
  123. if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
  124. {
  125. goto handled;
  126. }
  127. /* Get the invoked method's name and make sure it's non-NULL. */
  128. if (!(call.method_name = dbus_message_get_member (message)))
  129. {
  130. jack_dbus_error(
  131. &call,
  132. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  133. "Received method call with empty method name");
  134. goto send_return;
  135. }
  136. /* Initialize our data. */
  137. call.context = object_ptr->context;
  138. call.connection = connection;
  139. call.message = message;
  140. call.reply = NULL;
  141. /* Check if there's an interface specified for this method call. */
  142. interface_name = dbus_message_get_interface (message);
  143. if (interface_name != NULL)
  144. {
  145. /* Check if we can match the interface and method.
  146. * The inteface handler functions only return false if the
  147. * method name was unknown, otherwise they run the specified
  148. * method and return TRUE.
  149. */
  150. interface_ptr_ptr = object_ptr->interfaces;
  151. while (*interface_ptr_ptr != NULL)
  152. {
  153. if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0)
  154. {
  155. if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  156. {
  157. break;
  158. }
  159. goto send_return;
  160. }
  161. interface_ptr_ptr++;
  162. }
  163. }
  164. else
  165. {
  166. /* No interface was specified so we have to try them all. This is
  167. * dictated by the D-Bus specification which states that method calls
  168. * omitting the interface must never be rejected.
  169. */
  170. interface_ptr_ptr = object_ptr->interfaces;
  171. while (*interface_ptr_ptr != NULL)
  172. {
  173. if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  174. {
  175. goto send_return;
  176. }
  177. interface_ptr_ptr++;
  178. }
  179. }
  180. jack_dbus_error(
  181. &call,
  182. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  183. "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
  184. call.method_name,
  185. dbus_message_get_signature(message),
  186. interface_name);
  187. send_return:
  188. jack_dbus_send_method_return(&call);
  189. handled:
  190. return DBUS_HANDLER_RESULT_HANDLED;
  191. }
  192. void
  193. jack_dbus_message_handler_unregister(
  194. DBusConnection *connection,
  195. void *data)
  196. {
  197. jack_info ("Message handler was unregistered");
  198. }
  199. #undef object_ptr
  200. /*
  201. * Check if the supplied method name exists in org.jackaudio.JackConfigure,
  202. * if it does execute it and return TRUE. Otherwise return FALSE.
  203. */
  204. bool
  205. jack_dbus_run_method(
  206. struct jack_dbus_method_call *call,
  207. const struct jack_dbus_interface_method_descriptor * methods)
  208. {
  209. const struct jack_dbus_interface_method_descriptor * method_ptr;
  210. method_ptr = methods;
  211. while (method_ptr->name != NULL)
  212. {
  213. if (strcmp(call->method_name, method_ptr->name) == 0)
  214. {
  215. method_ptr->handler(call);
  216. return TRUE;
  217. }
  218. method_ptr++;
  219. }
  220. return FALSE;
  221. }
  222. /*
  223. * Read arguments from a method call.
  224. * If the operation fails construct an error and return false,
  225. * otherwise return true.
  226. */
  227. bool
  228. jack_dbus_get_method_args(
  229. struct jack_dbus_method_call *call,
  230. int type,
  231. ...)
  232. {
  233. va_list args;
  234. DBusError error;
  235. bool retval = true;
  236. va_start (args, type);
  237. dbus_error_init (&error);
  238. if (!dbus_message_get_args_valist (call->message, &error, type, args))
  239. {
  240. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  241. "Invalid arguments to method \"%s\"",
  242. call->method_name);
  243. retval = false;
  244. }
  245. dbus_error_free (&error);
  246. va_end (args);
  247. return retval;
  248. }
  249. /*
  250. * Read a string and a variant argument from a method call.
  251. * If the operation fails construct an error and return false,
  252. * otherwise return true.
  253. */
  254. bool
  255. jack_dbus_get_method_args_string_and_variant(
  256. struct jack_dbus_method_call *call,
  257. const char **arg1,
  258. message_arg_t *arg2,
  259. int *type_ptr)
  260. {
  261. DBusMessageIter iter, sub_iter;
  262. /* First we want a string... */
  263. if (dbus_message_iter_init (call->message, &iter)
  264. && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
  265. {
  266. dbus_message_iter_get_basic (&iter, arg1);
  267. dbus_message_iter_next (&iter);
  268. /* ...and then a variant. */
  269. if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT)
  270. {
  271. dbus_message_iter_recurse (&iter, &sub_iter);
  272. dbus_message_iter_get_basic (&sub_iter, arg2);
  273. *type_ptr = dbus_message_iter_get_arg_type (&sub_iter);
  274. /* Got what we wanted. */
  275. return true;
  276. }
  277. }
  278. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  279. "Invalid arguments to method \"%s\"",
  280. call->method_name);
  281. return false;
  282. }
  283. /*
  284. * Append a variant type to a D-Bus message.
  285. * Return false if something fails, true otherwise.
  286. */
  287. bool
  288. jack_dbus_message_append_variant(
  289. DBusMessageIter *iter,
  290. int type,
  291. const char *signature,
  292. message_arg_t *arg)
  293. {
  294. DBusMessageIter sub_iter;
  295. /* Open a variant container. */
  296. if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter))
  297. {
  298. goto fail;
  299. }
  300. /* Append the supplied value. */
  301. if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg))
  302. {
  303. dbus_message_iter_close_container (iter, &sub_iter);
  304. goto fail;
  305. }
  306. /* Close the container. */
  307. if (!dbus_message_iter_close_container (iter, &sub_iter))
  308. {
  309. goto fail;
  310. }
  311. return true;
  312. fail:
  313. return false;
  314. }
  315. /*
  316. * Construct an empty method return message.
  317. *
  318. * The operation can only fail due to lack of memory, in which case
  319. * there's no sense in trying to construct an error return. Instead,
  320. * call->reply will be set to NULL and handled in send_method_return().
  321. */
  322. void
  323. jack_dbus_construct_method_return_empty(
  324. struct jack_dbus_method_call * call)
  325. {
  326. call->reply = dbus_message_new_method_return (call->message);
  327. if (call->reply == NULL)
  328. {
  329. jack_error ("Ran out of memory trying to construct method return");
  330. }
  331. }
  332. /*
  333. * Construct a method return which holds a single argument or, if
  334. * the type parameter is DBUS_TYPE_INVALID, no arguments at all
  335. * (a void message).
  336. *
  337. * The operation can only fail due to lack of memory, in which case
  338. * there's no sense in trying to construct an error return. Instead,
  339. * call->reply will be set to NULL and handled in send_method_return().
  340. */
  341. void
  342. jack_dbus_construct_method_return_single(
  343. struct jack_dbus_method_call *call,
  344. int type,
  345. message_arg_t arg)
  346. {
  347. DBusMessageIter iter;
  348. call->reply = dbus_message_new_method_return (call->message);
  349. if (call->reply == NULL)
  350. {
  351. goto fail_no_mem;
  352. }
  353. /* Void method return requested by caller. */
  354. if (type == DBUS_TYPE_INVALID)
  355. {
  356. return;
  357. }
  358. /* Prevent crash on NULL input string. */
  359. else if (type == DBUS_TYPE_STRING && arg.string == NULL)
  360. {
  361. arg.string = "";
  362. }
  363. dbus_message_iter_init_append (call->reply, &iter);
  364. if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg))
  365. {
  366. dbus_message_unref (call->reply);
  367. call->reply = NULL;
  368. goto fail_no_mem;
  369. }
  370. return;
  371. fail_no_mem:
  372. jack_error ("Ran out of memory trying to construct method return");
  373. }
  374. /*
  375. * Construct a method return which holds an array of strings.
  376. *
  377. * The operation can only fail due to lack of memory, in which case
  378. * there's no sense in trying to construct an error return. Instead,
  379. * call->reply will be set to NULL and handled in send_method_return().
  380. */
  381. void
  382. jack_dbus_construct_method_return_array_of_strings(
  383. struct jack_dbus_method_call *call,
  384. unsigned int num_members,
  385. const char **array)
  386. {
  387. DBusMessageIter iter, sub_iter;
  388. unsigned int i;
  389. call->reply = dbus_message_new_method_return (call->message);
  390. if (!call->reply)
  391. {
  392. goto fail;
  393. }
  394. dbus_message_iter_init_append (call->reply, &iter);
  395. if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
  396. {
  397. goto fail_unref;
  398. }
  399. for (i = 0; i < num_members; ++i)
  400. {
  401. if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i]))
  402. {
  403. dbus_message_iter_close_container (&iter, &sub_iter);
  404. goto fail_unref;
  405. }
  406. }
  407. if (!dbus_message_iter_close_container (&iter, &sub_iter))
  408. {
  409. goto fail_unref;
  410. }
  411. return;
  412. fail_unref:
  413. dbus_message_unref (call->reply);
  414. call->reply = NULL;
  415. fail:
  416. jack_error ("Ran out of memory trying to construct method return");
  417. }
  418. void
  419. jack_dbus_info_callback(const char *msg)
  420. {
  421. time_t timestamp;
  422. char timestamp_str[26];
  423. time(&timestamp);
  424. ctime_r(&timestamp, timestamp_str);
  425. timestamp_str[24] = 0;
  426. fprintf(g_logfile, "%s: %s\n", timestamp_str, msg);
  427. fflush(g_logfile);
  428. }
  429. void
  430. jack_dbus_error_callback(const char *msg)
  431. {
  432. time_t timestamp;
  433. char timestamp_str[26];
  434. time(&timestamp);
  435. ctime_r(&timestamp, timestamp_str);
  436. timestamp_str[24] = 0;
  437. fprintf(g_logfile, "%s: ERROR: %s\n", timestamp_str, msg);
  438. fflush(g_logfile);
  439. }
  440. bool
  441. ensure_dir_exist(const char *dirname, int mode)
  442. {
  443. struct stat st;
  444. if (stat(dirname, &st) != 0)
  445. {
  446. if (errno == ENOENT)
  447. {
  448. printf("Directory \"%s\" does not exist. Creating...\n", dirname);
  449. if (mkdir(dirname, mode) != 0)
  450. {
  451. fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno));
  452. return false;
  453. }
  454. }
  455. else
  456. {
  457. fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno));
  458. return false;
  459. }
  460. }
  461. else
  462. {
  463. if (!S_ISDIR(st.st_mode))
  464. {
  465. fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname);
  466. return false;
  467. }
  468. }
  469. return true;
  470. }
  471. char *
  472. pathname_cat(const char *pathname_a, const char *pathname_b)
  473. {
  474. char *pathname;
  475. int pathname_a_len, pathname_b_len, pathname_len;
  476. pathname_a_len = strlen(pathname_a);
  477. pathname_b_len = strlen(pathname_b);
  478. pathname = malloc(pathname_a_len + pathname_b_len + 1);
  479. if (pathname == NULL)
  480. {
  481. fprintf(stderr, "Out of memory\n");
  482. return NULL;
  483. }
  484. memcpy(pathname, pathname_a, pathname_a_len);
  485. memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len);
  486. pathname_len = pathname_a_len + pathname_b_len;
  487. pathname[pathname_len] = 0;
  488. return pathname;
  489. }
  490. bool
  491. paths_init()
  492. {
  493. const char *home_dir, *xdg_config_home, *xdg_log_home;
  494. home_dir = getenv("HOME");
  495. if (home_dir == NULL)
  496. {
  497. fprintf(stderr, "Environment variable HOME not set\n");
  498. goto fail;
  499. }
  500. xdg_config_home = getenv("XDG_CONFIG_HOME");
  501. if (xdg_config_home == NULL)
  502. {
  503. if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail;
  504. }
  505. if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail;
  506. if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail;
  507. if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail;
  508. if (!ensure_dir_exist(xdg_config_home, 0700))
  509. {
  510. goto fail;
  511. }
  512. if (!ensure_dir_exist(xdg_log_home, 0700))
  513. {
  514. goto fail;
  515. }
  516. if (!ensure_dir_exist(g_jackdbus_config_dir, 0700))
  517. {
  518. free(g_jackdbus_config_dir);
  519. goto fail;
  520. }
  521. g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir);
  522. if (!ensure_dir_exist(g_jackdbus_log_dir, 0700))
  523. {
  524. free(g_jackdbus_log_dir);
  525. goto fail;
  526. }
  527. g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir);
  528. return true;
  529. fail:
  530. return false;
  531. }
  532. void
  533. paths_uninit()
  534. {
  535. free(g_jackdbus_config_dir);
  536. free(g_jackdbus_log_dir);
  537. }
  538. int
  539. log_init()
  540. {
  541. char *log_filename;
  542. size_t log_len;
  543. log_len = strlen(JACKDBUS_LOG);
  544. log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1);
  545. if (log_filename == NULL)
  546. {
  547. fprintf(stderr, "Out of memory\n");
  548. return FALSE;
  549. }
  550. memcpy(log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len);
  551. memcpy(log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len);
  552. log_filename[g_jackdbus_log_dir_len + log_len] = 0;
  553. g_logfile = fopen(log_filename, "a");
  554. if (g_logfile == NULL)
  555. {
  556. fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno));
  557. free(log_filename);
  558. return FALSE;
  559. }
  560. free(log_filename);
  561. return TRUE;
  562. }
  563. void
  564. log_uninit()
  565. {
  566. fclose(g_logfile);
  567. }
  568. void
  569. jack_dbus_error(
  570. void *dbus_call_context_ptr,
  571. const char *error_name,
  572. const char *format,
  573. ...)
  574. {
  575. va_list ap;
  576. char buffer[300];
  577. va_start(ap, format);
  578. vsnprintf(buffer, sizeof(buffer), format, ap);
  579. jack_error_callback(buffer);
  580. if (dbus_call_context_ptr != NULL)
  581. {
  582. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error(
  583. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message,
  584. error_name,
  585. buffer);
  586. }
  587. va_end(ap);
  588. }
  589. int
  590. main (int argc, char **argv)
  591. {
  592. DBusError error;
  593. int ret;
  594. void *controller_ptr;
  595. if (!jack_controller_settings_init())
  596. {
  597. ret = 1;
  598. goto fail;
  599. }
  600. if (argc != 2 || strcmp(argv[1], "auto") != 0)
  601. {
  602. ret = 0;
  603. fprintf(
  604. stderr,
  605. "jackdbus should be auto-executed by D-Bus message bus daemon.\n"
  606. "If you want to run it manually anyway, specify \"auto\" as only parameter\n");
  607. goto fail_uninit_xml;
  608. }
  609. if (!paths_init())
  610. {
  611. ret = 1;
  612. goto fail_uninit_xml;
  613. }
  614. if (!log_init())
  615. {
  616. ret = 1;
  617. goto fail_uninit_paths;
  618. }
  619. #if !defined(DISABLE_SIGNAL_MAGIC)
  620. jackctl_setup_signals(0);
  621. #endif
  622. jack_set_error_function(jack_dbus_error_callback);
  623. jack_set_info_function(jack_dbus_info_callback);
  624. jack_info("------------------");
  625. jack_info("Controller activated. Version %s (%s)", jack_get_version_string(), JACK_SVNREVISION);
  626. if (!dbus_threads_init_default())
  627. {
  628. jack_error("dbus_threads_init_default() failed");
  629. ret = 1;
  630. goto fail_uninit_log;
  631. }
  632. dbus_error_init (&error);
  633. g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
  634. if (dbus_error_is_set (&error))
  635. {
  636. jack_error("Cannot connect to D-Bus session bus: %s", error.message);
  637. ret = 1;
  638. goto fail_uninit_log;
  639. }
  640. ret = dbus_bus_request_name(
  641. g_connection,
  642. "org.jackaudio.service",
  643. DBUS_NAME_FLAG_DO_NOT_QUEUE,
  644. &error);
  645. if (ret == -1)
  646. {
  647. jack_error("Cannot request service name: %s", error.message);
  648. dbus_error_free(&error);
  649. ret = 1;
  650. goto fail_unref_connection;
  651. }
  652. else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
  653. {
  654. jack_error("Requested D-Bus service name already exists");
  655. ret = 1;
  656. goto fail_unref_connection;
  657. }
  658. controller_ptr = jack_controller_create(g_connection);
  659. if (controller_ptr == NULL)
  660. {
  661. ret = 1;
  662. goto fail_unref_connection;
  663. }
  664. jack_info("Listening for D-Bus messages");
  665. g_exit_command = FALSE;
  666. while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200));
  667. jack_controller_destroy(controller_ptr);
  668. jack_info("Controller deactivated.");
  669. ret = 0;
  670. fail_unref_connection:
  671. dbus_connection_unref(g_connection);
  672. fail_uninit_log:
  673. log_uninit();
  674. fail_uninit_paths:
  675. paths_uninit();
  676. fail_uninit_xml:
  677. jack_controller_settings_uninit();
  678. fail:
  679. return ret;
  680. }
  681. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  682. /*
  683. Copyright (C) 2007,2008 Nedko Arnaudov
  684. Copyright (C) 2007-2008 Juuso Alasuutari
  685. Copyright (C) 2008 Marc-Olivier Barre
  686. This program is free software; you can redistribute it and/or modify
  687. it under the terms of the GNU General Public License as published by
  688. the Free Software Foundation; either version 2 of the License.
  689. This program is distributed in the hope that it will be useful,
  690. but WITHOUT ANY WARRANTY; without even the implied warranty of
  691. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  692. GNU General Public License for more details.
  693. You should have received a copy of the GNU General Public License
  694. along with this program; if not, write to the Free Software
  695. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  696. */
  697. #include <stdbool.h>
  698. #include <stdlib.h>
  699. #include <stdio.h>
  700. #include <string.h>
  701. #include <errno.h>
  702. #include <sys/stat.h>
  703. #include <signal.h>
  704. #include <dbus/dbus.h>
  705. #include <pthread.h>
  706. #include <unistd.h>
  707. #include "config.h"
  708. #include "jackdbus.h"
  709. #include "controller.h"
  710. #include "jack/jack.h"
  711. #include "jack/jslist.h"
  712. #include "jack/control.h"
  713. FILE *g_logfile;
  714. char *g_jackdbus_config_dir;
  715. size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */
  716. char *g_jackdbus_log_dir;
  717. size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */
  718. int g_exit_command;
  719. DBusConnection *g_connection;
  720. void
  721. jack_dbus_send_signal(
  722. const char *sender_object_path,
  723. const char *iface,
  724. const char *signal_name,
  725. int first_arg_type,
  726. ...)
  727. {
  728. DBusMessage *message_ptr;
  729. va_list ap;
  730. va_start(ap, first_arg_type);
  731. message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name);
  732. if (message_ptr == NULL)
  733. {
  734. jack_error("dbus_message_new_signal() failed.");
  735. goto exit;
  736. }
  737. if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap))
  738. {
  739. jack_error("dbus_message_append_args_valist() failed.");
  740. goto unref;
  741. }
  742. /* Add message to outgoing message queue */
  743. if (!dbus_connection_send(g_connection, message_ptr, NULL))
  744. {
  745. jack_error("dbus_connection_send() failed.");
  746. goto unref;
  747. }
  748. unref:
  749. dbus_message_unref(message_ptr);
  750. exit:
  751. va_end(ap);
  752. }
  753. /*
  754. * Send a method return.
  755. *
  756. * If call->reply is NULL (i.e. a message construct method failed
  757. * due to lack of memory) attempt to send a void method return.
  758. */
  759. static
  760. void
  761. jack_dbus_send_method_return(
  762. struct jack_dbus_method_call * call)
  763. {
  764. if (call->reply)
  765. {
  766. retry_send:
  767. if (!dbus_connection_send (call->connection, call->reply, NULL))
  768. {
  769. jack_error ("Ran out of memory trying to queue method return");
  770. }
  771. dbus_connection_flush (call->connection);
  772. dbus_message_unref (call->reply);
  773. call->reply = NULL;
  774. }
  775. else
  776. {
  777. jack_error ("send_method_return() called with a NULL message,"
  778. " trying to construct a void return...");
  779. if ((call->reply = dbus_message_new_method_return (call->message)))
  780. {
  781. goto retry_send;
  782. }
  783. else
  784. {
  785. jack_error ("Failed to construct method return!");
  786. }
  787. }
  788. }
  789. #define object_ptr ((struct jack_dbus_object_descriptor *)data)
  790. /*
  791. * The D-Bus message handler for object path /org/jackaudio/Controller.
  792. */
  793. DBusHandlerResult
  794. jack_dbus_message_handler(
  795. DBusConnection *connection,
  796. DBusMessage *message,
  797. void *data)
  798. {
  799. struct jack_dbus_method_call call;
  800. const char *interface_name;
  801. struct jack_dbus_interface_descriptor ** interface_ptr_ptr;
  802. /* Check if the message is a method call. If not, ignore it. */
  803. if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
  804. {
  805. goto handled;
  806. }
  807. /* Get the invoked method's name and make sure it's non-NULL. */
  808. if (!(call.method_name = dbus_message_get_member (message)))
  809. {
  810. jack_dbus_error(
  811. &call,
  812. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  813. "Received method call with empty method name");
  814. goto send_return;
  815. }
  816. /* Initialize our data. */
  817. call.context = object_ptr->context;
  818. call.connection = connection;
  819. call.message = message;
  820. call.reply = NULL;
  821. /* Check if there's an interface specified for this method call. */
  822. interface_name = dbus_message_get_interface (message);
  823. if (interface_name != NULL)
  824. {
  825. /* Check if we can match the interface and method.
  826. * The inteface handler functions only return false if the
  827. * method name was unknown, otherwise they run the specified
  828. * method and return TRUE.
  829. */
  830. interface_ptr_ptr = object_ptr->interfaces;
  831. while (*interface_ptr_ptr != NULL)
  832. {
  833. if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0)
  834. {
  835. if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  836. {
  837. break;
  838. }
  839. goto send_return;
  840. }
  841. interface_ptr_ptr++;
  842. }
  843. }
  844. else
  845. {
  846. /* No interface was specified so we have to try them all. This is
  847. * dictated by the D-Bus specification which states that method calls
  848. * omitting the interface must never be rejected.
  849. */
  850. interface_ptr_ptr = object_ptr->interfaces;
  851. while (*interface_ptr_ptr != NULL)
  852. {
  853. if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  854. {
  855. goto send_return;
  856. }
  857. interface_ptr_ptr++;
  858. }
  859. }
  860. jack_dbus_error(
  861. &call,
  862. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  863. "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
  864. call.method_name,
  865. dbus_message_get_signature(message),
  866. interface_name);
  867. send_return:
  868. jack_dbus_send_method_return(&call);
  869. handled:
  870. return DBUS_HANDLER_RESULT_HANDLED;
  871. }
  872. void
  873. jack_dbus_message_handler_unregister(
  874. DBusConnection *connection,
  875. void *data)
  876. {
  877. jack_info ("Message handler was unregistered");
  878. }
  879. #undef object_ptr
  880. /*
  881. * Check if the supplied method name exists in org.jackaudio.JackConfigure,
  882. * if it does execute it and return TRUE. Otherwise return FALSE.
  883. */
  884. bool
  885. jack_dbus_run_method(
  886. struct jack_dbus_method_call *call,
  887. const struct jack_dbus_interface_method_descriptor * methods)
  888. {
  889. const struct jack_dbus_interface_method_descriptor * method_ptr;
  890. method_ptr = methods;
  891. while (method_ptr->name != NULL)
  892. {
  893. if (strcmp(call->method_name, method_ptr->name) == 0)
  894. {
  895. method_ptr->handler(call);
  896. return TRUE;
  897. }
  898. method_ptr++;
  899. }
  900. return FALSE;
  901. }
  902. /*
  903. * Read arguments from a method call.
  904. * If the operation fails construct an error and return false,
  905. * otherwise return true.
  906. */
  907. bool
  908. jack_dbus_get_method_args(
  909. struct jack_dbus_method_call *call,
  910. int type,
  911. ...)
  912. {
  913. va_list args;
  914. DBusError error;
  915. bool retval = true;
  916. va_start (args, type);
  917. dbus_error_init (&error);
  918. if (!dbus_message_get_args_valist (call->message, &error, type, args))
  919. {
  920. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  921. "Invalid arguments to method \"%s\"",
  922. call->method_name);
  923. retval = false;
  924. }
  925. dbus_error_free (&error);
  926. va_end (args);
  927. return retval;
  928. }
  929. /*
  930. * Read a string and a variant argument from a method call.
  931. * If the operation fails construct an error and return false,
  932. * otherwise return true.
  933. */
  934. bool
  935. jack_dbus_get_method_args_string_and_variant(
  936. struct jack_dbus_method_call *call,
  937. const char **arg1,
  938. message_arg_t *arg2,
  939. int *type_ptr)
  940. {
  941. DBusMessageIter iter, sub_iter;
  942. /* First we want a string... */
  943. if (dbus_message_iter_init (call->message, &iter)
  944. && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
  945. {
  946. dbus_message_iter_get_basic (&iter, arg1);
  947. dbus_message_iter_next (&iter);
  948. /* ...and then a variant. */
  949. if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT)
  950. {
  951. dbus_message_iter_recurse (&iter, &sub_iter);
  952. dbus_message_iter_get_basic (&sub_iter, arg2);
  953. *type_ptr = dbus_message_iter_get_arg_type (&sub_iter);
  954. /* Got what we wanted. */
  955. return true;
  956. }
  957. }
  958. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  959. "Invalid arguments to method \"%s\"",
  960. call->method_name);
  961. return false;
  962. }
  963. /*
  964. * Append a variant type to a D-Bus message.
  965. * Return false if something fails, true otherwise.
  966. */
  967. bool
  968. jack_dbus_message_append_variant(
  969. DBusMessageIter *iter,
  970. int type,
  971. const char *signature,
  972. message_arg_t *arg)
  973. {
  974. DBusMessageIter sub_iter;
  975. /* Open a variant container. */
  976. if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter))
  977. {
  978. goto fail;
  979. }
  980. /* Append the supplied value. */
  981. if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg))
  982. {
  983. dbus_message_iter_close_container (iter, &sub_iter);
  984. goto fail;
  985. }
  986. /* Close the container. */
  987. if (!dbus_message_iter_close_container (iter, &sub_iter))
  988. {
  989. goto fail;
  990. }
  991. return true;
  992. fail:
  993. return false;
  994. }
  995. /*
  996. * Construct an empty method return message.
  997. *
  998. * The operation can only fail due to lack of memory, in which case
  999. * there's no sense in trying to construct an error return. Instead,
  1000. * call->reply will be set to NULL and handled in send_method_return().
  1001. */
  1002. void
  1003. jack_dbus_construct_method_return_empty(
  1004. struct jack_dbus_method_call * call)
  1005. {
  1006. call->reply = dbus_message_new_method_return (call->message);
  1007. if (call->reply == NULL)
  1008. {
  1009. jack_error ("Ran out of memory trying to construct method return");
  1010. }
  1011. }
  1012. /*
  1013. * Construct a method return which holds a single argument or, if
  1014. * the type parameter is DBUS_TYPE_INVALID, no arguments at all
  1015. * (a void message).
  1016. *
  1017. * The operation can only fail due to lack of memory, in which case
  1018. * there's no sense in trying to construct an error return. Instead,
  1019. * call->reply will be set to NULL and handled in send_method_return().
  1020. */
  1021. void
  1022. jack_dbus_construct_method_return_single(
  1023. struct jack_dbus_method_call *call,
  1024. int type,
  1025. message_arg_t arg)
  1026. {
  1027. DBusMessageIter iter;
  1028. call->reply = dbus_message_new_method_return (call->message);
  1029. if (call->reply == NULL)
  1030. {
  1031. goto fail_no_mem;
  1032. }
  1033. /* Void method return requested by caller. */
  1034. if (type == DBUS_TYPE_INVALID)
  1035. {
  1036. return;
  1037. }
  1038. /* Prevent crash on NULL input string. */
  1039. else if (type == DBUS_TYPE_STRING && arg.string == NULL)
  1040. {
  1041. arg.string = "";
  1042. }
  1043. dbus_message_iter_init_append (call->reply, &iter);
  1044. if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg))
  1045. {
  1046. dbus_message_unref (call->reply);
  1047. call->reply = NULL;
  1048. goto fail_no_mem;
  1049. }
  1050. return;
  1051. fail_no_mem:
  1052. jack_error ("Ran out of memory trying to construct method return");
  1053. }
  1054. /*
  1055. * Construct a method return which holds an array of strings.
  1056. *
  1057. * The operation can only fail due to lack of memory, in which case
  1058. * there's no sense in trying to construct an error return. Instead,
  1059. * call->reply will be set to NULL and handled in send_method_return().
  1060. */
  1061. void
  1062. jack_dbus_construct_method_return_array_of_strings(
  1063. struct jack_dbus_method_call *call,
  1064. unsigned int num_members,
  1065. const char **array)
  1066. {
  1067. DBusMessageIter iter, sub_iter;
  1068. unsigned int i;
  1069. call->reply = dbus_message_new_method_return (call->message);
  1070. if (!call->reply)
  1071. {
  1072. goto fail;
  1073. }
  1074. dbus_message_iter_init_append (call->reply, &iter);
  1075. if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
  1076. {
  1077. goto fail_unref;
  1078. }
  1079. for (i = 0; i < num_members; ++i)
  1080. {
  1081. if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i]))
  1082. {
  1083. dbus_message_iter_close_container (&iter, &sub_iter);
  1084. goto fail_unref;
  1085. }
  1086. }
  1087. if (!dbus_message_iter_close_container (&iter, &sub_iter))
  1088. {
  1089. goto fail_unref;
  1090. }
  1091. return;
  1092. fail_unref:
  1093. dbus_message_unref (call->reply);
  1094. call->reply = NULL;
  1095. fail:
  1096. jack_error ("Ran out of memory trying to construct method return");
  1097. }
  1098. void
  1099. jack_dbus_info_callback(const char *msg)
  1100. {
  1101. time_t timestamp;
  1102. char timestamp_str[26];
  1103. time(&timestamp);
  1104. ctime_r(&timestamp, timestamp_str);
  1105. timestamp_str[24] = 0;
  1106. fprintf(g_logfile, "%s: %s\n", timestamp_str, msg);
  1107. fflush(g_logfile);
  1108. }
  1109. void
  1110. jack_dbus_error_callback(const char *msg)
  1111. {
  1112. time_t timestamp;
  1113. char timestamp_str[26];
  1114. time(&timestamp);
  1115. ctime_r(&timestamp, timestamp_str);
  1116. timestamp_str[24] = 0;
  1117. fprintf(g_logfile, "%s: ERROR: %s\n", timestamp_str, msg);
  1118. fflush(g_logfile);
  1119. }
  1120. bool
  1121. ensure_dir_exist(const char *dirname, int mode)
  1122. {
  1123. struct stat st;
  1124. if (stat(dirname, &st) != 0)
  1125. {
  1126. if (errno == ENOENT)
  1127. {
  1128. printf("Directory \"%s\" does not exist. Creating...\n", dirname);
  1129. if (mkdir(dirname, mode) != 0)
  1130. {
  1131. fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno));
  1132. return false;
  1133. }
  1134. }
  1135. else
  1136. {
  1137. fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno));
  1138. return false;
  1139. }
  1140. }
  1141. else
  1142. {
  1143. if (!S_ISDIR(st.st_mode))
  1144. {
  1145. fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname);
  1146. return false;
  1147. }
  1148. }
  1149. return true;
  1150. }
  1151. char *
  1152. pathname_cat(const char *pathname_a, const char *pathname_b)
  1153. {
  1154. char *pathname;
  1155. int pathname_a_len, pathname_b_len, pathname_len;
  1156. pathname_a_len = strlen(pathname_a);
  1157. pathname_b_len = strlen(pathname_b);
  1158. pathname = malloc(pathname_a_len + pathname_b_len + 1);
  1159. if (pathname == NULL)
  1160. {
  1161. fprintf(stderr, "Out of memory\n");
  1162. return NULL;
  1163. }
  1164. memcpy(pathname, pathname_a, pathname_a_len);
  1165. memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len);
  1166. pathname_len = pathname_a_len + pathname_b_len;
  1167. pathname[pathname_len] = 0;
  1168. return pathname;
  1169. }
  1170. bool
  1171. paths_init()
  1172. {
  1173. const char *home_dir, *xdg_config_home, *xdg_log_home;
  1174. home_dir = getenv("HOME");
  1175. if (home_dir == NULL)
  1176. {
  1177. fprintf(stderr, "Environment variable HOME not set\n");
  1178. goto fail;
  1179. }
  1180. xdg_config_home = getenv("XDG_CONFIG_HOME");
  1181. if (xdg_config_home == NULL)
  1182. {
  1183. if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail;
  1184. }
  1185. if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail;
  1186. if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail;
  1187. if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail;
  1188. if (!ensure_dir_exist(xdg_config_home, 0700))
  1189. {
  1190. goto fail;
  1191. }
  1192. if (!ensure_dir_exist(xdg_log_home, 0700))
  1193. {
  1194. goto fail;
  1195. }
  1196. if (!ensure_dir_exist(g_jackdbus_config_dir, 0700))
  1197. {
  1198. free(g_jackdbus_config_dir);
  1199. goto fail;
  1200. }
  1201. g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir);
  1202. if (!ensure_dir_exist(g_jackdbus_log_dir, 0700))
  1203. {
  1204. free(g_jackdbus_log_dir);
  1205. goto fail;
  1206. }
  1207. g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir);
  1208. return true;
  1209. fail:
  1210. return false;
  1211. }
  1212. void
  1213. paths_uninit()
  1214. {
  1215. free(g_jackdbus_config_dir);
  1216. free(g_jackdbus_log_dir);
  1217. }
  1218. int
  1219. log_init()
  1220. {
  1221. char *log_filename;
  1222. size_t log_len;
  1223. log_len = strlen(JACKDBUS_LOG);
  1224. log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1);
  1225. if (log_filename == NULL)
  1226. {
  1227. fprintf(stderr, "Out of memory\n");
  1228. return FALSE;
  1229. }
  1230. memcpy(log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len);
  1231. memcpy(log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len);
  1232. log_filename[g_jackdbus_log_dir_len + log_len] = 0;
  1233. g_logfile = fopen(log_filename, "a");
  1234. if (g_logfile == NULL)
  1235. {
  1236. fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno));
  1237. free(log_filename);
  1238. return FALSE;
  1239. }
  1240. free(log_filename);
  1241. return TRUE;
  1242. }
  1243. void
  1244. log_uninit()
  1245. {
  1246. fclose(g_logfile);
  1247. }
  1248. void
  1249. jack_dbus_error(
  1250. void *dbus_call_context_ptr,
  1251. const char *error_name,
  1252. const char *format,
  1253. ...)
  1254. {
  1255. va_list ap;
  1256. char buffer[300];
  1257. va_start(ap, format);
  1258. vsnprintf(buffer, sizeof(buffer), format, ap);
  1259. jack_error_callback(buffer);
  1260. if (dbus_call_context_ptr != NULL)
  1261. {
  1262. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error(
  1263. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message,
  1264. error_name,
  1265. buffer);
  1266. }
  1267. va_end(ap);
  1268. }
  1269. int
  1270. main (int argc, char **argv)
  1271. {
  1272. DBusError error;
  1273. int ret;
  1274. void *controller_ptr;
  1275. if (!jack_controller_settings_init())
  1276. {
  1277. ret = 1;
  1278. goto fail;
  1279. }
  1280. if (argc != 2 || strcmp(argv[1], "auto") != 0)
  1281. {
  1282. ret = 0;
  1283. fprintf(
  1284. stderr,
  1285. "jackdbus should be auto-executed by D-Bus message bus daemon.\n"
  1286. "If you want to run it manually anyway, specify \"auto\" as only parameter\n");
  1287. goto fail_uninit_xml;
  1288. }
  1289. if (!paths_init())
  1290. {
  1291. ret = 1;
  1292. goto fail_uninit_xml;
  1293. }
  1294. if (!log_init())
  1295. {
  1296. ret = 1;
  1297. goto fail_uninit_paths;
  1298. }
  1299. #if !defined(DISABLE_SIGNAL_MAGIC)
  1300. jackctl_setup_signals(0);
  1301. #endif
  1302. jack_set_error_function(jack_dbus_error_callback);
  1303. jack_set_info_function(jack_dbus_info_callback);
  1304. jack_info("------------------");
  1305. jack_info("Controller activated. Version %s (%s)", jack_get_version_string(), JACK_SVNREVISION);
  1306. if (!dbus_threads_init_default())
  1307. {
  1308. jack_error("dbus_threads_init_default() failed");
  1309. ret = 1;
  1310. goto fail_uninit_log;
  1311. }
  1312. dbus_error_init (&error);
  1313. g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
  1314. if (dbus_error_is_set (&error))
  1315. {
  1316. jack_error("Cannot connect to D-Bus session bus: %s", error.message);
  1317. ret = 1;
  1318. goto fail_uninit_log;
  1319. }
  1320. ret = dbus_bus_request_name(
  1321. g_connection,
  1322. "org.jackaudio.service",
  1323. DBUS_NAME_FLAG_DO_NOT_QUEUE,
  1324. &error);
  1325. if (ret == -1)
  1326. {
  1327. jack_error("Cannot request service name: %s", error.message);
  1328. dbus_error_free(&error);
  1329. ret = 1;
  1330. goto fail_unref_connection;
  1331. }
  1332. else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
  1333. {
  1334. jack_error("Requested D-Bus service name already exists");
  1335. ret = 1;
  1336. goto fail_unref_connection;
  1337. }
  1338. controller_ptr = jack_controller_create(g_connection);
  1339. if (controller_ptr == NULL)
  1340. {
  1341. ret = 1;
  1342. goto fail_unref_connection;
  1343. }
  1344. jack_info("Listening for D-Bus messages");
  1345. g_exit_command = FALSE;
  1346. while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200));
  1347. jack_controller_destroy(controller_ptr);
  1348. jack_info("Controller deactivated.");
  1349. ret = 0;
  1350. fail_unref_connection:
  1351. dbus_connection_unref(g_connection);
  1352. fail_uninit_log:
  1353. log_uninit();
  1354. fail_uninit_paths:
  1355. paths_uninit();
  1356. fail_uninit_xml:
  1357. jack_controller_settings_uninit();
  1358. fail:
  1359. return ret;
  1360. }
  1361. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  1362. /*
  1363. Copyright (C) 2007,2008 Nedko Arnaudov
  1364. Copyright (C) 2007-2008 Juuso Alasuutari
  1365. Copyright (C) 2008 Marc-Olivier Barre
  1366. This program is free software; you can redistribute it and/or modify
  1367. it under the terms of the GNU General Public License as published by
  1368. the Free Software Foundation; either version 2 of the License.
  1369. This program is distributed in the hope that it will be useful,
  1370. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1371. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1372. GNU General Public License for more details.
  1373. You should have received a copy of the GNU General Public License
  1374. along with this program; if not, write to the Free Software
  1375. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1376. */
  1377. #include <stdbool.h>
  1378. #include <stdlib.h>
  1379. #include <stdio.h>
  1380. #include <string.h>
  1381. #include <errno.h>
  1382. #include <sys/stat.h>
  1383. #include <signal.h>
  1384. #include <dbus/dbus.h>
  1385. #include <pthread.h>
  1386. #include <unistd.h>
  1387. #include "config.h"
  1388. #include "jackdbus.h"
  1389. #include "controller.h"
  1390. #include "jack/jack.h"
  1391. #include "jack/jslist.h"
  1392. #include "jack/control.h"
  1393. FILE *g_logfile;
  1394. char *g_jackdbus_config_dir;
  1395. size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */
  1396. char *g_jackdbus_log_dir;
  1397. size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */
  1398. int g_exit_command;
  1399. DBusConnection *g_connection;
  1400. void
  1401. jack_dbus_send_signal(
  1402. const char *sender_object_path,
  1403. const char *iface,
  1404. const char *signal_name,
  1405. int first_arg_type,
  1406. ...)
  1407. {
  1408. DBusMessage *message_ptr;
  1409. va_list ap;
  1410. va_start(ap, first_arg_type);
  1411. message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name);
  1412. if (message_ptr == NULL)
  1413. {
  1414. jack_error("dbus_message_new_signal() failed.");
  1415. goto exit;
  1416. }
  1417. if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap))
  1418. {
  1419. jack_error("dbus_message_append_args_valist() failed.");
  1420. goto unref;
  1421. }
  1422. /* Add message to outgoing message queue */
  1423. if (!dbus_connection_send(g_connection, message_ptr, NULL))
  1424. {
  1425. jack_error("dbus_connection_send() failed.");
  1426. goto unref;
  1427. }
  1428. unref:
  1429. dbus_message_unref(message_ptr);
  1430. exit:
  1431. va_end(ap);
  1432. }
  1433. /*
  1434. * Send a method return.
  1435. *
  1436. * If call->reply is NULL (i.e. a message construct method failed
  1437. * due to lack of memory) attempt to send a void method return.
  1438. */
  1439. static
  1440. void
  1441. jack_dbus_send_method_return(
  1442. struct jack_dbus_method_call * call)
  1443. {
  1444. if (call->reply)
  1445. {
  1446. retry_send:
  1447. if (!dbus_connection_send (call->connection, call->reply, NULL))
  1448. {
  1449. jack_error ("Ran out of memory trying to queue method return");
  1450. }
  1451. dbus_connection_flush (call->connection);
  1452. dbus_message_unref (call->reply);
  1453. call->reply = NULL;
  1454. }
  1455. else
  1456. {
  1457. jack_error ("send_method_return() called with a NULL message,"
  1458. " trying to construct a void return...");
  1459. if ((call->reply = dbus_message_new_method_return (call->message)))
  1460. {
  1461. goto retry_send;
  1462. }
  1463. else
  1464. {
  1465. jack_error ("Failed to construct method return!");
  1466. }
  1467. }
  1468. }
  1469. #define object_ptr ((struct jack_dbus_object_descriptor *)data)
  1470. /*
  1471. * The D-Bus message handler for object path /org/jackaudio/Controller.
  1472. */
  1473. DBusHandlerResult
  1474. jack_dbus_message_handler(
  1475. DBusConnection *connection,
  1476. DBusMessage *message,
  1477. void *data)
  1478. {
  1479. struct jack_dbus_method_call call;
  1480. const char *interface_name;
  1481. struct jack_dbus_interface_descriptor ** interface_ptr_ptr;
  1482. /* Check if the message is a method call. If not, ignore it. */
  1483. if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
  1484. {
  1485. goto handled;
  1486. }
  1487. /* Get the invoked method's name and make sure it's non-NULL. */
  1488. if (!(call.method_name = dbus_message_get_member (message)))
  1489. {
  1490. jack_dbus_error(
  1491. &call,
  1492. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  1493. "Received method call with empty method name");
  1494. goto send_return;
  1495. }
  1496. /* Initialize our data. */
  1497. call.context = object_ptr->context;
  1498. call.connection = connection;
  1499. call.message = message;
  1500. call.reply = NULL;
  1501. /* Check if there's an interface specified for this method call. */
  1502. interface_name = dbus_message_get_interface (message);
  1503. if (interface_name != NULL)
  1504. {
  1505. /* Check if we can match the interface and method.
  1506. * The inteface handler functions only return false if the
  1507. * method name was unknown, otherwise they run the specified
  1508. * method and return TRUE.
  1509. */
  1510. interface_ptr_ptr = object_ptr->interfaces;
  1511. while (*interface_ptr_ptr != NULL)
  1512. {
  1513. if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0)
  1514. {
  1515. if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  1516. {
  1517. break;
  1518. }
  1519. goto send_return;
  1520. }
  1521. interface_ptr_ptr++;
  1522. }
  1523. }
  1524. else
  1525. {
  1526. /* No interface was specified so we have to try them all. This is
  1527. * dictated by the D-Bus specification which states that method calls
  1528. * omitting the interface must never be rejected.
  1529. */
  1530. interface_ptr_ptr = object_ptr->interfaces;
  1531. while (*interface_ptr_ptr != NULL)
  1532. {
  1533. if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  1534. {
  1535. goto send_return;
  1536. }
  1537. interface_ptr_ptr++;
  1538. }
  1539. }
  1540. jack_dbus_error(
  1541. &call,
  1542. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  1543. "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
  1544. call.method_name,
  1545. dbus_message_get_signature(message),
  1546. interface_name);
  1547. send_return:
  1548. jack_dbus_send_method_return(&call);
  1549. handled:
  1550. return DBUS_HANDLER_RESULT_HANDLED;
  1551. }
  1552. void
  1553. jack_dbus_message_handler_unregister(
  1554. DBusConnection *connection,
  1555. void *data)
  1556. {
  1557. jack_info ("Message handler was unregistered");
  1558. }
  1559. #undef object_ptr
  1560. /*
  1561. * Check if the supplied method name exists in org.jackaudio.JackConfigure,
  1562. * if it does execute it and return TRUE. Otherwise return FALSE.
  1563. */
  1564. bool
  1565. jack_dbus_run_method(
  1566. struct jack_dbus_method_call *call,
  1567. const struct jack_dbus_interface_method_descriptor * methods)
  1568. {
  1569. const struct jack_dbus_interface_method_descriptor * method_ptr;
  1570. method_ptr = methods;
  1571. while (method_ptr->name != NULL)
  1572. {
  1573. if (strcmp(call->method_name, method_ptr->name) == 0)
  1574. {
  1575. method_ptr->handler(call);
  1576. return TRUE;
  1577. }
  1578. method_ptr++;
  1579. }
  1580. return FALSE;
  1581. }
  1582. /*
  1583. * Read arguments from a method call.
  1584. * If the operation fails construct an error and return false,
  1585. * otherwise return true.
  1586. */
  1587. bool
  1588. jack_dbus_get_method_args(
  1589. struct jack_dbus_method_call *call,
  1590. int type,
  1591. ...)
  1592. {
  1593. va_list args;
  1594. DBusError error;
  1595. bool retval = true;
  1596. va_start (args, type);
  1597. dbus_error_init (&error);
  1598. if (!dbus_message_get_args_valist (call->message, &error, type, args))
  1599. {
  1600. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  1601. "Invalid arguments to method \"%s\"",
  1602. call->method_name);
  1603. retval = false;
  1604. }
  1605. dbus_error_free (&error);
  1606. va_end (args);
  1607. return retval;
  1608. }
  1609. /*
  1610. * Read a string and a variant argument from a method call.
  1611. * If the operation fails construct an error and return false,
  1612. * otherwise return true.
  1613. */
  1614. bool
  1615. jack_dbus_get_method_args_string_and_variant(
  1616. struct jack_dbus_method_call *call,
  1617. const char **arg1,
  1618. message_arg_t *arg2,
  1619. int *type_ptr)
  1620. {
  1621. DBusMessageIter iter, sub_iter;
  1622. /* First we want a string... */
  1623. if (dbus_message_iter_init (call->message, &iter)
  1624. && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
  1625. {
  1626. dbus_message_iter_get_basic (&iter, arg1);
  1627. dbus_message_iter_next (&iter);
  1628. /* ...and then a variant. */
  1629. if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT)
  1630. {
  1631. dbus_message_iter_recurse (&iter, &sub_iter);
  1632. dbus_message_iter_get_basic (&sub_iter, arg2);
  1633. *type_ptr = dbus_message_iter_get_arg_type (&sub_iter);
  1634. /* Got what we wanted. */
  1635. return true;
  1636. }
  1637. }
  1638. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  1639. "Invalid arguments to method \"%s\"",
  1640. call->method_name);
  1641. return false;
  1642. }
  1643. /*
  1644. * Append a variant type to a D-Bus message.
  1645. * Return false if something fails, true otherwise.
  1646. */
  1647. bool
  1648. jack_dbus_message_append_variant(
  1649. DBusMessageIter *iter,
  1650. int type,
  1651. const char *signature,
  1652. message_arg_t *arg)
  1653. {
  1654. DBusMessageIter sub_iter;
  1655. /* Open a variant container. */
  1656. if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter))
  1657. {
  1658. goto fail;
  1659. }
  1660. /* Append the supplied value. */
  1661. if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg))
  1662. {
  1663. dbus_message_iter_close_container (iter, &sub_iter);
  1664. goto fail;
  1665. }
  1666. /* Close the container. */
  1667. if (!dbus_message_iter_close_container (iter, &sub_iter))
  1668. {
  1669. goto fail;
  1670. }
  1671. return true;
  1672. fail:
  1673. return false;
  1674. }
  1675. /*
  1676. * Construct an empty method return message.
  1677. *
  1678. * The operation can only fail due to lack of memory, in which case
  1679. * there's no sense in trying to construct an error return. Instead,
  1680. * call->reply will be set to NULL and handled in send_method_return().
  1681. */
  1682. void
  1683. jack_dbus_construct_method_return_empty(
  1684. struct jack_dbus_method_call * call)
  1685. {
  1686. call->reply = dbus_message_new_method_return (call->message);
  1687. if (call->reply == NULL)
  1688. {
  1689. jack_error ("Ran out of memory trying to construct method return");
  1690. }
  1691. }
  1692. /*
  1693. * Construct a method return which holds a single argument or, if
  1694. * the type parameter is DBUS_TYPE_INVALID, no arguments at all
  1695. * (a void message).
  1696. *
  1697. * The operation can only fail due to lack of memory, in which case
  1698. * there's no sense in trying to construct an error return. Instead,
  1699. * call->reply will be set to NULL and handled in send_method_return().
  1700. */
  1701. void
  1702. jack_dbus_construct_method_return_single(
  1703. struct jack_dbus_method_call *call,
  1704. int type,
  1705. message_arg_t arg)
  1706. {
  1707. DBusMessageIter iter;
  1708. call->reply = dbus_message_new_method_return (call->message);
  1709. if (call->reply == NULL)
  1710. {
  1711. goto fail_no_mem;
  1712. }
  1713. /* Void method return requested by caller. */
  1714. if (type == DBUS_TYPE_INVALID)
  1715. {
  1716. return;
  1717. }
  1718. /* Prevent crash on NULL input string. */
  1719. else if (type == DBUS_TYPE_STRING && arg.string == NULL)
  1720. {
  1721. arg.string = "";
  1722. }
  1723. dbus_message_iter_init_append (call->reply, &iter);
  1724. if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg))
  1725. {
  1726. dbus_message_unref (call->reply);
  1727. call->reply = NULL;
  1728. goto fail_no_mem;
  1729. }
  1730. return;
  1731. fail_no_mem:
  1732. jack_error ("Ran out of memory trying to construct method return");
  1733. }
  1734. /*
  1735. * Construct a method return which holds an array of strings.
  1736. *
  1737. * The operation can only fail due to lack of memory, in which case
  1738. * there's no sense in trying to construct an error return. Instead,
  1739. * call->reply will be set to NULL and handled in send_method_return().
  1740. */
  1741. void
  1742. jack_dbus_construct_method_return_array_of_strings(
  1743. struct jack_dbus_method_call *call,
  1744. unsigned int num_members,
  1745. const char **array)
  1746. {
  1747. DBusMessageIter iter, sub_iter;
  1748. unsigned int i;
  1749. call->reply = dbus_message_new_method_return (call->message);
  1750. if (!call->reply)
  1751. {
  1752. goto fail;
  1753. }
  1754. dbus_message_iter_init_append (call->reply, &iter);
  1755. if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
  1756. {
  1757. goto fail_unref;
  1758. }
  1759. for (i = 0; i < num_members; ++i)
  1760. {
  1761. if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i]))
  1762. {
  1763. dbus_message_iter_close_container (&iter, &sub_iter);
  1764. goto fail_unref;
  1765. }
  1766. }
  1767. if (!dbus_message_iter_close_container (&iter, &sub_iter))
  1768. {
  1769. goto fail_unref;
  1770. }
  1771. return;
  1772. fail_unref:
  1773. dbus_message_unref (call->reply);
  1774. call->reply = NULL;
  1775. fail:
  1776. jack_error ("Ran out of memory trying to construct method return");
  1777. }
  1778. void
  1779. jack_dbus_info_callback(const char *msg)
  1780. {
  1781. time_t timestamp;
  1782. char timestamp_str[26];
  1783. time(&timestamp);
  1784. ctime_r(&timestamp, timestamp_str);
  1785. timestamp_str[24] = 0;
  1786. fprintf(g_logfile, "%s: %s\n", timestamp_str, msg);
  1787. fflush(g_logfile);
  1788. }
  1789. void
  1790. jack_dbus_error_callback(const char *msg)
  1791. {
  1792. time_t timestamp;
  1793. char timestamp_str[26];
  1794. time(&timestamp);
  1795. ctime_r(&timestamp, timestamp_str);
  1796. timestamp_str[24] = 0;
  1797. fprintf(g_logfile, "%s: ERROR: %s\n", timestamp_str, msg);
  1798. fflush(g_logfile);
  1799. }
  1800. bool
  1801. ensure_dir_exist(const char *dirname, int mode)
  1802. {
  1803. struct stat st;
  1804. if (stat(dirname, &st) != 0)
  1805. {
  1806. if (errno == ENOENT)
  1807. {
  1808. printf("Directory \"%s\" does not exist. Creating...\n", dirname);
  1809. if (mkdir(dirname, mode) != 0)
  1810. {
  1811. fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno));
  1812. return false;
  1813. }
  1814. }
  1815. else
  1816. {
  1817. fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno));
  1818. return false;
  1819. }
  1820. }
  1821. else
  1822. {
  1823. if (!S_ISDIR(st.st_mode))
  1824. {
  1825. fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname);
  1826. return false;
  1827. }
  1828. }
  1829. return true;
  1830. }
  1831. char *
  1832. pathname_cat(const char *pathname_a, const char *pathname_b)
  1833. {
  1834. char *pathname;
  1835. int pathname_a_len, pathname_b_len, pathname_len;
  1836. pathname_a_len = strlen(pathname_a);
  1837. pathname_b_len = strlen(pathname_b);
  1838. pathname = malloc(pathname_a_len + pathname_b_len + 1);
  1839. if (pathname == NULL)
  1840. {
  1841. fprintf(stderr, "Out of memory\n");
  1842. return NULL;
  1843. }
  1844. memcpy(pathname, pathname_a, pathname_a_len);
  1845. memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len);
  1846. pathname_len = pathname_a_len + pathname_b_len;
  1847. pathname[pathname_len] = 0;
  1848. return pathname;
  1849. }
  1850. bool
  1851. paths_init()
  1852. {
  1853. const char *home_dir, *xdg_config_home, *xdg_log_home;
  1854. home_dir = getenv("HOME");
  1855. if (home_dir == NULL)
  1856. {
  1857. fprintf(stderr, "Environment variable HOME not set\n");
  1858. goto fail;
  1859. }
  1860. xdg_config_home = getenv("XDG_CONFIG_HOME");
  1861. if (xdg_config_home == NULL)
  1862. {
  1863. if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail;
  1864. }
  1865. if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail;
  1866. if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail;
  1867. if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail;
  1868. if (!ensure_dir_exist(xdg_config_home, 0700))
  1869. {
  1870. goto fail;
  1871. }
  1872. if (!ensure_dir_exist(xdg_log_home, 0700))
  1873. {
  1874. goto fail;
  1875. }
  1876. if (!ensure_dir_exist(g_jackdbus_config_dir, 0700))
  1877. {
  1878. free(g_jackdbus_config_dir);
  1879. goto fail;
  1880. }
  1881. g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir);
  1882. if (!ensure_dir_exist(g_jackdbus_log_dir, 0700))
  1883. {
  1884. free(g_jackdbus_log_dir);
  1885. goto fail;
  1886. }
  1887. g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir);
  1888. return true;
  1889. fail:
  1890. return false;
  1891. }
  1892. void
  1893. paths_uninit()
  1894. {
  1895. free(g_jackdbus_config_dir);
  1896. free(g_jackdbus_log_dir);
  1897. }
  1898. int
  1899. log_init()
  1900. {
  1901. char *log_filename;
  1902. size_t log_len;
  1903. log_len = strlen(JACKDBUS_LOG);
  1904. log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1);
  1905. if (log_filename == NULL)
  1906. {
  1907. fprintf(stderr, "Out of memory\n");
  1908. return FALSE;
  1909. }
  1910. memcpy(log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len);
  1911. memcpy(log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len);
  1912. log_filename[g_jackdbus_log_dir_len + log_len] = 0;
  1913. g_logfile = fopen(log_filename, "a");
  1914. if (g_logfile == NULL)
  1915. {
  1916. fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno));
  1917. free(log_filename);
  1918. return FALSE;
  1919. }
  1920. free(log_filename);
  1921. return TRUE;
  1922. }
  1923. void
  1924. log_uninit()
  1925. {
  1926. fclose(g_logfile);
  1927. }
  1928. void
  1929. jack_dbus_error(
  1930. void *dbus_call_context_ptr,
  1931. const char *error_name,
  1932. const char *format,
  1933. ...)
  1934. {
  1935. va_list ap;
  1936. char buffer[300];
  1937. va_start(ap, format);
  1938. vsnprintf(buffer, sizeof(buffer), format, ap);
  1939. jack_error_callback(buffer);
  1940. if (dbus_call_context_ptr != NULL)
  1941. {
  1942. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error(
  1943. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message,
  1944. error_name,
  1945. buffer);
  1946. }
  1947. va_end(ap);
  1948. }
  1949. int
  1950. main (int argc, char **argv)
  1951. {
  1952. DBusError error;
  1953. int ret;
  1954. void *controller_ptr;
  1955. if (!jack_controller_settings_init())
  1956. {
  1957. ret = 1;
  1958. goto fail;
  1959. }
  1960. if (argc != 2 || strcmp(argv[1], "auto") != 0)
  1961. {
  1962. ret = 0;
  1963. fprintf(
  1964. stderr,
  1965. "jackdbus should be auto-executed by D-Bus message bus daemon.\n"
  1966. "If you want to run it manually anyway, specify \"auto\" as only parameter\n");
  1967. goto fail_uninit_xml;
  1968. }
  1969. if (!paths_init())
  1970. {
  1971. ret = 1;
  1972. goto fail_uninit_xml;
  1973. }
  1974. if (!log_init())
  1975. {
  1976. ret = 1;
  1977. goto fail_uninit_paths;
  1978. }
  1979. #if !defined(DISABLE_SIGNAL_MAGIC)
  1980. jackctl_setup_signals(0);
  1981. #endif
  1982. jack_set_error_function(jack_dbus_error_callback);
  1983. jack_set_info_function(jack_dbus_info_callback);
  1984. jack_info("------------------");
  1985. jack_info("Controller activated. Version %s (%s)", jack_get_version_string(), JACK_SVNREVISION);
  1986. if (!dbus_threads_init_default())
  1987. {
  1988. jack_error("dbus_threads_init_default() failed");
  1989. ret = 1;
  1990. goto fail_uninit_log;
  1991. }
  1992. dbus_error_init (&error);
  1993. g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
  1994. if (dbus_error_is_set (&error))
  1995. {
  1996. jack_error("Cannot connect to D-Bus session bus: %s", error.message);
  1997. ret = 1;
  1998. goto fail_uninit_log;
  1999. }
  2000. ret = dbus_bus_request_name(
  2001. g_connection,
  2002. "org.jackaudio.service",
  2003. DBUS_NAME_FLAG_DO_NOT_QUEUE,
  2004. &error);
  2005. if (ret == -1)
  2006. {
  2007. jack_error("Cannot request service name: %s", error.message);
  2008. dbus_error_free(&error);
  2009. ret = 1;
  2010. goto fail_unref_connection;
  2011. }
  2012. else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
  2013. {
  2014. jack_error("Requested D-Bus service name already exists");
  2015. ret = 1;
  2016. goto fail_unref_connection;
  2017. }
  2018. controller_ptr = jack_controller_create(g_connection);
  2019. if (controller_ptr == NULL)
  2020. {
  2021. ret = 1;
  2022. goto fail_unref_connection;
  2023. }
  2024. jack_info("Listening for D-Bus messages");
  2025. g_exit_command = FALSE;
  2026. while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200));
  2027. jack_controller_destroy(controller_ptr);
  2028. jack_info("Controller deactivated.");
  2029. ret = 0;
  2030. fail_unref_connection:
  2031. dbus_connection_unref(g_connection);
  2032. fail_uninit_log:
  2033. log_uninit();
  2034. fail_uninit_paths:
  2035. paths_uninit();
  2036. fail_uninit_xml:
  2037. jack_controller_settings_uninit();
  2038. fail:
  2039. return ret;
  2040. }
  2041. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  2042. /*
  2043. Copyright (C) 2007,2008 Nedko Arnaudov
  2044. Copyright (C) 2007-2008 Juuso Alasuutari
  2045. Copyright (C) 2008 Marc-Olivier Barre
  2046. This program is free software; you can redistribute it and/or modify
  2047. it under the terms of the GNU General Public License as published by
  2048. the Free Software Foundation; either version 2 of the License.
  2049. This program is distributed in the hope that it will be useful,
  2050. but WITHOUT ANY WARRANTY; without even the implied warranty of
  2051. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2052. GNU General Public License for more details.
  2053. You should have received a copy of the GNU General Public License
  2054. along with this program; if not, write to the Free Software
  2055. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2056. */
  2057. #include <stdbool.h>
  2058. #include <stdlib.h>
  2059. #include <stdio.h>
  2060. #include <string.h>
  2061. #include <errno.h>
  2062. #include <sys/stat.h>
  2063. #include <signal.h>
  2064. #include <dbus/dbus.h>
  2065. #include <pthread.h>
  2066. #include <unistd.h>
  2067. #include "config.h"
  2068. #include "jackdbus.h"
  2069. #include "controller.h"
  2070. #include "jack/jack.h"
  2071. #include "jack/jslist.h"
  2072. #include "jack/control.h"
  2073. FILE *g_logfile;
  2074. char *g_jackdbus_config_dir;
  2075. size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */
  2076. char *g_jackdbus_log_dir;
  2077. size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */
  2078. int g_exit_command;
  2079. DBusConnection *g_connection;
  2080. void
  2081. jack_dbus_send_signal(
  2082. const char *sender_object_path,
  2083. const char *iface,
  2084. const char *signal_name,
  2085. int first_arg_type,
  2086. ...)
  2087. {
  2088. DBusMessage *message_ptr;
  2089. va_list ap;
  2090. va_start(ap, first_arg_type);
  2091. message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name);
  2092. if (message_ptr == NULL)
  2093. {
  2094. jack_error("dbus_message_new_signal() failed.");
  2095. goto exit;
  2096. }
  2097. if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap))
  2098. {
  2099. jack_error("dbus_message_append_args_valist() failed.");
  2100. goto unref;
  2101. }
  2102. /* Add message to outgoing message queue */
  2103. if (!dbus_connection_send(g_connection, message_ptr, NULL))
  2104. {
  2105. jack_error("dbus_connection_send() failed.");
  2106. goto unref;
  2107. }
  2108. unref:
  2109. dbus_message_unref(message_ptr);
  2110. exit:
  2111. va_end(ap);
  2112. }
  2113. /*
  2114. * Send a method return.
  2115. *
  2116. * If call->reply is NULL (i.e. a message construct method failed
  2117. * due to lack of memory) attempt to send a void method return.
  2118. */
  2119. static
  2120. void
  2121. jack_dbus_send_method_return(
  2122. struct jack_dbus_method_call * call)
  2123. {
  2124. if (call->reply)
  2125. {
  2126. retry_send:
  2127. if (!dbus_connection_send (call->connection, call->reply, NULL))
  2128. {
  2129. jack_error ("Ran out of memory trying to queue method return");
  2130. }
  2131. dbus_connection_flush (call->connection);
  2132. dbus_message_unref (call->reply);
  2133. call->reply = NULL;
  2134. }
  2135. else
  2136. {
  2137. jack_error ("send_method_return() called with a NULL message,"
  2138. " trying to construct a void return...");
  2139. if ((call->reply = dbus_message_new_method_return (call->message)))
  2140. {
  2141. goto retry_send;
  2142. }
  2143. else
  2144. {
  2145. jack_error ("Failed to construct method return!");
  2146. }
  2147. }
  2148. }
  2149. #define object_ptr ((struct jack_dbus_object_descriptor *)data)
  2150. /*
  2151. * The D-Bus message handler for object path /org/jackaudio/Controller.
  2152. */
  2153. DBusHandlerResult
  2154. jack_dbus_message_handler(
  2155. DBusConnection *connection,
  2156. DBusMessage *message,
  2157. void *data)
  2158. {
  2159. struct jack_dbus_method_call call;
  2160. const char *interface_name;
  2161. struct jack_dbus_interface_descriptor ** interface_ptr_ptr;
  2162. /* Check if the message is a method call. If not, ignore it. */
  2163. if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
  2164. {
  2165. goto handled;
  2166. }
  2167. /* Get the invoked method's name and make sure it's non-NULL. */
  2168. if (!(call.method_name = dbus_message_get_member (message)))
  2169. {
  2170. jack_dbus_error(
  2171. &call,
  2172. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  2173. "Received method call with empty method name");
  2174. goto send_return;
  2175. }
  2176. /* Initialize our data. */
  2177. call.context = object_ptr->context;
  2178. call.connection = connection;
  2179. call.message = message;
  2180. call.reply = NULL;
  2181. /* Check if there's an interface specified for this method call. */
  2182. interface_name = dbus_message_get_interface (message);
  2183. if (interface_name != NULL)
  2184. {
  2185. /* Check if we can match the interface and method.
  2186. * The inteface handler functions only return false if the
  2187. * method name was unknown, otherwise they run the specified
  2188. * method and return TRUE.
  2189. */
  2190. interface_ptr_ptr = object_ptr->interfaces;
  2191. while (*interface_ptr_ptr != NULL)
  2192. {
  2193. if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0)
  2194. {
  2195. if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  2196. {
  2197. break;
  2198. }
  2199. goto send_return;
  2200. }
  2201. interface_ptr_ptr++;
  2202. }
  2203. }
  2204. else
  2205. {
  2206. /* No interface was specified so we have to try them all. This is
  2207. * dictated by the D-Bus specification which states that method calls
  2208. * omitting the interface must never be rejected.
  2209. */
  2210. interface_ptr_ptr = object_ptr->interfaces;
  2211. while (*interface_ptr_ptr != NULL)
  2212. {
  2213. if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  2214. {
  2215. goto send_return;
  2216. }
  2217. interface_ptr_ptr++;
  2218. }
  2219. }
  2220. jack_dbus_error(
  2221. &call,
  2222. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  2223. "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
  2224. call.method_name,
  2225. dbus_message_get_signature(message),
  2226. interface_name);
  2227. send_return:
  2228. jack_dbus_send_method_return(&call);
  2229. handled:
  2230. return DBUS_HANDLER_RESULT_HANDLED;
  2231. }
  2232. void
  2233. jack_dbus_message_handler_unregister(
  2234. DBusConnection *connection,
  2235. void *data)
  2236. {
  2237. jack_info ("Message handler was unregistered");
  2238. }
  2239. #undef object_ptr
  2240. /*
  2241. * Check if the supplied method name exists in org.jackaudio.JackConfigure,
  2242. * if it does execute it and return TRUE. Otherwise return FALSE.
  2243. */
  2244. bool
  2245. jack_dbus_run_method(
  2246. struct jack_dbus_method_call *call,
  2247. const struct jack_dbus_interface_method_descriptor * methods)
  2248. {
  2249. const struct jack_dbus_interface_method_descriptor * method_ptr;
  2250. method_ptr = methods;
  2251. while (method_ptr->name != NULL)
  2252. {
  2253. if (strcmp(call->method_name, method_ptr->name) == 0)
  2254. {
  2255. method_ptr->handler(call);
  2256. return TRUE;
  2257. }
  2258. method_ptr++;
  2259. }
  2260. return FALSE;
  2261. }
  2262. /*
  2263. * Read arguments from a method call.
  2264. * If the operation fails construct an error and return false,
  2265. * otherwise return true.
  2266. */
  2267. bool
  2268. jack_dbus_get_method_args(
  2269. struct jack_dbus_method_call *call,
  2270. int type,
  2271. ...)
  2272. {
  2273. va_list args;
  2274. DBusError error;
  2275. bool retval = true;
  2276. va_start (args, type);
  2277. dbus_error_init (&error);
  2278. if (!dbus_message_get_args_valist (call->message, &error, type, args))
  2279. {
  2280. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  2281. "Invalid arguments to method \"%s\"",
  2282. call->method_name);
  2283. retval = false;
  2284. }
  2285. dbus_error_free (&error);
  2286. va_end (args);
  2287. return retval;
  2288. }
  2289. /*
  2290. * Read a string and a variant argument from a method call.
  2291. * If the operation fails construct an error and return false,
  2292. * otherwise return true.
  2293. */
  2294. bool
  2295. jack_dbus_get_method_args_string_and_variant(
  2296. struct jack_dbus_method_call *call,
  2297. const char **arg1,
  2298. message_arg_t *arg2,
  2299. int *type_ptr)
  2300. {
  2301. DBusMessageIter iter, sub_iter;
  2302. /* First we want a string... */
  2303. if (dbus_message_iter_init (call->message, &iter)
  2304. && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
  2305. {
  2306. dbus_message_iter_get_basic (&iter, arg1);
  2307. dbus_message_iter_next (&iter);
  2308. /* ...and then a variant. */
  2309. if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT)
  2310. {
  2311. dbus_message_iter_recurse (&iter, &sub_iter);
  2312. dbus_message_iter_get_basic (&sub_iter, arg2);
  2313. *type_ptr = dbus_message_iter_get_arg_type (&sub_iter);
  2314. /* Got what we wanted. */
  2315. return true;
  2316. }
  2317. }
  2318. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  2319. "Invalid arguments to method \"%s\"",
  2320. call->method_name);
  2321. return false;
  2322. }
  2323. /*
  2324. * Append a variant type to a D-Bus message.
  2325. * Return false if something fails, true otherwise.
  2326. */
  2327. bool
  2328. jack_dbus_message_append_variant(
  2329. DBusMessageIter *iter,
  2330. int type,
  2331. const char *signature,
  2332. message_arg_t *arg)
  2333. {
  2334. DBusMessageIter sub_iter;
  2335. /* Open a variant container. */
  2336. if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter))
  2337. {
  2338. goto fail;
  2339. }
  2340. /* Append the supplied value. */
  2341. if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg))
  2342. {
  2343. dbus_message_iter_close_container (iter, &sub_iter);
  2344. goto fail;
  2345. }
  2346. /* Close the container. */
  2347. if (!dbus_message_iter_close_container (iter, &sub_iter))
  2348. {
  2349. goto fail;
  2350. }
  2351. return true;
  2352. fail:
  2353. return false;
  2354. }
  2355. /*
  2356. * Construct an empty method return message.
  2357. *
  2358. * The operation can only fail due to lack of memory, in which case
  2359. * there's no sense in trying to construct an error return. Instead,
  2360. * call->reply will be set to NULL and handled in send_method_return().
  2361. */
  2362. void
  2363. jack_dbus_construct_method_return_empty(
  2364. struct jack_dbus_method_call * call)
  2365. {
  2366. call->reply = dbus_message_new_method_return (call->message);
  2367. if (call->reply == NULL)
  2368. {
  2369. jack_error ("Ran out of memory trying to construct method return");
  2370. }
  2371. }
  2372. /*
  2373. * Construct a method return which holds a single argument or, if
  2374. * the type parameter is DBUS_TYPE_INVALID, no arguments at all
  2375. * (a void message).
  2376. *
  2377. * The operation can only fail due to lack of memory, in which case
  2378. * there's no sense in trying to construct an error return. Instead,
  2379. * call->reply will be set to NULL and handled in send_method_return().
  2380. */
  2381. void
  2382. jack_dbus_construct_method_return_single(
  2383. struct jack_dbus_method_call *call,
  2384. int type,
  2385. message_arg_t arg)
  2386. {
  2387. DBusMessageIter iter;
  2388. call->reply = dbus_message_new_method_return (call->message);
  2389. if (call->reply == NULL)
  2390. {
  2391. goto fail_no_mem;
  2392. }
  2393. /* Void method return requested by caller. */
  2394. if (type == DBUS_TYPE_INVALID)
  2395. {
  2396. return;
  2397. }
  2398. /* Prevent crash on NULL input string. */
  2399. else if (type == DBUS_TYPE_STRING && arg.string == NULL)
  2400. {
  2401. arg.string = "";
  2402. }
  2403. dbus_message_iter_init_append (call->reply, &iter);
  2404. if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg))
  2405. {
  2406. dbus_message_unref (call->reply);
  2407. call->reply = NULL;
  2408. goto fail_no_mem;
  2409. }
  2410. return;
  2411. fail_no_mem:
  2412. jack_error ("Ran out of memory trying to construct method return");
  2413. }
  2414. /*
  2415. * Construct a method return which holds an array of strings.
  2416. *
  2417. * The operation can only fail due to lack of memory, in which case
  2418. * there's no sense in trying to construct an error return. Instead,
  2419. * call->reply will be set to NULL and handled in send_method_return().
  2420. */
  2421. void
  2422. jack_dbus_construct_method_return_array_of_strings(
  2423. struct jack_dbus_method_call *call,
  2424. unsigned int num_members,
  2425. const char **array)
  2426. {
  2427. DBusMessageIter iter, sub_iter;
  2428. unsigned int i;
  2429. call->reply = dbus_message_new_method_return (call->message);
  2430. if (!call->reply)
  2431. {
  2432. goto fail;
  2433. }
  2434. dbus_message_iter_init_append (call->reply, &iter);
  2435. if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
  2436. {
  2437. goto fail_unref;
  2438. }
  2439. for (i = 0; i < num_members; ++i)
  2440. {
  2441. if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i]))
  2442. {
  2443. dbus_message_iter_close_container (&iter, &sub_iter);
  2444. goto fail_unref;
  2445. }
  2446. }
  2447. if (!dbus_message_iter_close_container (&iter, &sub_iter))
  2448. {
  2449. goto fail_unref;
  2450. }
  2451. return;
  2452. fail_unref:
  2453. dbus_message_unref (call->reply);
  2454. call->reply = NULL;
  2455. fail:
  2456. jack_error ("Ran out of memory trying to construct method return");
  2457. }
  2458. void
  2459. jack_dbus_info_callback(const char *msg)
  2460. {
  2461. time_t timestamp;
  2462. char timestamp_str[26];
  2463. time(&timestamp);
  2464. ctime_r(&timestamp, timestamp_str);
  2465. timestamp_str[24] = 0;
  2466. fprintf(g_logfile, "%s: %s\n", timestamp_str, msg);
  2467. fflush(g_logfile);
  2468. }
  2469. void
  2470. jack_dbus_error_callback(const char *msg)
  2471. {
  2472. time_t timestamp;
  2473. char timestamp_str[26];
  2474. time(&timestamp);
  2475. ctime_r(&timestamp, timestamp_str);
  2476. timestamp_str[24] = 0;
  2477. fprintf(g_logfile, "%s: ERROR: %s\n", timestamp_str, msg);
  2478. fflush(g_logfile);
  2479. }
  2480. bool
  2481. ensure_dir_exist(const char *dirname, int mode)
  2482. {
  2483. struct stat st;
  2484. if (stat(dirname, &st) != 0)
  2485. {
  2486. if (errno == ENOENT)
  2487. {
  2488. printf("Directory \"%s\" does not exist. Creating...\n", dirname);
  2489. if (mkdir(dirname, mode) != 0)
  2490. {
  2491. fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno));
  2492. return false;
  2493. }
  2494. }
  2495. else
  2496. {
  2497. fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno));
  2498. return false;
  2499. }
  2500. }
  2501. else
  2502. {
  2503. if (!S_ISDIR(st.st_mode))
  2504. {
  2505. fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname);
  2506. return false;
  2507. }
  2508. }
  2509. return true;
  2510. }
  2511. char *
  2512. pathname_cat(const char *pathname_a, const char *pathname_b)
  2513. {
  2514. char *pathname;
  2515. int pathname_a_len, pathname_b_len, pathname_len;
  2516. pathname_a_len = strlen(pathname_a);
  2517. pathname_b_len = strlen(pathname_b);
  2518. pathname = malloc(pathname_a_len + pathname_b_len + 1);
  2519. if (pathname == NULL)
  2520. {
  2521. fprintf(stderr, "Out of memory\n");
  2522. return NULL;
  2523. }
  2524. memcpy(pathname, pathname_a, pathname_a_len);
  2525. memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len);
  2526. pathname_len = pathname_a_len + pathname_b_len;
  2527. pathname[pathname_len] = 0;
  2528. return pathname;
  2529. }
  2530. bool
  2531. paths_init()
  2532. {
  2533. const char *home_dir, *xdg_config_home, *xdg_log_home;
  2534. home_dir = getenv("HOME");
  2535. if (home_dir == NULL)
  2536. {
  2537. fprintf(stderr, "Environment variable HOME not set\n");
  2538. goto fail;
  2539. }
  2540. xdg_config_home = getenv("XDG_CONFIG_HOME");
  2541. if (xdg_config_home == NULL)
  2542. {
  2543. if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail;
  2544. }
  2545. if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail;
  2546. if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail;
  2547. if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail;
  2548. if (!ensure_dir_exist(xdg_config_home, 0700))
  2549. {
  2550. goto fail;
  2551. }
  2552. if (!ensure_dir_exist(xdg_log_home, 0700))
  2553. {
  2554. goto fail;
  2555. }
  2556. if (!ensure_dir_exist(g_jackdbus_config_dir, 0700))
  2557. {
  2558. free(g_jackdbus_config_dir);
  2559. goto fail;
  2560. }
  2561. g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir);
  2562. if (!ensure_dir_exist(g_jackdbus_log_dir, 0700))
  2563. {
  2564. free(g_jackdbus_log_dir);
  2565. goto fail;
  2566. }
  2567. g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir);
  2568. return true;
  2569. fail:
  2570. return false;
  2571. }
  2572. void
  2573. paths_uninit()
  2574. {
  2575. free(g_jackdbus_config_dir);
  2576. free(g_jackdbus_log_dir);
  2577. }
  2578. int
  2579. log_init()
  2580. {
  2581. char *log_filename;
  2582. size_t log_len;
  2583. log_len = strlen(JACKDBUS_LOG);
  2584. log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1);
  2585. if (log_filename == NULL)
  2586. {
  2587. fprintf(stderr, "Out of memory\n");
  2588. return FALSE;
  2589. }
  2590. memcpy(log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len);
  2591. memcpy(log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len);
  2592. log_filename[g_jackdbus_log_dir_len + log_len] = 0;
  2593. g_logfile = fopen(log_filename, "a");
  2594. if (g_logfile == NULL)
  2595. {
  2596. fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno));
  2597. free(log_filename);
  2598. return FALSE;
  2599. }
  2600. free(log_filename);
  2601. return TRUE;
  2602. }
  2603. void
  2604. log_uninit()
  2605. {
  2606. fclose(g_logfile);
  2607. }
  2608. void
  2609. jack_dbus_error(
  2610. void *dbus_call_context_ptr,
  2611. const char *error_name,
  2612. const char *format,
  2613. ...)
  2614. {
  2615. va_list ap;
  2616. char buffer[300];
  2617. va_start(ap, format);
  2618. vsnprintf(buffer, sizeof(buffer), format, ap);
  2619. jack_error_callback(buffer);
  2620. if (dbus_call_context_ptr != NULL)
  2621. {
  2622. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error(
  2623. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message,
  2624. error_name,
  2625. buffer);
  2626. }
  2627. va_end(ap);
  2628. }
  2629. int
  2630. main (int argc, char **argv)
  2631. {
  2632. DBusError error;
  2633. int ret;
  2634. void *controller_ptr;
  2635. if (!jack_controller_settings_init())
  2636. {
  2637. ret = 1;
  2638. goto fail;
  2639. }
  2640. if (argc != 2 || strcmp(argv[1], "auto") != 0)
  2641. {
  2642. ret = 0;
  2643. fprintf(
  2644. stderr,
  2645. "jackdbus should be auto-executed by D-Bus message bus daemon.\n"
  2646. "If you want to run it manually anyway, specify \"auto\" as only parameter\n");
  2647. goto fail_uninit_xml;
  2648. }
  2649. if (!paths_init())
  2650. {
  2651. ret = 1;
  2652. goto fail_uninit_xml;
  2653. }
  2654. if (!log_init())
  2655. {
  2656. ret = 1;
  2657. goto fail_uninit_paths;
  2658. }
  2659. #if !defined(DISABLE_SIGNAL_MAGIC)
  2660. jackctl_setup_signals(0);
  2661. #endif
  2662. jack_set_error_function(jack_dbus_error_callback);
  2663. jack_set_info_function(jack_dbus_info_callback);
  2664. jack_info("------------------");
  2665. jack_info("Controller activated. Version %s (%s)", jack_get_version_string(), JACK_SVNREVISION);
  2666. if (!dbus_threads_init_default())
  2667. {
  2668. jack_error("dbus_threads_init_default() failed");
  2669. ret = 1;
  2670. goto fail_uninit_log;
  2671. }
  2672. dbus_error_init (&error);
  2673. g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
  2674. if (dbus_error_is_set (&error))
  2675. {
  2676. jack_error("Cannot connect to D-Bus session bus: %s", error.message);
  2677. ret = 1;
  2678. goto fail_uninit_log;
  2679. }
  2680. ret = dbus_bus_request_name(
  2681. g_connection,
  2682. "org.jackaudio.service",
  2683. DBUS_NAME_FLAG_DO_NOT_QUEUE,
  2684. &error);
  2685. if (ret == -1)
  2686. {
  2687. jack_error("Cannot request service name: %s", error.message);
  2688. dbus_error_free(&error);
  2689. ret = 1;
  2690. goto fail_unref_connection;
  2691. }
  2692. else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
  2693. {
  2694. jack_error("Requested D-Bus service name already exists");
  2695. ret = 1;
  2696. goto fail_unref_connection;
  2697. }
  2698. controller_ptr = jack_controller_create(g_connection);
  2699. if (controller_ptr == NULL)
  2700. {
  2701. ret = 1;
  2702. goto fail_unref_connection;
  2703. }
  2704. jack_info("Listening for D-Bus messages");
  2705. g_exit_command = FALSE;
  2706. while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200));
  2707. jack_controller_destroy(controller_ptr);
  2708. jack_info("Controller deactivated.");
  2709. ret = 0;
  2710. fail_unref_connection:
  2711. dbus_connection_unref(g_connection);
  2712. fail_uninit_log:
  2713. log_uninit();
  2714. fail_uninit_paths:
  2715. paths_uninit();
  2716. fail_uninit_xml:
  2717. jack_controller_settings_uninit();
  2718. fail:
  2719. return ret;
  2720. }