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.

1081 lines
26KB

  1. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  2. /*
  3. Copyright (C) 2007,2008 Nedko Arnaudov
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include <stdbool.h>
  16. #include <stdint.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <unistd.h>
  20. #include <fcntl.h>
  21. #include <errno.h>
  22. #include <string.h>
  23. #include <dbus/dbus.h>
  24. #include <time.h>
  25. #include "controller_internal.h"
  26. #include "jackdbus.h"
  27. bool
  28. jack_controller_settings_write_string(int fd, const char * string, void *dbus_call_context_ptr)
  29. {
  30. size_t len;
  31. len = strlen(string);
  32. if (write(fd, string, len) != len)
  33. {
  34. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "write() failed to write config file.");
  35. return false;
  36. }
  37. return true;
  38. }
  39. struct save_context
  40. {
  41. int fd;
  42. const char *indent;
  43. };
  44. #define save_context_ptr ((struct save_context *)context)
  45. #define fd (save_context_ptr->fd)
  46. bool
  47. jack_controller_settings_write_option(
  48. void *context,
  49. const char *name,
  50. const char *content,
  51. void *dbus_call_context_ptr)
  52. {
  53. if (!jack_controller_settings_write_string(fd, save_context_ptr->indent, dbus_call_context_ptr))
  54. {
  55. return false;
  56. }
  57. if (!jack_controller_settings_write_string(fd, "<option name=\"", dbus_call_context_ptr))
  58. {
  59. return false;
  60. }
  61. if (!jack_controller_settings_write_string(fd, name, dbus_call_context_ptr))
  62. {
  63. return false;
  64. }
  65. if (!jack_controller_settings_write_string(fd, "\">", dbus_call_context_ptr))
  66. {
  67. return false;
  68. }
  69. if (!jack_controller_settings_write_string(fd, content, dbus_call_context_ptr))
  70. {
  71. return false;
  72. }
  73. if (!jack_controller_settings_write_string(fd, "</option>\n", dbus_call_context_ptr))
  74. {
  75. return false;
  76. }
  77. return true;
  78. }
  79. #undef fd
  80. bool
  81. jack_controller_settings_save(
  82. struct jack_controller * controller_ptr,
  83. void *dbus_call_context_ptr)
  84. {
  85. char *filename;
  86. size_t conf_len;
  87. int fd;
  88. bool ret;
  89. time_t timestamp;
  90. char timestamp_str[26];
  91. struct save_context context;
  92. const JSList * node_ptr;
  93. jackctl_driver_t *driver;
  94. time(&timestamp);
  95. ctime_r(&timestamp, timestamp_str);
  96. timestamp_str[24] = 0;
  97. ret = false;
  98. conf_len = strlen(JACKDBUS_CONF);
  99. filename = malloc(g_jackdbus_config_dir_len + conf_len + 1);
  100. if (filename == NULL)
  101. {
  102. jack_error("Out of memory.");
  103. goto exit;
  104. }
  105. memcpy(filename, g_jackdbus_config_dir, g_jackdbus_config_dir_len);
  106. memcpy(filename + g_jackdbus_config_dir_len, JACKDBUS_CONF, conf_len);
  107. filename[g_jackdbus_config_dir_len + conf_len] = 0;
  108. jack_info("Saving settings to \"%s\" ...", filename);
  109. fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  110. if (fd == -1)
  111. {
  112. jack_error("open() failed to open conf filename. error is %d (%s)", errno, strerror(errno));
  113. goto exit_free_filename;
  114. }
  115. context.fd = fd;
  116. if (!jack_controller_settings_write_string(fd, "<?xml version=\"1.0\"?>\n", dbus_call_context_ptr))
  117. {
  118. goto exit_close;
  119. }
  120. if (!jack_controller_settings_write_string(fd, "<!--\n", dbus_call_context_ptr))
  121. {
  122. goto exit_close;
  123. }
  124. if (!jack_controller_settings_write_string(fd, JACK_CONF_HEADER_TEXT, dbus_call_context_ptr))
  125. {
  126. goto exit_close;
  127. }
  128. if (!jack_controller_settings_write_string(fd, "-->\n", dbus_call_context_ptr))
  129. {
  130. goto exit_close;
  131. }
  132. if (!jack_controller_settings_write_string(fd, "<!-- ", dbus_call_context_ptr))
  133. {
  134. goto exit_close;
  135. }
  136. if (!jack_controller_settings_write_string(fd, timestamp_str, dbus_call_context_ptr))
  137. {
  138. goto exit_close;
  139. }
  140. if (!jack_controller_settings_write_string(fd, " -->\n", dbus_call_context_ptr))
  141. {
  142. goto exit_close;
  143. }
  144. if (!jack_controller_settings_write_string(fd, "<jack>\n", dbus_call_context_ptr))
  145. {
  146. goto exit_close;
  147. }
  148. if (!jack_controller_settings_write_string(fd, " <engine>\n", dbus_call_context_ptr))
  149. {
  150. goto exit_close;
  151. }
  152. context.indent = " ";
  153. if (!jack_controller_settings_save_engine_options(&context, controller_ptr, dbus_call_context_ptr))
  154. {
  155. goto exit_close;
  156. }
  157. if (!jack_controller_settings_write_string(fd, " </engine>\n", dbus_call_context_ptr))
  158. {
  159. goto exit_close;
  160. }
  161. if (!jack_controller_settings_write_string(fd, " <drivers>\n", dbus_call_context_ptr))
  162. {
  163. goto exit_close;
  164. }
  165. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  166. while (node_ptr != NULL)
  167. {
  168. driver = (jackctl_driver_t *)node_ptr->data;
  169. if (!jack_controller_settings_write_string(fd, " <driver name=\"", dbus_call_context_ptr))
  170. {
  171. goto exit_close;
  172. }
  173. if (!jack_controller_settings_write_string(fd, jackctl_driver_get_name(driver), dbus_call_context_ptr))
  174. {
  175. goto exit_close;
  176. }
  177. if (!jack_controller_settings_write_string(fd, "\">\n", dbus_call_context_ptr))
  178. {
  179. goto exit_close;
  180. }
  181. context.indent = " ";
  182. if (!jack_controller_settings_save_driver_options(&context, driver, dbus_call_context_ptr))
  183. {
  184. goto exit_close;
  185. }
  186. if (!jack_controller_settings_write_string(fd, " </driver>\n", dbus_call_context_ptr))
  187. {
  188. goto exit_close;
  189. }
  190. node_ptr = jack_slist_next(node_ptr);
  191. }
  192. if (!jack_controller_settings_write_string(fd, " </drivers>\n", dbus_call_context_ptr))
  193. {
  194. goto exit_close;
  195. }
  196. if (!jack_controller_settings_write_string(fd, "</jack>\n", dbus_call_context_ptr))
  197. {
  198. goto exit_close;
  199. }
  200. ret = true;
  201. exit_close:
  202. close(fd);
  203. exit_free_filename:
  204. free(filename);
  205. exit:
  206. return ret;
  207. }
  208. void
  209. jack_controller_settings_save_auto(
  210. struct jack_controller * controller_ptr)
  211. {
  212. jack_controller_settings_save(controller_ptr, NULL);
  213. }
  214. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  215. /*
  216. Copyright (C) 2007,2008 Nedko Arnaudov
  217. This program is free software; you can redistribute it and/or modify
  218. it under the terms of the GNU General Public License as published by
  219. the Free Software Foundation; either version 2 of the License.
  220. This program is distributed in the hope that it will be useful,
  221. but WITHOUT ANY WARRANTY; without even the implied warranty of
  222. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  223. GNU General Public License for more details.
  224. You should have received a copy of the GNU General Public License
  225. along with this program; if not, write to the Free Software
  226. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  227. */
  228. #include <stdbool.h>
  229. #include <stdint.h>
  230. #include <sys/types.h>
  231. #include <sys/stat.h>
  232. #include <unistd.h>
  233. #include <fcntl.h>
  234. #include <errno.h>
  235. #include <string.h>
  236. #include <dbus/dbus.h>
  237. #include <time.h>
  238. #include "controller_internal.h"
  239. #include "jackdbus.h"
  240. bool
  241. jack_controller_settings_write_string(int fd, const char * string, void *dbus_call_context_ptr)
  242. {
  243. size_t len;
  244. len = strlen(string);
  245. if (write(fd, string, len) != len)
  246. {
  247. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "write() failed to write config file.");
  248. return false;
  249. }
  250. return true;
  251. }
  252. struct save_context
  253. {
  254. int fd;
  255. const char *indent;
  256. };
  257. #define save_context_ptr ((struct save_context *)context)
  258. #define fd (save_context_ptr->fd)
  259. bool
  260. jack_controller_settings_write_option(
  261. void *context,
  262. const char *name,
  263. const char *content,
  264. void *dbus_call_context_ptr)
  265. {
  266. if (!jack_controller_settings_write_string(fd, save_context_ptr->indent, dbus_call_context_ptr))
  267. {
  268. return false;
  269. }
  270. if (!jack_controller_settings_write_string(fd, "<option name=\"", dbus_call_context_ptr))
  271. {
  272. return false;
  273. }
  274. if (!jack_controller_settings_write_string(fd, name, dbus_call_context_ptr))
  275. {
  276. return false;
  277. }
  278. if (!jack_controller_settings_write_string(fd, "\">", dbus_call_context_ptr))
  279. {
  280. return false;
  281. }
  282. if (!jack_controller_settings_write_string(fd, content, dbus_call_context_ptr))
  283. {
  284. return false;
  285. }
  286. if (!jack_controller_settings_write_string(fd, "</option>\n", dbus_call_context_ptr))
  287. {
  288. return false;
  289. }
  290. return true;
  291. }
  292. #undef fd
  293. bool
  294. jack_controller_settings_save(
  295. struct jack_controller * controller_ptr,
  296. void *dbus_call_context_ptr)
  297. {
  298. char *filename;
  299. size_t conf_len;
  300. int fd;
  301. bool ret;
  302. time_t timestamp;
  303. char timestamp_str[26];
  304. struct save_context context;
  305. const JSList * node_ptr;
  306. jackctl_driver_t *driver;
  307. time(&timestamp);
  308. ctime_r(&timestamp, timestamp_str);
  309. timestamp_str[24] = 0;
  310. ret = false;
  311. conf_len = strlen(JACKDBUS_CONF);
  312. filename = malloc(g_jackdbus_config_dir_len + conf_len + 1);
  313. if (filename == NULL)
  314. {
  315. jack_error("Out of memory.");
  316. goto exit;
  317. }
  318. memcpy(filename, g_jackdbus_config_dir, g_jackdbus_config_dir_len);
  319. memcpy(filename + g_jackdbus_config_dir_len, JACKDBUS_CONF, conf_len);
  320. filename[g_jackdbus_config_dir_len + conf_len] = 0;
  321. jack_info("Saving settings to \"%s\" ...", filename);
  322. fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  323. if (fd == -1)
  324. {
  325. jack_error("open() failed to open conf filename. error is %d (%s)", errno, strerror(errno));
  326. goto exit_free_filename;
  327. }
  328. context.fd = fd;
  329. if (!jack_controller_settings_write_string(fd, "<?xml version=\"1.0\"?>\n", dbus_call_context_ptr))
  330. {
  331. goto exit_close;
  332. }
  333. if (!jack_controller_settings_write_string(fd, "<!--\n", dbus_call_context_ptr))
  334. {
  335. goto exit_close;
  336. }
  337. if (!jack_controller_settings_write_string(fd, JACK_CONF_HEADER_TEXT, dbus_call_context_ptr))
  338. {
  339. goto exit_close;
  340. }
  341. if (!jack_controller_settings_write_string(fd, "-->\n", dbus_call_context_ptr))
  342. {
  343. goto exit_close;
  344. }
  345. if (!jack_controller_settings_write_string(fd, "<!-- ", dbus_call_context_ptr))
  346. {
  347. goto exit_close;
  348. }
  349. if (!jack_controller_settings_write_string(fd, timestamp_str, dbus_call_context_ptr))
  350. {
  351. goto exit_close;
  352. }
  353. if (!jack_controller_settings_write_string(fd, " -->\n", dbus_call_context_ptr))
  354. {
  355. goto exit_close;
  356. }
  357. if (!jack_controller_settings_write_string(fd, "<jack>\n", dbus_call_context_ptr))
  358. {
  359. goto exit_close;
  360. }
  361. if (!jack_controller_settings_write_string(fd, " <engine>\n", dbus_call_context_ptr))
  362. {
  363. goto exit_close;
  364. }
  365. context.indent = " ";
  366. if (!jack_controller_settings_save_engine_options(&context, controller_ptr, dbus_call_context_ptr))
  367. {
  368. goto exit_close;
  369. }
  370. if (!jack_controller_settings_write_string(fd, " </engine>\n", dbus_call_context_ptr))
  371. {
  372. goto exit_close;
  373. }
  374. if (!jack_controller_settings_write_string(fd, " <drivers>\n", dbus_call_context_ptr))
  375. {
  376. goto exit_close;
  377. }
  378. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  379. while (node_ptr != NULL)
  380. {
  381. driver = (jackctl_driver_t *)node_ptr->data;
  382. if (!jack_controller_settings_write_string(fd, " <driver name=\"", dbus_call_context_ptr))
  383. {
  384. goto exit_close;
  385. }
  386. if (!jack_controller_settings_write_string(fd, jackctl_driver_get_name(driver), dbus_call_context_ptr))
  387. {
  388. goto exit_close;
  389. }
  390. if (!jack_controller_settings_write_string(fd, "\">\n", dbus_call_context_ptr))
  391. {
  392. goto exit_close;
  393. }
  394. context.indent = " ";
  395. if (!jack_controller_settings_save_driver_options(&context, driver, dbus_call_context_ptr))
  396. {
  397. goto exit_close;
  398. }
  399. if (!jack_controller_settings_write_string(fd, " </driver>\n", dbus_call_context_ptr))
  400. {
  401. goto exit_close;
  402. }
  403. node_ptr = jack_slist_next(node_ptr);
  404. }
  405. if (!jack_controller_settings_write_string(fd, " </drivers>\n", dbus_call_context_ptr))
  406. {
  407. goto exit_close;
  408. }
  409. if (!jack_controller_settings_write_string(fd, "</jack>\n", dbus_call_context_ptr))
  410. {
  411. goto exit_close;
  412. }
  413. ret = true;
  414. exit_close:
  415. close(fd);
  416. exit_free_filename:
  417. free(filename);
  418. exit:
  419. return ret;
  420. }
  421. void
  422. jack_controller_settings_save_auto(
  423. struct jack_controller * controller_ptr)
  424. {
  425. jack_controller_settings_save(controller_ptr, NULL);
  426. }
  427. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  428. /*
  429. Copyright (C) 2007,2008 Nedko Arnaudov
  430. This program is free software; you can redistribute it and/or modify
  431. it under the terms of the GNU General Public License as published by
  432. the Free Software Foundation; either version 2 of the License.
  433. This program is distributed in the hope that it will be useful,
  434. but WITHOUT ANY WARRANTY; without even the implied warranty of
  435. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  436. GNU General Public License for more details.
  437. You should have received a copy of the GNU General Public License
  438. along with this program; if not, write to the Free Software
  439. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  440. */
  441. #include <stdbool.h>
  442. #include <stdint.h>
  443. #include <sys/types.h>
  444. #include <sys/stat.h>
  445. #include <unistd.h>
  446. #include <fcntl.h>
  447. #include <errno.h>
  448. #include <string.h>
  449. #include <dbus/dbus.h>
  450. #include <time.h>
  451. #include "controller_internal.h"
  452. #include "jackdbus.h"
  453. bool
  454. jack_controller_settings_write_string(int fd, const char * string, void *dbus_call_context_ptr)
  455. {
  456. size_t len;
  457. len = strlen(string);
  458. if (write(fd, string, len) != len)
  459. {
  460. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "write() failed to write config file.");
  461. return false;
  462. }
  463. return true;
  464. }
  465. struct save_context
  466. {
  467. int fd;
  468. const char *indent;
  469. };
  470. #define save_context_ptr ((struct save_context *)context)
  471. #define fd (save_context_ptr->fd)
  472. bool
  473. jack_controller_settings_write_option(
  474. void *context,
  475. const char *name,
  476. const char *content,
  477. void *dbus_call_context_ptr)
  478. {
  479. if (!jack_controller_settings_write_string(fd, save_context_ptr->indent, dbus_call_context_ptr))
  480. {
  481. return false;
  482. }
  483. if (!jack_controller_settings_write_string(fd, "<option name=\"", dbus_call_context_ptr))
  484. {
  485. return false;
  486. }
  487. if (!jack_controller_settings_write_string(fd, name, dbus_call_context_ptr))
  488. {
  489. return false;
  490. }
  491. if (!jack_controller_settings_write_string(fd, "\">", dbus_call_context_ptr))
  492. {
  493. return false;
  494. }
  495. if (!jack_controller_settings_write_string(fd, content, dbus_call_context_ptr))
  496. {
  497. return false;
  498. }
  499. if (!jack_controller_settings_write_string(fd, "</option>\n", dbus_call_context_ptr))
  500. {
  501. return false;
  502. }
  503. return true;
  504. }
  505. #undef fd
  506. bool
  507. jack_controller_settings_save(
  508. struct jack_controller * controller_ptr,
  509. void *dbus_call_context_ptr)
  510. {
  511. char *filename;
  512. size_t conf_len;
  513. int fd;
  514. bool ret;
  515. time_t timestamp;
  516. char timestamp_str[26];
  517. struct save_context context;
  518. const JSList * node_ptr;
  519. jackctl_driver_t *driver;
  520. time(&timestamp);
  521. ctime_r(&timestamp, timestamp_str);
  522. timestamp_str[24] = 0;
  523. ret = false;
  524. conf_len = strlen(JACKDBUS_CONF);
  525. filename = malloc(g_jackdbus_config_dir_len + conf_len + 1);
  526. if (filename == NULL)
  527. {
  528. jack_error("Out of memory.");
  529. goto exit;
  530. }
  531. memcpy(filename, g_jackdbus_config_dir, g_jackdbus_config_dir_len);
  532. memcpy(filename + g_jackdbus_config_dir_len, JACKDBUS_CONF, conf_len);
  533. filename[g_jackdbus_config_dir_len + conf_len] = 0;
  534. jack_info("Saving settings to \"%s\" ...", filename);
  535. fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  536. if (fd == -1)
  537. {
  538. jack_error("open() failed to open conf filename. error is %d (%s)", errno, strerror(errno));
  539. goto exit_free_filename;
  540. }
  541. context.fd = fd;
  542. if (!jack_controller_settings_write_string(fd, "<?xml version=\"1.0\"?>\n", dbus_call_context_ptr))
  543. {
  544. goto exit_close;
  545. }
  546. if (!jack_controller_settings_write_string(fd, "<!--\n", dbus_call_context_ptr))
  547. {
  548. goto exit_close;
  549. }
  550. if (!jack_controller_settings_write_string(fd, JACK_CONF_HEADER_TEXT, dbus_call_context_ptr))
  551. {
  552. goto exit_close;
  553. }
  554. if (!jack_controller_settings_write_string(fd, "-->\n", dbus_call_context_ptr))
  555. {
  556. goto exit_close;
  557. }
  558. if (!jack_controller_settings_write_string(fd, "<!-- ", dbus_call_context_ptr))
  559. {
  560. goto exit_close;
  561. }
  562. if (!jack_controller_settings_write_string(fd, timestamp_str, dbus_call_context_ptr))
  563. {
  564. goto exit_close;
  565. }
  566. if (!jack_controller_settings_write_string(fd, " -->\n", dbus_call_context_ptr))
  567. {
  568. goto exit_close;
  569. }
  570. if (!jack_controller_settings_write_string(fd, "<jack>\n", dbus_call_context_ptr))
  571. {
  572. goto exit_close;
  573. }
  574. if (!jack_controller_settings_write_string(fd, " <engine>\n", dbus_call_context_ptr))
  575. {
  576. goto exit_close;
  577. }
  578. context.indent = " ";
  579. if (!jack_controller_settings_save_engine_options(&context, controller_ptr, dbus_call_context_ptr))
  580. {
  581. goto exit_close;
  582. }
  583. if (!jack_controller_settings_write_string(fd, " </engine>\n", dbus_call_context_ptr))
  584. {
  585. goto exit_close;
  586. }
  587. if (!jack_controller_settings_write_string(fd, " <drivers>\n", dbus_call_context_ptr))
  588. {
  589. goto exit_close;
  590. }
  591. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  592. while (node_ptr != NULL)
  593. {
  594. driver = (jackctl_driver_t *)node_ptr->data;
  595. if (!jack_controller_settings_write_string(fd, " <driver name=\"", dbus_call_context_ptr))
  596. {
  597. goto exit_close;
  598. }
  599. if (!jack_controller_settings_write_string(fd, jackctl_driver_get_name(driver), dbus_call_context_ptr))
  600. {
  601. goto exit_close;
  602. }
  603. if (!jack_controller_settings_write_string(fd, "\">\n", dbus_call_context_ptr))
  604. {
  605. goto exit_close;
  606. }
  607. context.indent = " ";
  608. if (!jack_controller_settings_save_driver_options(&context, driver, dbus_call_context_ptr))
  609. {
  610. goto exit_close;
  611. }
  612. if (!jack_controller_settings_write_string(fd, " </driver>\n", dbus_call_context_ptr))
  613. {
  614. goto exit_close;
  615. }
  616. node_ptr = jack_slist_next(node_ptr);
  617. }
  618. if (!jack_controller_settings_write_string(fd, " </drivers>\n", dbus_call_context_ptr))
  619. {
  620. goto exit_close;
  621. }
  622. if (!jack_controller_settings_write_string(fd, "</jack>\n", dbus_call_context_ptr))
  623. {
  624. goto exit_close;
  625. }
  626. ret = true;
  627. exit_close:
  628. close(fd);
  629. exit_free_filename:
  630. free(filename);
  631. exit:
  632. return ret;
  633. }
  634. void
  635. jack_controller_settings_save_auto(
  636. struct jack_controller * controller_ptr)
  637. {
  638. jack_controller_settings_save(controller_ptr, NULL);
  639. }
  640. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  641. /*
  642. Copyright (C) 2007,2008 Nedko Arnaudov
  643. This program is free software; you can redistribute it and/or modify
  644. it under the terms of the GNU General Public License as published by
  645. the Free Software Foundation; either version 2 of the License.
  646. This program is distributed in the hope that it will be useful,
  647. but WITHOUT ANY WARRANTY; without even the implied warranty of
  648. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  649. GNU General Public License for more details.
  650. You should have received a copy of the GNU General Public License
  651. along with this program; if not, write to the Free Software
  652. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  653. */
  654. #include <stdbool.h>
  655. #include <stdint.h>
  656. #include <sys/types.h>
  657. #include <sys/stat.h>
  658. #include <unistd.h>
  659. #include <fcntl.h>
  660. #include <errno.h>
  661. #include <string.h>
  662. #include <dbus/dbus.h>
  663. #include <time.h>
  664. #include "controller_internal.h"
  665. #include "jackdbus.h"
  666. bool
  667. jack_controller_settings_write_string(int fd, const char * string, void *dbus_call_context_ptr)
  668. {
  669. size_t len;
  670. len = strlen(string);
  671. if (write(fd, string, len) != len)
  672. {
  673. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "write() failed to write config file.");
  674. return false;
  675. }
  676. return true;
  677. }
  678. struct save_context
  679. {
  680. int fd;
  681. const char *indent;
  682. };
  683. #define save_context_ptr ((struct save_context *)context)
  684. #define fd (save_context_ptr->fd)
  685. bool
  686. jack_controller_settings_write_option(
  687. void *context,
  688. const char *name,
  689. const char *content,
  690. void *dbus_call_context_ptr)
  691. {
  692. if (!jack_controller_settings_write_string(fd, save_context_ptr->indent, dbus_call_context_ptr))
  693. {
  694. return false;
  695. }
  696. if (!jack_controller_settings_write_string(fd, "<option name=\"", dbus_call_context_ptr))
  697. {
  698. return false;
  699. }
  700. if (!jack_controller_settings_write_string(fd, name, dbus_call_context_ptr))
  701. {
  702. return false;
  703. }
  704. if (!jack_controller_settings_write_string(fd, "\">", dbus_call_context_ptr))
  705. {
  706. return false;
  707. }
  708. if (!jack_controller_settings_write_string(fd, content, dbus_call_context_ptr))
  709. {
  710. return false;
  711. }
  712. if (!jack_controller_settings_write_string(fd, "</option>\n", dbus_call_context_ptr))
  713. {
  714. return false;
  715. }
  716. return true;
  717. }
  718. #undef fd
  719. bool
  720. jack_controller_settings_save(
  721. struct jack_controller * controller_ptr,
  722. void *dbus_call_context_ptr)
  723. {
  724. char *filename;
  725. size_t conf_len;
  726. int fd;
  727. bool ret;
  728. time_t timestamp;
  729. char timestamp_str[26];
  730. struct save_context context;
  731. const JSList * node_ptr;
  732. jackctl_driver_t *driver;
  733. time(&timestamp);
  734. ctime_r(&timestamp, timestamp_str);
  735. timestamp_str[24] = 0;
  736. ret = false;
  737. conf_len = strlen(JACKDBUS_CONF);
  738. filename = malloc(g_jackdbus_config_dir_len + conf_len + 1);
  739. if (filename == NULL)
  740. {
  741. jack_error("Out of memory.");
  742. goto exit;
  743. }
  744. memcpy(filename, g_jackdbus_config_dir, g_jackdbus_config_dir_len);
  745. memcpy(filename + g_jackdbus_config_dir_len, JACKDBUS_CONF, conf_len);
  746. filename[g_jackdbus_config_dir_len + conf_len] = 0;
  747. jack_info("Saving settings to \"%s\" ...", filename);
  748. fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  749. if (fd == -1)
  750. {
  751. jack_error("open() failed to open conf filename. error is %d (%s)", errno, strerror(errno));
  752. goto exit_free_filename;
  753. }
  754. context.fd = fd;
  755. if (!jack_controller_settings_write_string(fd, "<?xml version=\"1.0\"?>\n", dbus_call_context_ptr))
  756. {
  757. goto exit_close;
  758. }
  759. if (!jack_controller_settings_write_string(fd, "<!--\n", dbus_call_context_ptr))
  760. {
  761. goto exit_close;
  762. }
  763. if (!jack_controller_settings_write_string(fd, JACK_CONF_HEADER_TEXT, dbus_call_context_ptr))
  764. {
  765. goto exit_close;
  766. }
  767. if (!jack_controller_settings_write_string(fd, "-->\n", dbus_call_context_ptr))
  768. {
  769. goto exit_close;
  770. }
  771. if (!jack_controller_settings_write_string(fd, "<!-- ", dbus_call_context_ptr))
  772. {
  773. goto exit_close;
  774. }
  775. if (!jack_controller_settings_write_string(fd, timestamp_str, dbus_call_context_ptr))
  776. {
  777. goto exit_close;
  778. }
  779. if (!jack_controller_settings_write_string(fd, " -->\n", dbus_call_context_ptr))
  780. {
  781. goto exit_close;
  782. }
  783. if (!jack_controller_settings_write_string(fd, "<jack>\n", dbus_call_context_ptr))
  784. {
  785. goto exit_close;
  786. }
  787. if (!jack_controller_settings_write_string(fd, " <engine>\n", dbus_call_context_ptr))
  788. {
  789. goto exit_close;
  790. }
  791. context.indent = " ";
  792. if (!jack_controller_settings_save_engine_options(&context, controller_ptr, dbus_call_context_ptr))
  793. {
  794. goto exit_close;
  795. }
  796. if (!jack_controller_settings_write_string(fd, " </engine>\n", dbus_call_context_ptr))
  797. {
  798. goto exit_close;
  799. }
  800. if (!jack_controller_settings_write_string(fd, " <drivers>\n", dbus_call_context_ptr))
  801. {
  802. goto exit_close;
  803. }
  804. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  805. while (node_ptr != NULL)
  806. {
  807. driver = (jackctl_driver_t *)node_ptr->data;
  808. if (!jack_controller_settings_write_string(fd, " <driver name=\"", dbus_call_context_ptr))
  809. {
  810. goto exit_close;
  811. }
  812. if (!jack_controller_settings_write_string(fd, jackctl_driver_get_name(driver), dbus_call_context_ptr))
  813. {
  814. goto exit_close;
  815. }
  816. if (!jack_controller_settings_write_string(fd, "\">\n", dbus_call_context_ptr))
  817. {
  818. goto exit_close;
  819. }
  820. context.indent = " ";
  821. if (!jack_controller_settings_save_driver_options(&context, driver, dbus_call_context_ptr))
  822. {
  823. goto exit_close;
  824. }
  825. if (!jack_controller_settings_write_string(fd, " </driver>\n", dbus_call_context_ptr))
  826. {
  827. goto exit_close;
  828. }
  829. node_ptr = jack_slist_next(node_ptr);
  830. }
  831. if (!jack_controller_settings_write_string(fd, " </drivers>\n", dbus_call_context_ptr))
  832. {
  833. goto exit_close;
  834. }
  835. if (!jack_controller_settings_write_string(fd, "</jack>\n", dbus_call_context_ptr))
  836. {
  837. goto exit_close;
  838. }
  839. ret = true;
  840. exit_close:
  841. close(fd);
  842. exit_free_filename:
  843. free(filename);
  844. exit:
  845. return ret;
  846. }
  847. void
  848. jack_controller_settings_save_auto(
  849. struct jack_controller * controller_ptr)
  850. {
  851. jack_controller_settings_save(controller_ptr, NULL);
  852. }