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.

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