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.

976 lines
24KB

  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
  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. #if defined(HAVE_CONFIG_H)
  18. #include "config.h"
  19. #endif
  20. #include <stdbool.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <sys/stat.h>
  26. #include <signal.h>
  27. #include <dbus/dbus.h>
  28. #include <pthread.h>
  29. #include <unistd.h>
  30. #include "config.h"
  31. #include "jackdbus.h"
  32. #include "controller.h"
  33. #include "jack/jack.h"
  34. #include "jack/jslist.h"
  35. #include "jack/control.h"
  36. #include "sigsegv.h"
  37. static char * g_log_filename;
  38. static ino_t g_log_file_ino;
  39. FILE *g_logfile;
  40. char *g_jackdbus_config_dir;
  41. size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */
  42. char *g_jackdbus_log_dir;
  43. size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */
  44. int g_exit_command;
  45. DBusConnection *g_connection;
  46. void
  47. jack_dbus_send_signal(
  48. const char *sender_object_path,
  49. const char *iface,
  50. const char *signal_name,
  51. int first_arg_type,
  52. ...)
  53. {
  54. DBusMessage *message_ptr;
  55. va_list ap;
  56. va_start(ap, first_arg_type);
  57. message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name);
  58. if (message_ptr == NULL)
  59. {
  60. jack_error("dbus_message_new_signal() failed.");
  61. goto exit;
  62. }
  63. if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap))
  64. {
  65. jack_error("dbus_message_append_args_valist() failed.");
  66. goto unref;
  67. }
  68. /* Add message to outgoing message queue */
  69. if (!dbus_connection_send(g_connection, message_ptr, NULL))
  70. {
  71. jack_error("dbus_connection_send() failed.");
  72. goto unref;
  73. }
  74. unref:
  75. dbus_message_unref(message_ptr);
  76. exit:
  77. va_end(ap);
  78. }
  79. /*
  80. * Send a method return.
  81. *
  82. * If call->reply is NULL (i.e. a message construct method failed
  83. * due to lack of memory) attempt to send a void method return.
  84. */
  85. static
  86. void
  87. jack_dbus_send_method_return(
  88. struct jack_dbus_method_call * call)
  89. {
  90. if (call->message == NULL)
  91. {
  92. /* async call */
  93. return;
  94. }
  95. if (call->reply)
  96. {
  97. retry_send:
  98. if (!dbus_connection_send (call->connection, call->reply, NULL))
  99. {
  100. jack_error ("Ran out of memory trying to queue method return");
  101. }
  102. dbus_connection_flush (call->connection);
  103. dbus_message_unref (call->reply);
  104. call->reply = NULL;
  105. }
  106. else
  107. {
  108. jack_error ("send_method_return() called with a NULL message,"
  109. " trying to construct a void return...");
  110. if ((call->reply = dbus_message_new_method_return (call->message)))
  111. {
  112. goto retry_send;
  113. }
  114. else
  115. {
  116. jack_error ("Failed to construct method return!");
  117. }
  118. }
  119. }
  120. #define object_ptr ((struct jack_dbus_object_descriptor *)data)
  121. /*
  122. * The D-Bus message handler for object path /org/jackaudio/Controller.
  123. */
  124. DBusHandlerResult
  125. jack_dbus_message_handler(
  126. DBusConnection *connection,
  127. DBusMessage *message,
  128. void *data)
  129. {
  130. struct jack_dbus_method_call call;
  131. const char *interface_name;
  132. struct jack_dbus_interface_descriptor ** interface_ptr_ptr;
  133. /* Check if the message is a method call. If not, ignore it. */
  134. if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
  135. {
  136. goto handled;
  137. }
  138. /* Get the invoked method's name and make sure it's non-NULL. */
  139. if (!(call.method_name = dbus_message_get_member (message)))
  140. {
  141. jack_dbus_error(
  142. &call,
  143. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  144. "Received method call with empty method name");
  145. goto send_return;
  146. }
  147. /* Initialize our data. */
  148. call.context = object_ptr->context;
  149. call.connection = connection;
  150. call.message = message;
  151. call.reply = NULL;
  152. /* Check if there's an interface specified for this method call. */
  153. interface_name = dbus_message_get_interface (message);
  154. if (interface_name != NULL)
  155. {
  156. /* Check if we can match the interface and method.
  157. * The interface handler functions only return false if the
  158. * method name was unknown, otherwise they run the specified
  159. * method and return TRUE.
  160. */
  161. interface_ptr_ptr = object_ptr->interfaces;
  162. while (*interface_ptr_ptr != NULL)
  163. {
  164. if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0)
  165. {
  166. if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  167. {
  168. break;
  169. }
  170. goto send_return;
  171. }
  172. interface_ptr_ptr++;
  173. }
  174. }
  175. else
  176. {
  177. /* No interface was specified so we have to try them all. This is
  178. * dictated by the D-Bus specification which states that method calls
  179. * omitting the interface must never be rejected.
  180. */
  181. interface_ptr_ptr = object_ptr->interfaces;
  182. while (*interface_ptr_ptr != NULL)
  183. {
  184. if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods))
  185. {
  186. goto send_return;
  187. }
  188. interface_ptr_ptr++;
  189. }
  190. }
  191. jack_dbus_error(
  192. &call,
  193. JACK_DBUS_ERROR_UNKNOWN_METHOD,
  194. "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
  195. call.method_name,
  196. dbus_message_get_signature(message),
  197. interface_name);
  198. send_return:
  199. jack_dbus_send_method_return(&call);
  200. handled:
  201. return DBUS_HANDLER_RESULT_HANDLED;
  202. }
  203. void
  204. jack_dbus_message_handler_unregister(
  205. DBusConnection *connection,
  206. void *data)
  207. {
  208. jack_info ("Message handler was unregistered");
  209. }
  210. #undef object_ptr
  211. /*
  212. * Check if the supplied method name exists in org.jackaudio.JackConfigure,
  213. * if it does execute it and return TRUE. Otherwise return FALSE.
  214. */
  215. bool
  216. jack_dbus_run_method(
  217. struct jack_dbus_method_call *call,
  218. const struct jack_dbus_interface_method_descriptor * methods)
  219. {
  220. const struct jack_dbus_interface_method_descriptor * method_ptr;
  221. method_ptr = methods;
  222. while (method_ptr->name != NULL)
  223. {
  224. if (strcmp(call->method_name, method_ptr->name) == 0)
  225. {
  226. method_ptr->handler(call);
  227. return TRUE;
  228. }
  229. method_ptr++;
  230. }
  231. return FALSE;
  232. }
  233. /*
  234. * Read arguments from a method call.
  235. * If the operation fails construct an error and return false,
  236. * otherwise return true.
  237. */
  238. bool
  239. jack_dbus_get_method_args(
  240. struct jack_dbus_method_call *call,
  241. int type,
  242. ...)
  243. {
  244. va_list args;
  245. DBusError error;
  246. bool retval = true;
  247. va_start (args, type);
  248. dbus_error_init (&error);
  249. if (!dbus_message_get_args_valist (call->message, &error, type, args))
  250. {
  251. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  252. "Invalid arguments to method \"%s\"",
  253. call->method_name);
  254. retval = false;
  255. }
  256. dbus_error_free (&error);
  257. va_end (args);
  258. return retval;
  259. }
  260. /*
  261. * Read a string and a variant argument from a method call.
  262. * If the operation fails construct an error and return false,
  263. * otherwise return true.
  264. */
  265. bool
  266. jack_dbus_get_method_args_string_and_variant(
  267. struct jack_dbus_method_call *call,
  268. const char **arg1,
  269. message_arg_t *arg2,
  270. int *type_ptr)
  271. {
  272. DBusMessageIter iter, sub_iter;
  273. /* First we want a string... */
  274. if (dbus_message_iter_init (call->message, &iter)
  275. && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
  276. {
  277. dbus_message_iter_get_basic (&iter, arg1);
  278. dbus_message_iter_next (&iter);
  279. /* ...and then a variant. */
  280. if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT)
  281. {
  282. dbus_message_iter_recurse (&iter, &sub_iter);
  283. dbus_message_iter_get_basic (&sub_iter, arg2);
  284. *type_ptr = dbus_message_iter_get_arg_type (&sub_iter);
  285. /* Got what we wanted. */
  286. return true;
  287. }
  288. }
  289. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  290. "Invalid arguments to method \"%s\"",
  291. call->method_name);
  292. return false;
  293. }
  294. /*
  295. * Read two strings and a variant argument from a method call.
  296. * If the operation fails construct an error and return false,
  297. * otherwise return true.
  298. */
  299. bool
  300. jack_dbus_get_method_args_two_strings_and_variant(
  301. struct jack_dbus_method_call *call,
  302. const char **arg1,
  303. const char **arg2,
  304. message_arg_t *arg3,
  305. int *type_ptr)
  306. {
  307. DBusMessageIter iter, sub_iter;
  308. /* First we want a string... */
  309. if (dbus_message_iter_init (call->message, &iter)
  310. && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
  311. {
  312. dbus_message_iter_get_basic (&iter, arg1);
  313. dbus_message_iter_next (&iter);
  314. /* ...and then a second string. */
  315. if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
  316. {
  317. return false;
  318. }
  319. /* Got what we wanted. */
  320. dbus_message_iter_get_basic (&iter, arg2);
  321. dbus_message_iter_next (&iter);
  322. /* ...and then a variant. */
  323. if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT)
  324. {
  325. dbus_message_iter_recurse (&iter, &sub_iter);
  326. dbus_message_iter_get_basic (&sub_iter, arg3);
  327. *type_ptr = dbus_message_iter_get_arg_type (&sub_iter);
  328. /* Got what we wanted. */
  329. return true;
  330. }
  331. }
  332. jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS,
  333. "Invalid arguments to method \"%s\"",
  334. call->method_name);
  335. return false;
  336. }
  337. /*
  338. * Append a variant type to a D-Bus message.
  339. * Return false if something fails, true otherwise.
  340. */
  341. bool
  342. jack_dbus_message_append_variant(
  343. DBusMessageIter *iter,
  344. int type,
  345. const char *signature,
  346. message_arg_t *arg)
  347. {
  348. DBusMessageIter sub_iter;
  349. /* Open a variant container. */
  350. if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter))
  351. {
  352. goto fail;
  353. }
  354. /* Append the supplied value. */
  355. if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg))
  356. {
  357. dbus_message_iter_close_container (iter, &sub_iter);
  358. goto fail;
  359. }
  360. /* Close the container. */
  361. if (!dbus_message_iter_close_container (iter, &sub_iter))
  362. {
  363. goto fail;
  364. }
  365. return true;
  366. fail:
  367. return false;
  368. }
  369. /*
  370. * Construct an empty method return message.
  371. *
  372. * The operation can only fail due to lack of memory, in which case
  373. * there's no sense in trying to construct an error return. Instead,
  374. * call->reply will be set to NULL and handled in send_method_return().
  375. */
  376. void
  377. jack_dbus_construct_method_return_empty(
  378. struct jack_dbus_method_call * call)
  379. {
  380. call->reply = dbus_message_new_method_return (call->message);
  381. if (call->reply == NULL)
  382. {
  383. jack_error ("Ran out of memory trying to construct method return");
  384. }
  385. }
  386. /*
  387. * Construct a method return which holds a single argument or, if
  388. * the type parameter is DBUS_TYPE_INVALID, no arguments at all
  389. * (a void message).
  390. *
  391. * The operation can only fail due to lack of memory, in which case
  392. * there's no sense in trying to construct an error return. Instead,
  393. * call->reply will be set to NULL and handled in send_method_return().
  394. */
  395. void
  396. jack_dbus_construct_method_return_single(
  397. struct jack_dbus_method_call *call,
  398. int type,
  399. message_arg_t arg)
  400. {
  401. DBusMessageIter iter;
  402. call->reply = dbus_message_new_method_return (call->message);
  403. if (call->reply == NULL)
  404. {
  405. goto fail_no_mem;
  406. }
  407. /* Void method return requested by caller. */
  408. if (type == DBUS_TYPE_INVALID)
  409. {
  410. return;
  411. }
  412. /* Prevent crash on NULL input string. */
  413. else if (type == DBUS_TYPE_STRING && arg.string == NULL)
  414. {
  415. arg.string = "";
  416. }
  417. dbus_message_iter_init_append (call->reply, &iter);
  418. if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg))
  419. {
  420. dbus_message_unref (call->reply);
  421. call->reply = NULL;
  422. goto fail_no_mem;
  423. }
  424. return;
  425. fail_no_mem:
  426. jack_error ("Ran out of memory trying to construct method return");
  427. }
  428. /*
  429. * Construct a method return which holds an array of strings.
  430. *
  431. * The operation can only fail due to lack of memory, in which case
  432. * there's no sense in trying to construct an error return. Instead,
  433. * call->reply will be set to NULL and handled in send_method_return().
  434. */
  435. void
  436. jack_dbus_construct_method_return_array_of_strings(
  437. struct jack_dbus_method_call *call,
  438. unsigned int num_members,
  439. const char **array)
  440. {
  441. DBusMessageIter iter, sub_iter;
  442. unsigned int i;
  443. call->reply = dbus_message_new_method_return (call->message);
  444. if (!call->reply)
  445. {
  446. goto fail;
  447. }
  448. dbus_message_iter_init_append (call->reply, &iter);
  449. if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
  450. {
  451. goto fail_unref;
  452. }
  453. for (i = 0; i < num_members; ++i)
  454. {
  455. if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i]))
  456. {
  457. dbus_message_iter_close_container (&iter, &sub_iter);
  458. goto fail_unref;
  459. }
  460. }
  461. if (!dbus_message_iter_close_container (&iter, &sub_iter))
  462. {
  463. goto fail_unref;
  464. }
  465. return;
  466. fail_unref:
  467. dbus_message_unref (call->reply);
  468. call->reply = NULL;
  469. fail:
  470. jack_error ("Ran out of memory trying to construct method return");
  471. }
  472. static bool jack_dbus_log_open(void)
  473. {
  474. struct stat st;
  475. int ret;
  476. int retry;
  477. if (g_logfile != NULL)
  478. {
  479. ret = stat(g_log_filename, &st);
  480. if (ret != 0 || g_log_file_ino != st.st_ino)
  481. {
  482. fclose(g_logfile);
  483. }
  484. else
  485. {
  486. return true;
  487. }
  488. }
  489. for (retry = 0; retry < 10; retry++)
  490. {
  491. g_logfile = fopen(g_log_filename, "a");
  492. if (g_logfile == NULL)
  493. {
  494. fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", g_log_filename, errno, strerror(errno));
  495. return false;
  496. }
  497. ret = stat(g_log_filename, &st);
  498. if (ret == 0)
  499. {
  500. g_log_file_ino = st.st_ino;
  501. return true;
  502. }
  503. fclose(g_logfile);
  504. g_logfile = NULL;
  505. }
  506. fprintf(stderr, "Cannot stat just opened jackdbus log file \"%s\": %d (%s). %d retries\n", g_log_filename, errno, strerror(errno), retry);
  507. return false;
  508. }
  509. void
  510. jack_dbus_info_callback(const char *msg)
  511. {
  512. time_t timestamp;
  513. char timestamp_str[26];
  514. time(&timestamp);
  515. ctime_r(&timestamp, timestamp_str);
  516. timestamp_str[24] = 0;
  517. if (jack_dbus_log_open())
  518. {
  519. fprintf(g_logfile, "%s: %s\n", timestamp_str, msg);
  520. fflush(g_logfile);
  521. }
  522. }
  523. #define ANSI_BOLD_ON "\033[1m"
  524. #define ANSI_BOLD_OFF "\033[22m"
  525. #define ANSI_COLOR_RED "\033[31m"
  526. #define ANSI_RESET "\033[0m"
  527. void
  528. jack_dbus_error_callback(const char *msg)
  529. {
  530. time_t timestamp;
  531. char timestamp_str[26];
  532. time(&timestamp);
  533. ctime_r(&timestamp, timestamp_str);
  534. timestamp_str[24] = 0;
  535. if (jack_dbus_log_open())
  536. {
  537. fprintf(g_logfile, "%s: " ANSI_BOLD_ON ANSI_COLOR_RED "ERROR: %s" ANSI_RESET "\n", timestamp_str, msg);
  538. fflush(g_logfile);
  539. }
  540. }
  541. bool
  542. ensure_dir_exist(const char *dirname, int mode)
  543. {
  544. struct stat st;
  545. if (stat(dirname, &st) != 0)
  546. {
  547. if (errno == ENOENT)
  548. {
  549. printf("Directory \"%s\" does not exist. Creating...\n", dirname);
  550. if (mkdir(dirname, mode) != 0)
  551. {
  552. fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno));
  553. return false;
  554. }
  555. }
  556. else
  557. {
  558. fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno));
  559. return false;
  560. }
  561. }
  562. else
  563. {
  564. if (!S_ISDIR(st.st_mode))
  565. {
  566. fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname);
  567. return false;
  568. }
  569. }
  570. return true;
  571. }
  572. char *
  573. pathname_cat(const char *pathname_a, const char *pathname_b)
  574. {
  575. char *pathname;
  576. int pathname_a_len, pathname_b_len, pathname_len;
  577. pathname_a_len = strlen(pathname_a);
  578. pathname_b_len = strlen(pathname_b);
  579. pathname = malloc(pathname_a_len + pathname_b_len + 1);
  580. if (pathname == NULL)
  581. {
  582. fprintf(stderr, "Out of memory\n");
  583. return NULL;
  584. }
  585. memcpy(pathname, pathname_a, pathname_a_len);
  586. memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len);
  587. pathname_len = pathname_a_len + pathname_b_len;
  588. pathname[pathname_len] = 0;
  589. return pathname;
  590. }
  591. bool
  592. paths_init()
  593. {
  594. const char *home_dir, *xdg_config_home, *xdg_log_home;
  595. home_dir = getenv("HOME");
  596. if (home_dir == NULL)
  597. {
  598. fprintf(stderr, "Environment variable HOME not set\n");
  599. goto fail;
  600. }
  601. xdg_config_home = getenv("XDG_CONFIG_HOME");
  602. if (xdg_config_home == NULL)
  603. {
  604. if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail;
  605. }
  606. if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail;
  607. if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail;
  608. if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail;
  609. if (!ensure_dir_exist(xdg_config_home, 0700))
  610. {
  611. goto fail;
  612. }
  613. if (!ensure_dir_exist(xdg_log_home, 0700))
  614. {
  615. goto fail;
  616. }
  617. if (!ensure_dir_exist(g_jackdbus_config_dir, 0700))
  618. {
  619. free(g_jackdbus_config_dir);
  620. goto fail;
  621. }
  622. g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir);
  623. if (!ensure_dir_exist(g_jackdbus_log_dir, 0700))
  624. {
  625. free(g_jackdbus_log_dir);
  626. goto fail;
  627. }
  628. g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir);
  629. return true;
  630. fail:
  631. return false;
  632. }
  633. void
  634. paths_uninit()
  635. {
  636. free(g_jackdbus_config_dir);
  637. free(g_jackdbus_log_dir);
  638. }
  639. static bool log_init(void)
  640. {
  641. size_t log_len;
  642. log_len = strlen(JACKDBUS_LOG);
  643. g_log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1);
  644. if (g_log_filename == NULL)
  645. {
  646. fprintf(stderr, "Out of memory\n");
  647. return false;
  648. }
  649. memcpy(g_log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len);
  650. memcpy(g_log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len);
  651. g_log_filename[g_jackdbus_log_dir_len + log_len] = 0;
  652. if (!jack_dbus_log_open())
  653. {
  654. return false;
  655. }
  656. return true;
  657. }
  658. static void log_uninit(void)
  659. {
  660. if (g_logfile != NULL)
  661. {
  662. fclose(g_logfile);
  663. }
  664. free(g_log_filename);
  665. }
  666. void
  667. jack_dbus_error(
  668. void *dbus_call_context_ptr,
  669. const char *error_name,
  670. const char *format,
  671. ...)
  672. {
  673. va_list ap;
  674. char buffer[300];
  675. va_start(ap, format);
  676. vsnprintf(buffer, sizeof(buffer), format, ap);
  677. jack_error_callback(buffer);
  678. if (dbus_call_context_ptr != NULL)
  679. {
  680. if (((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply != NULL)
  681. {
  682. dbus_message_unref(((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply);
  683. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = NULL;
  684. }
  685. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error(
  686. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message,
  687. error_name,
  688. buffer);
  689. }
  690. va_end(ap);
  691. }
  692. void
  693. jack_dbus_only_error(
  694. void *dbus_call_context_ptr,
  695. const char *error_name,
  696. const char *format,
  697. ...)
  698. {
  699. va_list ap;
  700. char buffer[300];
  701. va_start(ap, format);
  702. vsnprintf(buffer, sizeof(buffer), format, ap);
  703. if (((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply != NULL)
  704. {
  705. dbus_message_unref(((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply);
  706. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = NULL;
  707. }
  708. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error(
  709. ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message,
  710. error_name,
  711. buffer);
  712. va_end(ap);
  713. }
  714. int
  715. main (int argc, char **argv)
  716. {
  717. DBusError error;
  718. int ret;
  719. void *controller_ptr;
  720. struct stat st;
  721. char timestamp_str[26];
  722. st.st_mtime = 0;
  723. stat(argv[0], &st);
  724. ctime_r(&st.st_mtime, timestamp_str);
  725. timestamp_str[24] = 0;
  726. if (!jack_controller_settings_init())
  727. {
  728. ret = 1;
  729. goto fail;
  730. }
  731. if (argc != 2 || strcmp(argv[1], "auto") != 0)
  732. {
  733. ret = 0;
  734. fprintf(
  735. stderr,
  736. "jackdbus should be auto-executed by D-Bus message bus daemon.\n"
  737. "If you want to run it manually anyway, specify \"auto\" as only parameter\n");
  738. goto fail_uninit_xml;
  739. }
  740. if (!paths_init())
  741. {
  742. ret = 1;
  743. goto fail_uninit_xml;
  744. }
  745. if (!log_init())
  746. {
  747. ret = 1;
  748. goto fail_uninit_paths;
  749. }
  750. #if !defined(DISABLE_SIGNAL_MAGIC)
  751. jackctl_setup_signals(0);
  752. #endif
  753. jack_set_error_function(jack_dbus_error_callback);
  754. jack_set_info_function(jack_dbus_info_callback);
  755. /* setup our SIGSEGV magic that prints nice stack in our logfile */
  756. setup_sigsegv();
  757. jack_info("------------------");
  758. jack_info("Controller activated. Version %s (%s) built on %s", jack_get_version_string(), JACK_VERSION, timestamp_str);
  759. if (!dbus_threads_init_default())
  760. {
  761. jack_error("dbus_threads_init_default() failed");
  762. ret = 1;
  763. goto fail_uninit_log;
  764. }
  765. dbus_error_init (&error);
  766. g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
  767. if (dbus_error_is_set (&error))
  768. {
  769. jack_error("Cannot connect to D-Bus session bus: %s", error.message);
  770. ret = 1;
  771. goto fail_uninit_log;
  772. }
  773. ret = dbus_bus_request_name(
  774. g_connection,
  775. "org.jackaudio.service",
  776. DBUS_NAME_FLAG_DO_NOT_QUEUE,
  777. &error);
  778. if (ret == -1)
  779. {
  780. jack_error("Cannot request service name: %s", error.message);
  781. dbus_error_free(&error);
  782. ret = 1;
  783. goto fail_unref_connection;
  784. }
  785. else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
  786. {
  787. jack_error("Requested D-Bus service name already exists");
  788. ret = 1;
  789. goto fail_unref_connection;
  790. }
  791. controller_ptr = jack_controller_create(g_connection);
  792. if (controller_ptr == NULL)
  793. {
  794. ret = 1;
  795. goto fail_unref_connection;
  796. }
  797. jack_info("Listening for D-Bus messages");
  798. g_exit_command = FALSE;
  799. while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200))
  800. {
  801. jack_controller_run(controller_ptr);
  802. }
  803. jack_controller_destroy(controller_ptr);
  804. jack_info("Controller deactivated.");
  805. ret = 0;
  806. fail_unref_connection:
  807. dbus_connection_unref(g_connection);
  808. fail_uninit_log:
  809. log_uninit();
  810. fail_uninit_paths:
  811. paths_uninit();
  812. fail_uninit_xml:
  813. jack_controller_settings_uninit();
  814. fail:
  815. return ret;
  816. }