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.

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