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.

1046 lines
27KB

  1. /* -*- Mode: C++ ; c-basic-offset: 4 -*- */
  2. /*
  3. JACK control API implementation
  4. Copyright (C) 2008 Nedko Arnaudov
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; version 2 of the License.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #if defined(HAVE_CONFIG_H)
  17. #include "config.h"
  18. #endif
  19. #ifndef WIN32
  20. #include <stdbool.h>
  21. #include <stdint.h>
  22. #include <dirent.h>
  23. #include <pthread.h>
  24. #endif
  25. #include "types.h"
  26. #include <string.h>
  27. #include <errno.h>
  28. #include <stdio.h>
  29. #include <assert.h>
  30. #include <signal.h>
  31. #include "jslist.h"
  32. #include "driver_interface.h"
  33. #include "JackError.h"
  34. #include "JackServer.h"
  35. #include "shm.h"
  36. #include "JackTools.h"
  37. #include "control_types.h"
  38. using namespace Jack;
  39. struct jackctl_server
  40. {
  41. JSList * drivers;
  42. JSList * internals;
  43. JSList * parameters;
  44. class JackServer * engine;
  45. /* string, server name */
  46. union jackctl_parameter_value name;
  47. union jackctl_parameter_value default_name;
  48. /* bool, whether to be "realtime" */
  49. union jackctl_parameter_value realtime;
  50. union jackctl_parameter_value default_realtime;
  51. /* int32_t */
  52. union jackctl_parameter_value realtime_priority;
  53. union jackctl_parameter_value default_realtime_priority;
  54. /* bool, whether to exit once all clients have closed their connections */
  55. union jackctl_parameter_value temporary;
  56. union jackctl_parameter_value default_temporary;
  57. /* bool, whether to be verbose */
  58. union jackctl_parameter_value verbose;
  59. union jackctl_parameter_value default_verbose;
  60. /* int32_t, msecs; if zero, use period size. */
  61. union jackctl_parameter_value client_timeout;
  62. union jackctl_parameter_value default_client_timeout;
  63. /* uint32_t, ports of the loopback driver */
  64. union jackctl_parameter_value loopback_ports;
  65. union jackctl_parameter_value default_loopback_ports;
  66. /* bool */
  67. union jackctl_parameter_value replace_registry;
  68. union jackctl_parameter_value default_replace_registry;
  69. /* bool, synchronous or asynchronous engine mode */
  70. union jackctl_parameter_value sync;
  71. union jackctl_parameter_value default_sync;
  72. };
  73. struct jackctl_driver
  74. {
  75. jack_driver_desc_t * desc_ptr;
  76. JSList * parameters;
  77. JSList * set_parameters;
  78. };
  79. struct jackctl_internal
  80. {
  81. jack_driver_desc_t * desc_ptr;
  82. JSList * parameters;
  83. JSList * set_parameters;
  84. };
  85. struct jackctl_parameter
  86. {
  87. const char * name;
  88. const char * short_description;
  89. const char * long_description;
  90. jackctl_param_type_t type;
  91. bool is_set;
  92. union jackctl_parameter_value * value_ptr;
  93. union jackctl_parameter_value * default_value_ptr;
  94. union jackctl_parameter_value value;
  95. union jackctl_parameter_value default_value;
  96. struct jackctl_driver * driver_ptr;
  97. char id;
  98. jack_driver_param_t * driver_parameter_ptr;
  99. };
  100. static
  101. struct jackctl_parameter *
  102. jackctl_add_parameter(
  103. JSList ** parameters_list_ptr_ptr,
  104. const char * name,
  105. const char * short_description,
  106. const char * long_description,
  107. jackctl_param_type_t type,
  108. union jackctl_parameter_value * value_ptr,
  109. union jackctl_parameter_value * default_value_ptr,
  110. union jackctl_parameter_value value)
  111. {
  112. struct jackctl_parameter * parameter_ptr;
  113. parameter_ptr = (struct jackctl_parameter *)malloc(sizeof(struct jackctl_parameter));
  114. if (parameter_ptr == NULL)
  115. {
  116. jack_error("Cannot allocate memory for jackctl_parameter structure.");
  117. goto fail;
  118. }
  119. parameter_ptr->name = name;
  120. parameter_ptr->short_description = short_description;
  121. parameter_ptr->long_description = long_description;
  122. parameter_ptr->type = type;
  123. parameter_ptr->is_set = false;
  124. if (value_ptr == NULL)
  125. {
  126. value_ptr = &parameter_ptr->value;
  127. }
  128. if (default_value_ptr == NULL)
  129. {
  130. default_value_ptr = &parameter_ptr->default_value;
  131. }
  132. parameter_ptr->value_ptr = value_ptr;
  133. parameter_ptr->default_value_ptr = default_value_ptr;
  134. *value_ptr = *default_value_ptr = value;
  135. parameter_ptr->driver_ptr = NULL;
  136. parameter_ptr->driver_parameter_ptr = NULL;
  137. parameter_ptr->id = 0;
  138. *parameters_list_ptr_ptr = jack_slist_append(*parameters_list_ptr_ptr, parameter_ptr);
  139. return parameter_ptr;
  140. fail:
  141. return NULL;
  142. }
  143. static
  144. void
  145. jackctl_free_driver_parameters(
  146. struct jackctl_driver * driver_ptr)
  147. {
  148. JSList * next_node_ptr;
  149. while (driver_ptr->parameters)
  150. {
  151. next_node_ptr = driver_ptr->parameters->next;
  152. free(driver_ptr->parameters->data);
  153. free(driver_ptr->parameters);
  154. driver_ptr->parameters = next_node_ptr;
  155. }
  156. while (driver_ptr->set_parameters)
  157. {
  158. next_node_ptr = driver_ptr->set_parameters->next;
  159. free(driver_ptr->set_parameters->data);
  160. free(driver_ptr->set_parameters);
  161. driver_ptr->set_parameters = next_node_ptr;
  162. }
  163. }
  164. static
  165. bool
  166. jackctl_add_driver_parameters(
  167. struct jackctl_driver * driver_ptr)
  168. {
  169. uint32_t i;
  170. union jackctl_parameter_value jackctl_value;
  171. jackctl_param_type_t jackctl_type;
  172. struct jackctl_parameter * parameter_ptr;
  173. jack_driver_param_desc_t * descriptor_ptr;
  174. for (i = 0 ; i < driver_ptr->desc_ptr->nparams ; i++)
  175. {
  176. descriptor_ptr = driver_ptr->desc_ptr->params + i;
  177. switch (descriptor_ptr->type)
  178. {
  179. case JackDriverParamInt:
  180. jackctl_type = JackParamInt;
  181. jackctl_value.i = descriptor_ptr->value.i;
  182. break;
  183. case JackDriverParamUInt:
  184. jackctl_type = JackParamUInt;
  185. jackctl_value.ui = descriptor_ptr->value.ui;
  186. break;
  187. case JackDriverParamChar:
  188. jackctl_type = JackParamChar;
  189. jackctl_value.c = descriptor_ptr->value.c;
  190. break;
  191. case JackDriverParamString:
  192. jackctl_type = JackParamString;
  193. strcpy(jackctl_value.str, descriptor_ptr->value.str);
  194. break;
  195. case JackDriverParamBool:
  196. jackctl_type = JackParamBool;
  197. jackctl_value.b = descriptor_ptr->value.i;
  198. break;
  199. default:
  200. jack_error("unknown driver parameter type %i", (int)descriptor_ptr->type);
  201. assert(0);
  202. goto fail;
  203. }
  204. parameter_ptr = jackctl_add_parameter(
  205. &driver_ptr->parameters,
  206. descriptor_ptr->name,
  207. descriptor_ptr->short_desc,
  208. descriptor_ptr->long_desc,
  209. jackctl_type,
  210. NULL,
  211. NULL,
  212. jackctl_value);
  213. if (parameter_ptr == NULL)
  214. {
  215. goto fail;
  216. }
  217. parameter_ptr->driver_ptr = driver_ptr;
  218. parameter_ptr->id = descriptor_ptr->character;
  219. }
  220. return true;
  221. fail:
  222. jackctl_free_driver_parameters(driver_ptr);
  223. return false;
  224. }
  225. static int
  226. jackctl_drivers_load(
  227. struct jackctl_server * server_ptr)
  228. {
  229. struct jackctl_driver * driver_ptr;
  230. JSList *node_ptr;
  231. JSList *descriptor_node_ptr;
  232. descriptor_node_ptr = jack_drivers_load(NULL);
  233. if (descriptor_node_ptr == NULL)
  234. {
  235. jack_error("could not find any drivers in driver directory!");
  236. return false;
  237. }
  238. while (descriptor_node_ptr != NULL)
  239. {
  240. driver_ptr = (struct jackctl_driver *)malloc(sizeof(struct jackctl_driver));
  241. if (driver_ptr == NULL)
  242. {
  243. jack_error("memory allocation of jackctl_driver structure failed.");
  244. goto next;
  245. }
  246. driver_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data;
  247. driver_ptr->parameters = NULL;
  248. driver_ptr->set_parameters = NULL;
  249. if (!jackctl_add_driver_parameters(driver_ptr))
  250. {
  251. assert(driver_ptr->parameters == NULL);
  252. free(driver_ptr);
  253. goto next;
  254. }
  255. server_ptr->drivers = jack_slist_append(server_ptr->drivers, driver_ptr);
  256. next:
  257. node_ptr = descriptor_node_ptr;
  258. descriptor_node_ptr = descriptor_node_ptr->next;
  259. free(node_ptr);
  260. }
  261. return true;
  262. }
  263. static
  264. void
  265. jackctl_server_free_drivers(
  266. struct jackctl_server * server_ptr)
  267. {
  268. JSList * next_node_ptr;
  269. struct jackctl_driver * driver_ptr;
  270. while (server_ptr->drivers)
  271. {
  272. next_node_ptr = server_ptr->drivers->next;
  273. driver_ptr = (struct jackctl_driver *)server_ptr->drivers->data;
  274. jackctl_free_driver_parameters(driver_ptr);
  275. free(driver_ptr->desc_ptr->params);
  276. free(driver_ptr->desc_ptr);
  277. free(driver_ptr);
  278. free(server_ptr->drivers);
  279. server_ptr->drivers = next_node_ptr;
  280. }
  281. }
  282. static int
  283. jackctl_internals_load(
  284. struct jackctl_server * server_ptr)
  285. {
  286. struct jackctl_internal * internal_ptr;
  287. JSList *node_ptr;
  288. JSList *descriptor_node_ptr;
  289. descriptor_node_ptr = jack_internals_load(NULL);
  290. if (descriptor_node_ptr == NULL)
  291. {
  292. jack_error("could not find any internals in driver directory!");
  293. return false;
  294. }
  295. while (descriptor_node_ptr != NULL)
  296. {
  297. jack_log("jackctl_internals_load");
  298. internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_driver));
  299. if (internal_ptr == NULL)
  300. {
  301. jack_error("memory allocation of jackctl_driver structure failed.");
  302. goto next;
  303. }
  304. internal_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data;
  305. internal_ptr->parameters = NULL;
  306. internal_ptr->set_parameters = NULL;
  307. if (!jackctl_add_driver_parameters((struct jackctl_driver *)internal_ptr))
  308. {
  309. assert(internal_ptr->parameters == NULL);
  310. free(internal_ptr);
  311. goto next;
  312. }
  313. server_ptr->internals = jack_slist_append(server_ptr->internals, internal_ptr);
  314. next:
  315. node_ptr = descriptor_node_ptr;
  316. descriptor_node_ptr = descriptor_node_ptr->next;
  317. free(node_ptr);
  318. }
  319. return true;
  320. }
  321. static
  322. void
  323. jackctl_server_free_internals(
  324. struct jackctl_server * server_ptr)
  325. {
  326. JSList * next_node_ptr;
  327. struct jackctl_internal * internal_ptr;
  328. while (server_ptr->internals)
  329. {
  330. next_node_ptr = server_ptr->internals->next;
  331. internal_ptr = (struct jackctl_internal *)server_ptr->internals->data;
  332. jackctl_free_driver_parameters((struct jackctl_driver *)internal_ptr);
  333. free(internal_ptr->desc_ptr->params);
  334. free(internal_ptr->desc_ptr);
  335. free(internal_ptr);
  336. free(server_ptr->internals);
  337. server_ptr->internals = next_node_ptr;
  338. }
  339. }
  340. static
  341. void
  342. jackctl_server_free_parameters(
  343. struct jackctl_server * server_ptr)
  344. {
  345. JSList * next_node_ptr;
  346. while (server_ptr->parameters)
  347. {
  348. next_node_ptr = server_ptr->parameters->next;
  349. free(server_ptr->parameters->data);
  350. free(server_ptr->parameters);
  351. server_ptr->parameters = next_node_ptr;
  352. }
  353. }
  354. #ifdef WIN32
  355. static HANDLE waitEvent;
  356. static void do_nothing_handler(int signum)
  357. {
  358. printf("jack main caught signal %d\n", signum);
  359. (void) signal(SIGINT, SIG_DFL);
  360. SetEvent(waitEvent);
  361. }
  362. sigset_t
  363. jackctl_setup_signals(
  364. unsigned int flags)
  365. {
  366. if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
  367. jack_error("CreateEvent fails err = %ld", GetLastError());
  368. return 0;
  369. }
  370. (void) signal(SIGINT, do_nothing_handler);
  371. (void) signal(SIGABRT, do_nothing_handler);
  372. (void) signal(SIGTERM, do_nothing_handler);
  373. return (sigset_t)waitEvent;
  374. }
  375. void jackctl_wait_signals(sigset_t signals)
  376. {
  377. if (WaitForSingleObject(waitEvent, INFINITE) != WAIT_OBJECT_0) {
  378. jack_error("WaitForSingleObject fails err = %ld", GetLastError());
  379. }
  380. }
  381. #else
  382. static
  383. void
  384. do_nothing_handler(int sig)
  385. {
  386. /* this is used by the child (active) process, but it never
  387. gets called unless we are already shutting down after
  388. another signal.
  389. */
  390. char buf[64];
  391. snprintf (buf, sizeof(buf),
  392. "received signal %d during shutdown (ignored)\n", sig);
  393. write (1, buf, strlen (buf));
  394. }
  395. EXPORT sigset_t
  396. jackctl_setup_signals(
  397. unsigned int flags)
  398. {
  399. sigset_t signals;
  400. sigset_t allsignals;
  401. struct sigaction action;
  402. int i;
  403. /* ensure that we are in our own process group so that
  404. kill (SIG, -pgrp) does the right thing.
  405. */
  406. setsid();
  407. pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  408. /* what's this for?
  409. POSIX says that signals are delivered like this:
  410. * if a thread has blocked that signal, it is not
  411. a candidate to receive the signal.
  412. * of all threads not blocking the signal, pick
  413. one at random, and deliver the signal.
  414. this means that a simple-minded multi-threaded program can
  415. expect to get POSIX signals delivered randomly to any one
  416. of its threads,
  417. here, we block all signals that we think we might receive
  418. and want to catch. all "child" threads will inherit this
  419. setting. if we create a thread that calls sigwait() on the
  420. same set of signals, implicitly unblocking all those
  421. signals. any of those signals that are delivered to the
  422. process will be delivered to that thread, and that thread
  423. alone. this makes cleanup for a signal-driven exit much
  424. easier, since we know which thread is doing it and more
  425. importantly, we are free to call async-unsafe functions,
  426. because the code is executing in normal thread context
  427. after a return from sigwait().
  428. */
  429. sigemptyset(&signals);
  430. sigaddset(&signals, SIGHUP);
  431. sigaddset(&signals, SIGINT);
  432. sigaddset(&signals, SIGQUIT);
  433. sigaddset(&signals, SIGPIPE);
  434. sigaddset(&signals, SIGTERM);
  435. sigaddset(&signals, SIGUSR1);
  436. sigaddset(&signals, SIGUSR2);
  437. /* all child threads will inherit this mask unless they
  438. * explicitly reset it
  439. */
  440. pthread_sigmask(SIG_BLOCK, &signals, 0);
  441. /* install a do-nothing handler because otherwise pthreads
  442. behaviour is undefined when we enter sigwait.
  443. */
  444. sigfillset(&allsignals);
  445. action.sa_handler = do_nothing_handler;
  446. action.sa_mask = allsignals;
  447. action.sa_flags = SA_RESTART|SA_RESETHAND;
  448. for (i = 1; i < NSIG; i++)
  449. {
  450. if (sigismember (&signals, i))
  451. {
  452. sigaction(i, &action, 0);
  453. }
  454. }
  455. return signals;
  456. }
  457. EXPORT void
  458. jackctl_wait_signals(sigset_t signals)
  459. {
  460. int sig;
  461. bool waiting = true;
  462. while (waiting) {
  463. sigwait(&signals, &sig);
  464. fprintf(stderr, "jack main caught signal %d\n", sig);
  465. switch (sig) {
  466. case SIGUSR1:
  467. //jack_dump_configuration(engine, 1);
  468. break;
  469. case SIGUSR2:
  470. // driver exit
  471. waiting = false;
  472. break;
  473. case SIGTTOU:
  474. break;
  475. default:
  476. waiting = false;
  477. break;
  478. }
  479. }
  480. if (sig != SIGSEGV) {
  481. // unblock signals so we can see them during shutdown.
  482. // this will help prod developers not to lose sight of
  483. // bugs that cause segfaults etc. during shutdown.
  484. sigprocmask(SIG_UNBLOCK, &signals, 0);
  485. }
  486. }
  487. #endif
  488. EXPORT jackctl_server_t * jackctl_server_create()
  489. {
  490. struct jackctl_server * server_ptr;
  491. union jackctl_parameter_value value;
  492. server_ptr = (struct jackctl_server *)malloc(sizeof(struct jackctl_server));
  493. if (server_ptr == NULL)
  494. {
  495. jack_error("Cannot allocate memory for jackctl_server structure.");
  496. goto fail;
  497. }
  498. server_ptr->drivers = NULL;
  499. server_ptr->internals = NULL;
  500. server_ptr->parameters = NULL;
  501. server_ptr->engine = NULL;
  502. strcpy(value.str, JACK_DEFAULT_SERVER_NAME);
  503. if (jackctl_add_parameter(
  504. &server_ptr->parameters,
  505. "name",
  506. "server name to use",
  507. "",
  508. JackParamString,
  509. &server_ptr->name,
  510. &server_ptr->default_name,
  511. value) == NULL)
  512. {
  513. goto fail_free_parameters;
  514. }
  515. value.b = false;
  516. if (jackctl_add_parameter(
  517. &server_ptr->parameters,
  518. "realtime",
  519. "Whether to use realtime mode",
  520. "Use realtime scheduling. This is needed for reliable low-latency performance. On most systems, it requires JACK to run with special scheduler and memory allocation privileges, which may be obtained in several ways. On Linux you should use PAM.",
  521. JackParamBool,
  522. &server_ptr->realtime,
  523. &server_ptr->default_realtime,
  524. value) == NULL)
  525. {
  526. goto fail_free_parameters;
  527. }
  528. value.i = 10;
  529. if (jackctl_add_parameter(
  530. &server_ptr->parameters,
  531. "realtime-priority",
  532. "Scheduler priority when running in realtime mode.",
  533. "",
  534. JackParamInt,
  535. &server_ptr->realtime_priority,
  536. &server_ptr->default_realtime_priority,
  537. value) == NULL)
  538. {
  539. goto fail_free_parameters;
  540. }
  541. value.b = false;
  542. if (jackctl_add_parameter(
  543. &server_ptr->parameters,
  544. "temporary",
  545. "Exit once all clients have closed their connections.",
  546. "",
  547. JackParamBool,
  548. &server_ptr->temporary,
  549. &server_ptr->default_temporary,
  550. value) == NULL)
  551. {
  552. goto fail_free_parameters;
  553. }
  554. value.b = false;
  555. if (jackctl_add_parameter(
  556. &server_ptr->parameters,
  557. "verbose",
  558. "Verbose mode.",
  559. "",
  560. JackParamBool,
  561. &server_ptr->verbose,
  562. &server_ptr->default_verbose,
  563. value) == NULL)
  564. {
  565. goto fail_free_parameters;
  566. }
  567. value.i = 0;
  568. if (jackctl_add_parameter(
  569. &server_ptr->parameters,
  570. "client-timeout",
  571. "Client timeout limit in milliseconds",
  572. "",
  573. JackParamInt,
  574. &server_ptr->client_timeout,
  575. &server_ptr->default_client_timeout,
  576. value) == NULL)
  577. {
  578. goto fail_free_parameters;
  579. }
  580. value.ui = 0;
  581. if (jackctl_add_parameter(
  582. &server_ptr->parameters,
  583. "loopback-ports",
  584. "Number of loopback ports",
  585. "",
  586. JackParamUInt,
  587. &server_ptr->loopback_ports,
  588. &server_ptr->default_loopback_ports,
  589. value) == NULL)
  590. {
  591. goto fail_free_parameters;
  592. }
  593. value.b = false;
  594. if (jackctl_add_parameter(
  595. &server_ptr->parameters,
  596. "replace-registry",
  597. "Replace registry",
  598. "",
  599. JackParamBool,
  600. &server_ptr->replace_registry,
  601. &server_ptr->default_replace_registry,
  602. value) == NULL)
  603. {
  604. goto fail_free_parameters;
  605. }
  606. value.b = false;
  607. if (jackctl_add_parameter(
  608. &server_ptr->parameters,
  609. "sync",
  610. "Use synchronous mode",
  611. "",
  612. JackParamBool,
  613. &server_ptr->sync,
  614. &server_ptr->default_sync,
  615. value) == NULL)
  616. {
  617. goto fail_free_parameters;
  618. }
  619. if (!jackctl_drivers_load(server_ptr))
  620. {
  621. goto fail_free_parameters;
  622. }
  623. if (!jackctl_internals_load(server_ptr))
  624. {
  625. goto fail_free_parameters;
  626. }
  627. return server_ptr;
  628. fail_free_parameters:
  629. jackctl_server_free_parameters(server_ptr);
  630. free(server_ptr);
  631. fail:
  632. return NULL;
  633. }
  634. EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
  635. {
  636. jackctl_server_free_drivers(server_ptr);
  637. jackctl_server_free_parameters(server_ptr);
  638. free(server_ptr);
  639. }
  640. EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
  641. {
  642. return server_ptr->drivers;
  643. }
  644. EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
  645. {
  646. server_ptr->engine->Stop();
  647. server_ptr->engine->Close();
  648. delete server_ptr->engine;
  649. /* clean up shared memory and files from this server instance */
  650. jack_log("cleaning up shared memory");
  651. jack_cleanup_shm();
  652. jack_log("cleaning up files");
  653. JackTools::CleanupFiles(server_ptr->name.str);
  654. jack_log("unregistering server `%s'", server_ptr->name.str);
  655. jack_unregister_server(server_ptr->name.str);
  656. server_ptr->engine = NULL;
  657. return true;
  658. }
  659. EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
  660. {
  661. return server_ptr->parameters;
  662. }
  663. EXPORT bool
  664. jackctl_server_start(
  665. jackctl_server *server_ptr,
  666. jackctl_driver *driver_ptr)
  667. {
  668. int rc;
  669. rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
  670. switch (rc)
  671. {
  672. case EEXIST:
  673. jack_error("`%s' server already active", server_ptr->name.str);
  674. goto fail;
  675. case ENOSPC:
  676. jack_error("too many servers already active");
  677. goto fail;
  678. case ENOMEM:
  679. jack_error("no access to shm registry");
  680. goto fail;
  681. }
  682. jack_log("server `%s' registered", server_ptr->name.str);
  683. /* clean up shared memory and files from any previous
  684. * instance of this server name */
  685. jack_cleanup_shm();
  686. JackTools::CleanupFiles(server_ptr->name.str);
  687. if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0)
  688. server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */
  689. /* get the engine/driver started */
  690. server_ptr->engine = new JackServer(
  691. server_ptr->sync.b,
  692. server_ptr->temporary.b,
  693. server_ptr->client_timeout.i,
  694. server_ptr->realtime.b,
  695. server_ptr->realtime_priority.i,
  696. server_ptr->loopback_ports.ui,
  697. server_ptr->verbose.b,
  698. server_ptr->name.str);
  699. if (server_ptr->engine == NULL)
  700. {
  701. jack_error("Failed to create new JackServer object");
  702. goto fail_unregister;
  703. }
  704. rc = server_ptr->engine->Open(driver_ptr->desc_ptr, driver_ptr->set_parameters);
  705. if (rc < 0)
  706. {
  707. jack_error("JackServer::Open() failed with %d", rc);
  708. goto fail_delete;
  709. }
  710. rc = server_ptr->engine->Start();
  711. if (rc < 0)
  712. {
  713. jack_error("JackServer::Start() failed with %d", rc);
  714. goto fail_close;
  715. }
  716. return true;
  717. fail_close:
  718. server_ptr->engine->Close();
  719. fail_delete:
  720. delete server_ptr->engine;
  721. server_ptr->engine = NULL;
  722. fail_unregister:
  723. jack_log("cleaning up shared memory");
  724. jack_cleanup_shm();
  725. jack_log("cleaning up files");
  726. JackTools::CleanupFiles(server_ptr->name.str);
  727. jack_log("unregistering server `%s'", server_ptr->name.str);
  728. jack_unregister_server(server_ptr->name.str);
  729. fail:
  730. return false;
  731. }
  732. EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
  733. {
  734. return driver_ptr->desc_ptr->name;
  735. }
  736. EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
  737. {
  738. return driver_ptr->parameters;
  739. }
  740. EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
  741. {
  742. return driver_ptr->desc_ptr;
  743. }
  744. EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
  745. {
  746. return parameter_ptr->name;
  747. }
  748. EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
  749. {
  750. return parameter_ptr->short_description;
  751. }
  752. EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
  753. {
  754. return parameter_ptr->long_description;
  755. }
  756. EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
  757. {
  758. return parameter_ptr->type;
  759. }
  760. EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
  761. {
  762. return parameter_ptr->id;
  763. }
  764. EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
  765. {
  766. return parameter_ptr->is_set;
  767. }
  768. EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr)
  769. {
  770. return *parameter_ptr->value_ptr;
  771. }
  772. EXPORT bool jackctl_parameter_reset_value(jackctl_parameter *parameter_ptr)
  773. {
  774. if (!parameter_ptr->is_set)
  775. {
  776. return true;
  777. }
  778. parameter_ptr->is_set = true;
  779. *parameter_ptr->value_ptr = *parameter_ptr->default_value_ptr;
  780. return true;
  781. }
  782. EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
  783. {
  784. bool new_driver_parameter;
  785. /* for driver parameters, set the parameter by adding jack_driver_param_t in the set_parameters list */
  786. if (parameter_ptr->driver_ptr != NULL)
  787. {
  788. /* jack_info("setting driver parameter %p ...", parameter_ptr); */
  789. new_driver_parameter = parameter_ptr->driver_parameter_ptr == NULL;
  790. if (new_driver_parameter)
  791. {
  792. /* jack_info("new driver parameter..."); */
  793. parameter_ptr->driver_parameter_ptr = (jack_driver_param_t *)malloc(sizeof(jack_driver_param_t));
  794. if (parameter_ptr->driver_parameter_ptr == NULL)
  795. {
  796. jack_error ("Allocation of jack_driver_param_t structure failed");
  797. return false;
  798. }
  799. parameter_ptr->driver_parameter_ptr->character = parameter_ptr->id;
  800. parameter_ptr->driver_ptr->set_parameters = jack_slist_append(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
  801. }
  802. switch (parameter_ptr->type)
  803. {
  804. case JackParamInt:
  805. parameter_ptr->driver_parameter_ptr->value.i = value_ptr->i;
  806. break;
  807. case JackParamUInt:
  808. parameter_ptr->driver_parameter_ptr->value.ui = value_ptr->ui;
  809. break;
  810. case JackParamChar:
  811. parameter_ptr->driver_parameter_ptr->value.c = value_ptr->c;
  812. break;
  813. case JackParamString:
  814. strcpy(parameter_ptr->driver_parameter_ptr->value.str, value_ptr->str);
  815. break;
  816. case JackParamBool:
  817. parameter_ptr->driver_parameter_ptr->value.i = value_ptr->b;
  818. break;
  819. default:
  820. jack_error("unknown parameter type %i", (int)parameter_ptr->type);
  821. assert(0);
  822. if (new_driver_parameter)
  823. {
  824. parameter_ptr->driver_ptr->set_parameters = jack_slist_remove(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
  825. }
  826. return false;
  827. }
  828. }
  829. parameter_ptr->is_set = true;
  830. *parameter_ptr->value_ptr = *value_ptr;
  831. return true;
  832. }
  833. EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
  834. {
  835. return *parameter_ptr->default_value_ptr;
  836. }
  837. // Internals clients
  838. EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
  839. {
  840. return server_ptr->internals;
  841. }
  842. EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
  843. {
  844. return internal_ptr->desc_ptr->name;
  845. }
  846. EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
  847. {
  848. return internal_ptr->parameters;
  849. }
  850. EXPORT bool jackctl_server_load_internal(
  851. jackctl_server * server,
  852. jackctl_internal * internal)
  853. {
  854. return false;
  855. }
  856. EXPORT bool jackctl_server_unload_internal(
  857. jackctl_server * server,
  858. jackctl_internal * internal)
  859. {
  860. return false;
  861. }