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.

1958 lines
58KB

  1. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  2. /*
  3. Copyright (C) 2008 Nedko Arnaudov
  4. Copyright (C) 2008 Juuso Alasuutari
  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; either 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. #define _GNU_SOURCE /* PTHREAD_MUTEX_RECURSIVE */
  20. #include <stdint.h>
  21. #include <inttypes.h>
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include <assert.h>
  25. #include <dbus/dbus.h>
  26. #include <pthread.h>
  27. #include "jackdbus.h"
  28. #include "controller_internal.h"
  29. #include "list.h"
  30. #define JACK_DBUS_IFACE_NAME "org.jackaudio.JackPatchbay"
  31. /* FIXME: these need to be retrieved from common headers */
  32. #define JACK_CLIENT_NAME_SIZE 64
  33. #define JACK_PORT_NAME_SIZE 256
  34. struct jack_graph
  35. {
  36. uint64_t version;
  37. struct list_head clients;
  38. struct list_head ports;
  39. struct list_head connections;
  40. };
  41. struct jack_graph_client
  42. {
  43. uint64_t id;
  44. char * name;
  45. int pid;
  46. struct list_head siblings;
  47. struct list_head ports;
  48. };
  49. struct jack_graph_port
  50. {
  51. uint64_t id;
  52. char * name;
  53. uint32_t flags;
  54. uint32_t type;
  55. struct list_head siblings_graph;
  56. struct list_head siblings_client;
  57. struct jack_graph_client * client;
  58. };
  59. struct jack_graph_connection
  60. {
  61. uint64_t id;
  62. struct jack_graph_port * port1;
  63. struct jack_graph_port * port2;
  64. struct list_head siblings;
  65. };
  66. struct jack_controller_patchbay
  67. {
  68. pthread_mutex_t lock;
  69. struct jack_graph graph;
  70. uint64_t next_client_id;
  71. uint64_t next_port_id;
  72. uint64_t next_connection_id;
  73. };
  74. void
  75. jack_controller_patchbay_send_signal_graph_changed(
  76. dbus_uint64_t new_graph_version)
  77. {
  78. jack_dbus_send_signal(
  79. JACK_CONTROLLER_OBJECT_PATH,
  80. JACK_DBUS_IFACE_NAME,
  81. "GraphChanged",
  82. DBUS_TYPE_UINT64,
  83. &new_graph_version,
  84. DBUS_TYPE_INVALID);
  85. }
  86. void
  87. jack_controller_patchbay_send_signal_client_appeared(
  88. dbus_uint64_t new_graph_version,
  89. dbus_uint64_t client_id,
  90. const char * client_name)
  91. {
  92. jack_dbus_send_signal(
  93. JACK_CONTROLLER_OBJECT_PATH,
  94. JACK_DBUS_IFACE_NAME,
  95. "ClientAppeared",
  96. DBUS_TYPE_UINT64,
  97. &new_graph_version,
  98. DBUS_TYPE_UINT64,
  99. &client_id,
  100. DBUS_TYPE_STRING,
  101. &client_name,
  102. DBUS_TYPE_INVALID);
  103. }
  104. void
  105. jack_controller_patchbay_send_signal_client_disappeared(
  106. dbus_uint64_t new_graph_version,
  107. dbus_uint64_t client_id,
  108. const char * client_name)
  109. {
  110. jack_dbus_send_signal(
  111. JACK_CONTROLLER_OBJECT_PATH,
  112. JACK_DBUS_IFACE_NAME,
  113. "ClientDisappeared",
  114. DBUS_TYPE_UINT64,
  115. &new_graph_version,
  116. DBUS_TYPE_UINT64,
  117. &client_id,
  118. DBUS_TYPE_STRING,
  119. &client_name,
  120. DBUS_TYPE_INVALID);
  121. }
  122. void
  123. jack_controller_patchbay_send_signal_port_appeared(
  124. dbus_uint64_t new_graph_version,
  125. dbus_uint64_t client_id,
  126. const char * client_name,
  127. dbus_uint64_t port_id,
  128. const char * port_name,
  129. dbus_uint32_t port_flags,
  130. dbus_uint32_t port_type)
  131. {
  132. jack_dbus_send_signal(
  133. JACK_CONTROLLER_OBJECT_PATH,
  134. JACK_DBUS_IFACE_NAME,
  135. "PortAppeared",
  136. DBUS_TYPE_UINT64,
  137. &new_graph_version,
  138. DBUS_TYPE_UINT64,
  139. &client_id,
  140. DBUS_TYPE_STRING,
  141. &client_name,
  142. DBUS_TYPE_UINT64,
  143. &port_id,
  144. DBUS_TYPE_STRING,
  145. &port_name,
  146. DBUS_TYPE_UINT32,
  147. &port_flags,
  148. DBUS_TYPE_UINT32,
  149. &port_type,
  150. DBUS_TYPE_INVALID);
  151. }
  152. void
  153. jack_controller_patchbay_send_signal_port_disappeared(
  154. dbus_uint64_t new_graph_version,
  155. dbus_uint64_t client_id,
  156. const char * client_name,
  157. dbus_uint64_t port_id,
  158. const char * port_name)
  159. {
  160. jack_dbus_send_signal(
  161. JACK_CONTROLLER_OBJECT_PATH,
  162. JACK_DBUS_IFACE_NAME,
  163. "PortDisappeared",
  164. DBUS_TYPE_UINT64,
  165. &new_graph_version,
  166. DBUS_TYPE_UINT64,
  167. &client_id,
  168. DBUS_TYPE_STRING,
  169. &client_name,
  170. DBUS_TYPE_UINT64,
  171. &port_id,
  172. DBUS_TYPE_STRING,
  173. &port_name,
  174. DBUS_TYPE_INVALID);
  175. }
  176. void
  177. jack_controller_patchbay_send_signal_ports_connected(
  178. dbus_uint64_t new_graph_version,
  179. dbus_uint64_t client1_id,
  180. const char * client1_name,
  181. dbus_uint64_t port1_id,
  182. const char * port1_name,
  183. dbus_uint64_t client2_id,
  184. const char * client2_name,
  185. dbus_uint64_t port2_id,
  186. const char * port2_name,
  187. dbus_uint64_t connection_id)
  188. {
  189. jack_dbus_send_signal(
  190. JACK_CONTROLLER_OBJECT_PATH,
  191. JACK_DBUS_IFACE_NAME,
  192. "PortsConnected",
  193. DBUS_TYPE_UINT64,
  194. &new_graph_version,
  195. DBUS_TYPE_UINT64,
  196. &client1_id,
  197. DBUS_TYPE_STRING,
  198. &client1_name,
  199. DBUS_TYPE_UINT64,
  200. &port1_id,
  201. DBUS_TYPE_STRING,
  202. &port1_name,
  203. DBUS_TYPE_UINT64,
  204. &client2_id,
  205. DBUS_TYPE_STRING,
  206. &client2_name,
  207. DBUS_TYPE_UINT64,
  208. &port2_id,
  209. DBUS_TYPE_STRING,
  210. &port2_name,
  211. DBUS_TYPE_UINT64,
  212. &connection_id,
  213. DBUS_TYPE_INVALID);
  214. }
  215. void
  216. jack_controller_patchbay_send_signal_ports_disconnected(
  217. dbus_uint64_t new_graph_version,
  218. dbus_uint64_t client1_id,
  219. const char * client1_name,
  220. dbus_uint64_t port1_id,
  221. const char * port1_name,
  222. dbus_uint64_t client2_id,
  223. const char * client2_name,
  224. dbus_uint64_t port2_id,
  225. const char * port2_name,
  226. dbus_uint64_t connection_id)
  227. {
  228. jack_dbus_send_signal(
  229. JACK_CONTROLLER_OBJECT_PATH,
  230. JACK_DBUS_IFACE_NAME,
  231. "PortsDisconnected",
  232. DBUS_TYPE_UINT64,
  233. &new_graph_version,
  234. DBUS_TYPE_UINT64,
  235. &client1_id,
  236. DBUS_TYPE_STRING,
  237. &client1_name,
  238. DBUS_TYPE_UINT64,
  239. &port1_id,
  240. DBUS_TYPE_STRING,
  241. &port1_name,
  242. DBUS_TYPE_UINT64,
  243. &client2_id,
  244. DBUS_TYPE_STRING,
  245. &client2_name,
  246. DBUS_TYPE_UINT64,
  247. &port2_id,
  248. DBUS_TYPE_STRING,
  249. &port2_name,
  250. DBUS_TYPE_UINT64,
  251. &connection_id,
  252. DBUS_TYPE_INVALID);
  253. }
  254. void
  255. jack_controller_patchbay_send_signal_port_renamed(
  256. dbus_uint64_t new_graph_version,
  257. dbus_uint64_t client_id,
  258. const char * client_name,
  259. dbus_uint64_t port_id,
  260. const char * port_old_name,
  261. const char * port_new_name)
  262. {
  263. jack_dbus_send_signal(
  264. JACK_CONTROLLER_OBJECT_PATH,
  265. JACK_DBUS_IFACE_NAME,
  266. "PortRenamed",
  267. DBUS_TYPE_UINT64,
  268. &new_graph_version,
  269. DBUS_TYPE_UINT64,
  270. &client_id,
  271. DBUS_TYPE_STRING,
  272. &client_name,
  273. DBUS_TYPE_UINT64,
  274. &port_id,
  275. DBUS_TYPE_STRING,
  276. &port_old_name,
  277. DBUS_TYPE_STRING,
  278. &port_new_name,
  279. DBUS_TYPE_INVALID);
  280. }
  281. static
  282. struct jack_graph_client *
  283. jack_controller_patchbay_find_client(
  284. struct jack_controller_patchbay *patchbay_ptr,
  285. const char *client_name, /* not '\0' terminated */
  286. size_t client_name_len) /* without terminating '\0' */
  287. {
  288. struct list_head *node_ptr;
  289. struct jack_graph_client *client_ptr;
  290. list_for_each(node_ptr, &patchbay_ptr->graph.clients)
  291. {
  292. client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings);
  293. if (strlen(client_ptr->name) == client_name_len && strncmp(client_ptr->name, client_name, client_name_len) == 0)
  294. {
  295. return client_ptr;
  296. }
  297. }
  298. return NULL;
  299. }
  300. static
  301. struct jack_graph_client *
  302. jack_controller_patchbay_find_client_by_id(
  303. struct jack_controller_patchbay *patchbay_ptr,
  304. uint64_t id)
  305. {
  306. struct list_head *node_ptr;
  307. struct jack_graph_client *client_ptr;
  308. list_for_each(node_ptr, &patchbay_ptr->graph.clients)
  309. {
  310. client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings);
  311. if (client_ptr->id == id)
  312. {
  313. return client_ptr;
  314. }
  315. }
  316. return NULL;
  317. }
  318. static
  319. struct jack_graph_client *
  320. jack_controller_patchbay_create_client(
  321. struct jack_controller_patchbay *patchbay_ptr,
  322. const char *client_name, /* not '\0' terminated */
  323. size_t client_name_len) /* without terminating '\0' */
  324. {
  325. struct jack_graph_client * client_ptr;
  326. client_ptr = malloc(sizeof(struct jack_graph_client));
  327. if (client_ptr == NULL)
  328. {
  329. jack_error("Memory allocation of jack_graph_client structure failed.");
  330. goto fail;
  331. }
  332. client_ptr->name = malloc(client_name_len + 1);
  333. if (client_ptr->name == NULL)
  334. {
  335. jack_error("malloc() failed to allocate memory for client name.");
  336. goto fail_free_client;
  337. }
  338. memcpy(client_ptr->name, client_name, client_name_len);
  339. client_ptr->name[client_name_len] = 0;
  340. client_ptr->pid = jack_get_client_pid(client_ptr->name);
  341. jack_info("New client '%s' with PID %d", client_ptr->name, client_ptr->pid);
  342. client_ptr->id = patchbay_ptr->next_client_id++;
  343. INIT_LIST_HEAD(&client_ptr->ports);
  344. pthread_mutex_lock(&patchbay_ptr->lock);
  345. list_add_tail(&client_ptr->siblings, &patchbay_ptr->graph.clients);
  346. patchbay_ptr->graph.version++;
  347. jack_controller_patchbay_send_signal_client_appeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name);
  348. jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
  349. pthread_mutex_unlock(&patchbay_ptr->lock);
  350. return client_ptr;
  351. fail_free_client:
  352. free(client_ptr);
  353. fail:
  354. return NULL;
  355. }
  356. static
  357. void
  358. jack_controller_patchbay_destroy_client(
  359. struct jack_controller_patchbay *patchbay_ptr,
  360. struct jack_graph_client *client_ptr)
  361. {
  362. jack_info("Client '%s' with PID %d is out", client_ptr->name, client_ptr->pid);
  363. pthread_mutex_lock(&patchbay_ptr->lock);
  364. list_del(&client_ptr->siblings);
  365. patchbay_ptr->graph.version++;
  366. jack_controller_patchbay_send_signal_client_disappeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name);
  367. jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
  368. pthread_mutex_unlock(&patchbay_ptr->lock);
  369. free(client_ptr->name);
  370. free(client_ptr);
  371. }
  372. static
  373. void
  374. jack_controller_patchbay_destroy_client_by_name(
  375. struct jack_controller_patchbay *patchbay_ptr,
  376. const char *client_name) /* '\0' terminated */
  377. {
  378. struct jack_graph_client *client_ptr;
  379. client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name));
  380. if (client_ptr == NULL)
  381. {
  382. jack_error("Cannot destroy unknown client '%s'", client_name);
  383. return;
  384. }
  385. jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr);
  386. }
  387. static
  388. void
  389. jack_controller_patchbay_new_port(
  390. struct jack_controller_patchbay *patchbay_ptr,
  391. const char *port_full_name,
  392. uint32_t port_flags,
  393. uint32_t port_type)
  394. {
  395. struct jack_graph_client *client_ptr;
  396. struct jack_graph_port *port_ptr;
  397. const char *port_short_name;
  398. size_t client_name_len;
  399. //jack_info("new port: %s", port_full_name);
  400. port_short_name = strchr(port_full_name, ':');
  401. if (port_short_name == NULL)
  402. {
  403. jack_error("port name '%s' does not contain ':' separator char", port_full_name);
  404. return;
  405. }
  406. port_short_name++; /* skip ':' separator char */
  407. client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */
  408. client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len);
  409. if (client_ptr == NULL)
  410. {
  411. client_ptr = jack_controller_patchbay_create_client(patchbay_ptr, port_full_name, client_name_len);
  412. if (client_ptr == NULL)
  413. {
  414. jack_error("Creation of new jack_graph client failed.");
  415. return;
  416. }
  417. }
  418. port_ptr = malloc(sizeof(struct jack_graph_port));
  419. if (port_ptr == NULL)
  420. {
  421. jack_error("Memory allocation of jack_graph_port structure failed.");
  422. return;
  423. }
  424. port_ptr->name = strdup(port_short_name);
  425. if (port_ptr->name == NULL)
  426. {
  427. jack_error("strdup() call for port name '%s' failed.", port_short_name);
  428. free(port_ptr);
  429. return;
  430. }
  431. port_ptr->id = patchbay_ptr->next_port_id++;
  432. port_ptr->flags = port_flags;
  433. port_ptr->type = port_type;
  434. port_ptr->client = client_ptr;
  435. pthread_mutex_lock(&patchbay_ptr->lock);
  436. list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
  437. list_add_tail(&port_ptr->siblings_graph, &patchbay_ptr->graph.ports);
  438. patchbay_ptr->graph.version++;
  439. jack_controller_patchbay_send_signal_port_appeared(
  440. patchbay_ptr->graph.version,
  441. client_ptr->id,
  442. client_ptr->name,
  443. port_ptr->id,
  444. port_ptr->name,
  445. port_ptr->flags,
  446. port_ptr->type);
  447. jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
  448. pthread_mutex_unlock(&patchbay_ptr->lock);
  449. }
  450. static
  451. void
  452. jack_controller_patchbay_remove_port(
  453. struct jack_controller_patchbay *patchbay_ptr,
  454. struct jack_graph_port *port_ptr)
  455. {
  456. //jack_info("remove port: %s", port_ptr->name);
  457. pthread_mutex_lock(&patchbay_ptr->lock);
  458. list_del(&port_ptr->siblings_client);
  459. list_del(&port_ptr->siblings_graph);
  460. patchbay_ptr->graph.version++;
  461. jack_controller_patchbay_send_signal_port_disappeared(patchbay_ptr->graph.version, port_ptr->client->id, port_ptr->client->name, port_ptr->id, port_ptr->name);
  462. jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
  463. pthread_mutex_unlock(&patchbay_ptr->lock);
  464. free(port_ptr->name);
  465. free(port_ptr);
  466. }
  467. static
  468. struct jack_graph_port *
  469. jack_controller_patchbay_find_port_by_id(
  470. struct jack_controller_patchbay *patchbay_ptr,
  471. uint64_t port_id)
  472. {
  473. struct list_head *node_ptr;
  474. struct jack_graph_port *port_ptr;
  475. list_for_each(node_ptr, &patchbay_ptr->graph.ports)
  476. {
  477. port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_graph);
  478. if (port_ptr->id == port_id)
  479. {
  480. return port_ptr;
  481. }
  482. }
  483. return NULL;
  484. }
  485. static
  486. struct jack_graph_port *
  487. jack_controller_patchbay_find_client_port_by_name(
  488. struct jack_controller_patchbay *patchbay_ptr,
  489. struct jack_graph_client *client_ptr,
  490. const char *port_name)
  491. {
  492. struct list_head *node_ptr;
  493. struct jack_graph_port *port_ptr;
  494. list_for_each(node_ptr, &client_ptr->ports)
  495. {
  496. port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_client);
  497. if (strcmp(port_ptr->name, port_name) == 0)
  498. {
  499. return port_ptr;
  500. }
  501. }
  502. return NULL;
  503. }
  504. static
  505. struct jack_graph_port *
  506. jack_controller_patchbay_find_port_by_full_name(
  507. struct jack_controller_patchbay *patchbay_ptr,
  508. const char *port_full_name)
  509. {
  510. const char *port_short_name;
  511. size_t client_name_len;
  512. struct jack_graph_client *client_ptr;
  513. //jack_info("name: %s", port_full_name);
  514. port_short_name = strchr(port_full_name, ':');
  515. if (port_short_name == NULL)
  516. {
  517. jack_error("port name '%s' does not contain ':' separator char", port_full_name);
  518. return NULL;
  519. }
  520. port_short_name++; /* skip ':' separator char */
  521. client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */
  522. client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len);
  523. if (client_ptr == NULL)
  524. {
  525. jack_error("cannot find client of port '%s'", port_full_name);
  526. return NULL;
  527. }
  528. return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_short_name);
  529. }
  530. static
  531. struct jack_graph_port *
  532. jack_controller_patchbay_find_port_by_names(
  533. struct jack_controller_patchbay *patchbay_ptr,
  534. const char *client_name,
  535. const char *port_name)
  536. {
  537. struct jack_graph_client *client_ptr;
  538. client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name));
  539. if (client_ptr == NULL)
  540. {
  541. jack_error("cannot find client '%s'", client_name);
  542. return NULL;
  543. }
  544. return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_name);
  545. }
  546. static
  547. struct jack_graph_connection *
  548. jack_controller_patchbay_create_connection(
  549. struct jack_controller_patchbay *patchbay_ptr,
  550. struct jack_graph_port *port1_ptr,
  551. struct jack_graph_port *port2_ptr)
  552. {
  553. struct jack_graph_connection * connection_ptr;
  554. connection_ptr = malloc(sizeof(struct jack_graph_connection));
  555. if (connection_ptr == NULL)
  556. {
  557. jack_error("Memory allocation of jack_graph_connection structure failed.");
  558. return NULL;
  559. }
  560. connection_ptr->id = patchbay_ptr->next_connection_id++;
  561. connection_ptr->port1 = port1_ptr;
  562. connection_ptr->port2 = port2_ptr;
  563. pthread_mutex_lock(&patchbay_ptr->lock);
  564. list_add_tail(&connection_ptr->siblings, &patchbay_ptr->graph.connections);
  565. patchbay_ptr->graph.version++;
  566. jack_controller_patchbay_send_signal_ports_connected(
  567. patchbay_ptr->graph.version,
  568. port1_ptr->client->id,
  569. port1_ptr->client->name,
  570. port1_ptr->id,
  571. port1_ptr->name,
  572. port2_ptr->client->id,
  573. port2_ptr->client->name,
  574. port2_ptr->id,
  575. port2_ptr->name,
  576. connection_ptr->id);
  577. jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
  578. pthread_mutex_unlock(&patchbay_ptr->lock);
  579. return connection_ptr;
  580. }
  581. static
  582. void
  583. jack_controller_patchbay_destroy_connection(
  584. struct jack_controller_patchbay *patchbay_ptr,
  585. struct jack_graph_connection *connection_ptr)
  586. {
  587. pthread_mutex_lock(&patchbay_ptr->lock);
  588. list_del(&connection_ptr->siblings);
  589. patchbay_ptr->graph.version++;
  590. jack_controller_patchbay_send_signal_ports_disconnected(
  591. patchbay_ptr->graph.version,
  592. connection_ptr->port1->client->id,
  593. connection_ptr->port1->client->name,
  594. connection_ptr->port1->id,
  595. connection_ptr->port1->name,
  596. connection_ptr->port2->client->id,
  597. connection_ptr->port2->client->name,
  598. connection_ptr->port2->id,
  599. connection_ptr->port2->name,
  600. connection_ptr->id);
  601. jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
  602. pthread_mutex_unlock(&patchbay_ptr->lock);
  603. free(connection_ptr);
  604. }
  605. static
  606. struct jack_graph_connection *
  607. jack_controller_patchbay_find_connection(
  608. struct jack_controller_patchbay *patchbay_ptr,
  609. struct jack_graph_port *port1_ptr,
  610. struct jack_graph_port *port2_ptr)
  611. {
  612. struct list_head *node_ptr;
  613. struct jack_graph_connection *connection_ptr;
  614. list_for_each(node_ptr, &patchbay_ptr->graph.connections)
  615. {
  616. connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings);
  617. if ((connection_ptr->port1 == port1_ptr &&
  618. connection_ptr->port2 == port2_ptr) ||
  619. (connection_ptr->port1 == port2_ptr &&
  620. connection_ptr->port2 == port1_ptr))
  621. {
  622. return connection_ptr;
  623. }
  624. }
  625. return NULL;
  626. }
  627. static
  628. struct jack_graph_connection *
  629. jack_controller_patchbay_find_connection_by_id(
  630. struct jack_controller_patchbay *patchbay_ptr,
  631. uint64_t connection_id)
  632. {
  633. struct list_head *node_ptr;
  634. struct jack_graph_connection *connection_ptr;
  635. list_for_each(node_ptr, &patchbay_ptr->graph.connections)
  636. {
  637. connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings);
  638. if (connection_ptr->id == connection_id)
  639. {
  640. return connection_ptr;
  641. }
  642. }
  643. return NULL;
  644. }
  645. static
  646. bool
  647. jack_controller_patchbay_connect(
  648. struct jack_dbus_method_call *dbus_call_ptr,
  649. struct jack_controller *controller_ptr,
  650. struct jack_graph_port *port1_ptr,
  651. struct jack_graph_port *port2_ptr)
  652. {
  653. int ret;
  654. char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  655. char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  656. sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name);
  657. sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name);
  658. ret = jack_connect(controller_ptr->client, port1_name, port2_name);
  659. if (ret != 0)
  660. {
  661. jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret);
  662. return false;
  663. }
  664. return true;
  665. }
  666. static
  667. bool
  668. jack_controller_patchbay_disconnect(
  669. struct jack_dbus_method_call *dbus_call_ptr,
  670. struct jack_controller *controller_ptr,
  671. struct jack_graph_port *port1_ptr,
  672. struct jack_graph_port *port2_ptr)
  673. {
  674. int ret;
  675. char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  676. char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  677. sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name);
  678. sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name);
  679. ret = jack_disconnect(controller_ptr->client, port1_name, port2_name);
  680. if (ret != 0)
  681. {
  682. jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_disconnect() failed with %d", ret);
  683. return false;
  684. }
  685. return true;
  686. }
  687. #define controller_ptr ((struct jack_controller *)call->context)
  688. #define patchbay_ptr ((struct jack_controller_patchbay *)controller_ptr->patchbay_context)
  689. static
  690. void
  691. jack_controller_dbus_get_all_ports(
  692. struct jack_dbus_method_call * call)
  693. {
  694. struct list_head * client_node_ptr;
  695. struct list_head * port_node_ptr;
  696. struct jack_graph_client * client_ptr;
  697. struct jack_graph_port * port_ptr;
  698. DBusMessageIter iter, sub_iter;
  699. char fullname[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  700. char *fullname_var = fullname;
  701. if (!controller_ptr->started)
  702. {
  703. jack_dbus_error(
  704. call,
  705. JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
  706. "Can't execute this method with stopped JACK server");
  707. return;
  708. }
  709. call->reply = dbus_message_new_method_return (call->message);
  710. if (!call->reply)
  711. {
  712. goto fail;
  713. }
  714. dbus_message_iter_init_append (call->reply, &iter);
  715. if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
  716. {
  717. goto fail_unref;
  718. }
  719. pthread_mutex_lock(&patchbay_ptr->lock);
  720. list_for_each(client_node_ptr, &patchbay_ptr->graph.clients)
  721. {
  722. client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings);
  723. list_for_each(port_node_ptr, &client_ptr->ports)
  724. {
  725. port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client);
  726. jack_info("%s:%s", client_ptr->name, port_ptr->name);
  727. sprintf(fullname, "%s:%s", client_ptr->name, port_ptr->name);
  728. if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, &fullname_var))
  729. {
  730. pthread_mutex_unlock(&patchbay_ptr->lock);
  731. dbus_message_iter_close_container (&iter, &sub_iter);
  732. goto fail_unref;
  733. }
  734. }
  735. }
  736. pthread_mutex_unlock(&patchbay_ptr->lock);
  737. if (!dbus_message_iter_close_container (&iter, &sub_iter))
  738. {
  739. goto fail_unref;
  740. }
  741. return;
  742. fail_unref:
  743. dbus_message_unref (call->reply);
  744. call->reply = NULL;
  745. fail:
  746. jack_error ("Ran out of memory trying to construct method return");
  747. }
  748. static
  749. void
  750. jack_controller_dbus_get_graph(
  751. struct jack_dbus_method_call * call)
  752. {
  753. struct list_head * client_node_ptr;
  754. struct list_head * port_node_ptr;
  755. struct list_head * connection_node_ptr;
  756. struct jack_graph_client * client_ptr;
  757. struct jack_graph_port * port_ptr;
  758. struct jack_graph_connection * connection_ptr;
  759. DBusMessageIter iter;
  760. DBusMessageIter clients_array_iter;
  761. DBusMessageIter client_struct_iter;
  762. DBusMessageIter ports_array_iter;
  763. DBusMessageIter port_struct_iter;
  764. dbus_uint64_t version;
  765. DBusMessageIter connections_array_iter;
  766. DBusMessageIter connection_struct_iter;
  767. if (!controller_ptr->started)
  768. {
  769. jack_dbus_error(
  770. call,
  771. JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
  772. "Can't execute this method with stopped JACK server");
  773. return;
  774. }
  775. if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT64, &version, DBUS_TYPE_INVALID))
  776. {
  777. /* The method call had invalid arguments meaning that
  778. * jack_dbus_get_method_args() has constructed an error for us.
  779. */
  780. goto exit;
  781. }
  782. //jack_info("Getting graph, know version is %" PRIu32, version);
  783. call->reply = dbus_message_new_method_return(call->message);
  784. if (!call->reply)
  785. {
  786. jack_error("Ran out of memory trying to construct method return");
  787. goto exit;
  788. }
  789. dbus_message_iter_init_append (call->reply, &iter);
  790. pthread_mutex_lock(&patchbay_ptr->lock);
  791. if (version > patchbay_ptr->graph.version)
  792. {
  793. jack_dbus_error(
  794. call,
  795. JACK_DBUS_ERROR_INVALID_ARGS,
  796. "known graph version %" PRIu64 " is newer than actual version %" PRIu64,
  797. version,
  798. patchbay_ptr->graph.version);
  799. pthread_mutex_unlock(&patchbay_ptr->lock);
  800. goto exit;
  801. }
  802. if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &patchbay_ptr->graph.version))
  803. {
  804. goto nomem_unlock;
  805. }
  806. if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter))
  807. {
  808. goto nomem_unlock;
  809. }
  810. if (version < patchbay_ptr->graph.version)
  811. {
  812. list_for_each(client_node_ptr, &patchbay_ptr->graph.clients)
  813. {
  814. client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings);
  815. if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter))
  816. {
  817. goto nomem_close_clients_array;
  818. }
  819. if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id))
  820. {
  821. goto nomem_close_client_struct;
  822. }
  823. if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name))
  824. {
  825. goto nomem_close_client_struct;
  826. }
  827. if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter))
  828. {
  829. goto nomem_close_client_struct;
  830. }
  831. list_for_each(port_node_ptr, &client_ptr->ports)
  832. {
  833. port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client);
  834. if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter))
  835. {
  836. goto nomem_close_ports_array;
  837. }
  838. if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id))
  839. {
  840. goto nomem_close_port_struct;
  841. }
  842. if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name))
  843. {
  844. goto nomem_close_port_struct;
  845. }
  846. if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags))
  847. {
  848. goto nomem_close_port_struct;
  849. }
  850. if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type))
  851. {
  852. goto nomem_close_port_struct;
  853. }
  854. if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter))
  855. {
  856. goto nomem_close_ports_array;
  857. }
  858. }
  859. if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter))
  860. {
  861. goto nomem_close_client_struct;
  862. }
  863. if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter))
  864. {
  865. goto nomem_close_clients_array;
  866. }
  867. }
  868. }
  869. if (!dbus_message_iter_close_container(&iter, &clients_array_iter))
  870. {
  871. goto nomem_unlock;
  872. }
  873. if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter))
  874. {
  875. goto nomem_unlock;
  876. }
  877. if (version < patchbay_ptr->graph.version)
  878. {
  879. list_for_each(connection_node_ptr, &patchbay_ptr->graph.connections)
  880. {
  881. connection_ptr = list_entry(connection_node_ptr, struct jack_graph_connection, siblings);
  882. if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter))
  883. {
  884. goto nomem_close_connections_array;
  885. }
  886. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->client->id))
  887. {
  888. goto nomem_close_connection_struct;
  889. }
  890. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->client->name))
  891. {
  892. goto nomem_close_connection_struct;
  893. }
  894. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->id))
  895. {
  896. goto nomem_close_connection_struct;
  897. }
  898. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->name))
  899. {
  900. goto nomem_close_connection_struct;
  901. }
  902. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->client->id))
  903. {
  904. goto nomem_close_connection_struct;
  905. }
  906. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->client->name))
  907. {
  908. goto nomem_close_connection_struct;
  909. }
  910. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->id))
  911. {
  912. goto nomem_close_connection_struct;
  913. }
  914. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->name))
  915. {
  916. goto nomem_close_connection_struct;
  917. }
  918. if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id))
  919. {
  920. goto nomem_close_connection_struct;
  921. }
  922. if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter))
  923. {
  924. goto nomem_close_connections_array;
  925. }
  926. }
  927. }
  928. if (!dbus_message_iter_close_container(&iter, &connections_array_iter))
  929. {
  930. goto nomem_unlock;
  931. }
  932. pthread_mutex_unlock(&patchbay_ptr->lock);
  933. return;
  934. nomem_close_connection_struct:
  935. dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter);
  936. nomem_close_connections_array:
  937. dbus_message_iter_close_container(&iter, &connections_array_iter);
  938. goto nomem_unlock;
  939. nomem_close_port_struct:
  940. dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter);
  941. nomem_close_ports_array:
  942. dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter);
  943. nomem_close_client_struct:
  944. dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter);
  945. nomem_close_clients_array:
  946. dbus_message_iter_close_container(&iter, &clients_array_iter);
  947. nomem_unlock:
  948. pthread_mutex_unlock(&patchbay_ptr->lock);
  949. //nomem:
  950. dbus_message_unref(call->reply);
  951. call->reply = NULL;
  952. jack_error("Ran out of memory trying to construct method return");
  953. exit:
  954. return;
  955. }
  956. static
  957. void
  958. jack_controller_dbus_connect_ports_by_name(
  959. struct jack_dbus_method_call * call)
  960. {
  961. const char * client1_name;
  962. const char * port1_name;
  963. const char * client2_name;
  964. const char * port2_name;
  965. struct jack_graph_port *port1_ptr;
  966. struct jack_graph_port *port2_ptr;
  967. /* jack_info("jack_controller_dbus_connect_ports_by_name() called."); */
  968. if (!controller_ptr->started)
  969. {
  970. jack_dbus_error(
  971. call,
  972. JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
  973. "Can't execute this method with stopped JACK server");
  974. return;
  975. }
  976. if (!jack_dbus_get_method_args(
  977. call,
  978. DBUS_TYPE_STRING,
  979. &client1_name,
  980. DBUS_TYPE_STRING,
  981. &port1_name,
  982. DBUS_TYPE_STRING,
  983. &client2_name,
  984. DBUS_TYPE_STRING,
  985. &port2_name,
  986. DBUS_TYPE_INVALID))
  987. {
  988. /* The method call had invalid arguments meaning that
  989. * jack_dbus_get_method_args() has constructed an error for us.
  990. */
  991. return;
  992. }
  993. /* jack_info("connecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */
  994. pthread_mutex_lock(&patchbay_ptr->lock);
  995. port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name);
  996. if (port1_ptr == NULL)
  997. {
  998. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name);
  999. goto unlock;
  1000. }
  1001. port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name);
  1002. if (port2_ptr == NULL)
  1003. {
  1004. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name);
  1005. goto unlock;
  1006. }
  1007. if (!jack_controller_patchbay_connect(
  1008. call,
  1009. controller_ptr,
  1010. port1_ptr,
  1011. port2_ptr))
  1012. {
  1013. /* jack_controller_patchbay_connect() constructed error reply */
  1014. goto unlock;
  1015. }
  1016. jack_dbus_construct_method_return_empty(call);
  1017. unlock:
  1018. pthread_mutex_unlock(&patchbay_ptr->lock);
  1019. }
  1020. static
  1021. void
  1022. jack_controller_dbus_connect_ports_by_id(
  1023. struct jack_dbus_method_call * call)
  1024. {
  1025. dbus_uint64_t port1_id;
  1026. dbus_uint64_t port2_id;
  1027. struct jack_graph_port *port1_ptr;
  1028. struct jack_graph_port *port2_ptr;
  1029. /* jack_info("jack_controller_dbus_connect_ports_by_id() called."); */
  1030. if (!controller_ptr->started)
  1031. {
  1032. jack_dbus_error(
  1033. call,
  1034. JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
  1035. "Can't execute this method with stopped JACK server");
  1036. return;
  1037. }
  1038. if (!jack_dbus_get_method_args(
  1039. call,
  1040. DBUS_TYPE_UINT64,
  1041. &port1_id,
  1042. DBUS_TYPE_UINT64,
  1043. &port2_id,
  1044. DBUS_TYPE_INVALID))
  1045. {
  1046. /* The method call had invalid arguments meaning that
  1047. * jack_dbus_get_method_args() has constructed an error for us.
  1048. */
  1049. return;
  1050. }
  1051. pthread_mutex_lock(&patchbay_ptr->lock);
  1052. port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id);
  1053. if (port1_ptr == NULL)
  1054. {
  1055. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id);
  1056. goto unlock;
  1057. }
  1058. port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id);
  1059. if (port2_ptr == NULL)
  1060. {
  1061. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id);
  1062. goto unlock;
  1063. }
  1064. if (!jack_controller_patchbay_connect(
  1065. call,
  1066. controller_ptr,
  1067. port1_ptr,
  1068. port2_ptr))
  1069. {
  1070. /* jack_controller_patchbay_connect() constructed error reply */
  1071. goto unlock;
  1072. }
  1073. jack_dbus_construct_method_return_empty(call);
  1074. unlock:
  1075. pthread_mutex_unlock(&patchbay_ptr->lock);
  1076. }
  1077. static
  1078. void
  1079. jack_controller_dbus_disconnect_ports_by_name(
  1080. struct jack_dbus_method_call * call)
  1081. {
  1082. const char * client1_name;
  1083. const char * port1_name;
  1084. const char * client2_name;
  1085. const char * port2_name;
  1086. struct jack_graph_port *port1_ptr;
  1087. struct jack_graph_port *port2_ptr;
  1088. /* jack_info("jack_controller_dbus_disconnect_ports_by_name() called."); */
  1089. if (!controller_ptr->started)
  1090. {
  1091. jack_dbus_error(
  1092. call,
  1093. JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
  1094. "Can't execute this method with stopped JACK server");
  1095. return;
  1096. }
  1097. if (!jack_dbus_get_method_args(
  1098. call,
  1099. DBUS_TYPE_STRING,
  1100. &client1_name,
  1101. DBUS_TYPE_STRING,
  1102. &port1_name,
  1103. DBUS_TYPE_STRING,
  1104. &client2_name,
  1105. DBUS_TYPE_STRING,
  1106. &port2_name,
  1107. DBUS_TYPE_INVALID))
  1108. {
  1109. /* The method call had invalid arguments meaning that
  1110. * jack_dbus_get_method_args() has constructed an error for us.
  1111. */
  1112. return;
  1113. }
  1114. /* jack_info("disconnecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */
  1115. pthread_mutex_lock(&patchbay_ptr->lock);
  1116. port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name);
  1117. if (port1_ptr == NULL)
  1118. {
  1119. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name);
  1120. goto unlock;
  1121. }
  1122. port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name);
  1123. if (port2_ptr == NULL)
  1124. {
  1125. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name);
  1126. goto unlock;
  1127. }
  1128. if (!jack_controller_patchbay_disconnect(
  1129. call,
  1130. controller_ptr,
  1131. port1_ptr,
  1132. port2_ptr))
  1133. {
  1134. /* jack_controller_patchbay_connect() constructed error reply */
  1135. goto unlock;
  1136. }
  1137. jack_dbus_construct_method_return_empty(call);
  1138. unlock:
  1139. pthread_mutex_unlock(&patchbay_ptr->lock);
  1140. }
  1141. static
  1142. void
  1143. jack_controller_dbus_disconnect_ports_by_id(
  1144. struct jack_dbus_method_call * call)
  1145. {
  1146. dbus_uint64_t port1_id;
  1147. dbus_uint64_t port2_id;
  1148. struct jack_graph_port *port1_ptr;
  1149. struct jack_graph_port *port2_ptr;
  1150. /* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */
  1151. if (!controller_ptr->started)
  1152. {
  1153. jack_dbus_error(
  1154. call,
  1155. JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
  1156. "Can't execute this method with stopped JACK server");
  1157. return;
  1158. }
  1159. if (!jack_dbus_get_method_args(
  1160. call,
  1161. DBUS_TYPE_UINT64,
  1162. &port1_id,
  1163. DBUS_TYPE_UINT64,
  1164. &port2_id,
  1165. DBUS_TYPE_INVALID))
  1166. {
  1167. /* The method call had invalid arguments meaning that
  1168. * jack_dbus_get_method_args() has constructed an error for us.
  1169. */
  1170. return;
  1171. }
  1172. pthread_mutex_lock(&patchbay_ptr->lock);
  1173. port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id);
  1174. if (port1_ptr == NULL)
  1175. {
  1176. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id);
  1177. goto unlock;
  1178. }
  1179. port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id);
  1180. if (port2_ptr == NULL)
  1181. {
  1182. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id);
  1183. goto unlock;
  1184. }
  1185. if (!jack_controller_patchbay_disconnect(
  1186. call,
  1187. controller_ptr,
  1188. port1_ptr,
  1189. port2_ptr))
  1190. {
  1191. /* jack_controller_patchbay_connect() constructed error reply */
  1192. goto unlock;
  1193. }
  1194. jack_dbus_construct_method_return_empty(call);
  1195. unlock:
  1196. pthread_mutex_unlock(&patchbay_ptr->lock);
  1197. }
  1198. static
  1199. void
  1200. jack_controller_dbus_disconnect_ports_by_connection_id(
  1201. struct jack_dbus_method_call * call)
  1202. {
  1203. dbus_uint64_t connection_id;
  1204. struct jack_graph_connection *connection_ptr;
  1205. /* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */
  1206. if (!jack_dbus_get_method_args(
  1207. call,
  1208. DBUS_TYPE_UINT64,
  1209. &connection_id,
  1210. DBUS_TYPE_INVALID))
  1211. {
  1212. /* The method call had invalid arguments meaning that
  1213. * jack_dbus_get_method_args() has constructed an error for us.
  1214. */
  1215. return;
  1216. }
  1217. pthread_mutex_lock(&patchbay_ptr->lock);
  1218. connection_ptr = jack_controller_patchbay_find_connection_by_id(patchbay_ptr, connection_id);
  1219. if (connection_ptr == NULL)
  1220. {
  1221. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find connection %" PRIu64, connection_id);
  1222. goto unlock;
  1223. }
  1224. if (!jack_controller_patchbay_disconnect(
  1225. call,
  1226. controller_ptr,
  1227. connection_ptr->port1,
  1228. connection_ptr->port2))
  1229. {
  1230. /* jack_controller_patchbay_connect() constructed error reply */
  1231. goto unlock;
  1232. }
  1233. jack_dbus_construct_method_return_empty(call);
  1234. unlock:
  1235. pthread_mutex_unlock(&patchbay_ptr->lock);
  1236. }
  1237. static
  1238. void
  1239. jack_controller_dbus_get_client_pid(
  1240. struct jack_dbus_method_call * call)
  1241. {
  1242. dbus_uint64_t client_id;
  1243. struct jack_graph_client *client_ptr;
  1244. message_arg_t arg;
  1245. /* jack_info("jack_controller_dbus_get_client_pid() called."); */
  1246. if (!jack_dbus_get_method_args(
  1247. call,
  1248. DBUS_TYPE_UINT64,
  1249. &client_id,
  1250. DBUS_TYPE_INVALID))
  1251. {
  1252. /* The method call had invalid arguments meaning that
  1253. * jack_dbus_get_method_args() has constructed an error for us.
  1254. */
  1255. return;
  1256. }
  1257. pthread_mutex_lock(&patchbay_ptr->lock);
  1258. client_ptr = jack_controller_patchbay_find_client_by_id(patchbay_ptr, client_id);
  1259. if (client_ptr == NULL)
  1260. {
  1261. jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find client %" PRIu64, client_id);
  1262. goto unlock;
  1263. }
  1264. arg.int64 = client_ptr->pid;
  1265. jack_dbus_construct_method_return_single(call, DBUS_TYPE_INT64, arg);
  1266. unlock:
  1267. pthread_mutex_unlock(&patchbay_ptr->lock);
  1268. }
  1269. #undef controller_ptr
  1270. #define controller_ptr ((struct jack_controller *)context)
  1271. static
  1272. int
  1273. jack_controller_graph_order_callback(
  1274. void *context)
  1275. {
  1276. const char **ports;
  1277. int i;
  1278. jack_port_t *port_ptr;
  1279. if (patchbay_ptr->graph.version > 1)
  1280. {
  1281. /* we use this only for initial catchup */
  1282. return 0;
  1283. }
  1284. ports = jack_get_ports(controller_ptr->client, NULL, NULL, 0);
  1285. if (ports)
  1286. {
  1287. for (i = 0; ports[i]; ++i)
  1288. {
  1289. jack_info("graph reorder: new port '%s'", ports[i]);
  1290. port_ptr = jack_port_by_name(controller_ptr->client, ports[i]);;
  1291. jack_controller_patchbay_new_port(patchbay_ptr, ports[i], jack_port_flags(port_ptr), jack_port_type_id(port_ptr));
  1292. }
  1293. free(ports);
  1294. }
  1295. if (patchbay_ptr->graph.version == 1)
  1296. {
  1297. /* we have empty initial graph, increment graph version,
  1298. so we don't do jack_get_ports() again,
  1299. on next next graph change */
  1300. patchbay_ptr->graph.version++;
  1301. }
  1302. return 0;
  1303. }
  1304. void
  1305. jack_controller_client_registration_callback(
  1306. const char *client_name,
  1307. int created,
  1308. void *context)
  1309. {
  1310. if (created)
  1311. {
  1312. jack_log("client '%s' created", client_name);
  1313. jack_controller_patchbay_create_client(patchbay_ptr, client_name, strlen(client_name));
  1314. }
  1315. else
  1316. {
  1317. jack_log("client '%s' destroyed", client_name);
  1318. jack_controller_patchbay_destroy_client_by_name(patchbay_ptr, client_name);
  1319. }
  1320. }
  1321. void
  1322. jack_controller_port_registration_callback(
  1323. jack_port_id_t port_id,
  1324. int created,
  1325. void *context)
  1326. {
  1327. jack_port_t *port_ptr;
  1328. struct jack_graph_port *graph_port_ptr;
  1329. const char *port_name;
  1330. port_ptr = jack_port_by_id(controller_ptr->client, port_id);
  1331. port_name = jack_port_name(port_ptr);
  1332. if (created)
  1333. {
  1334. jack_log("port '%s' created", port_name);
  1335. jack_controller_patchbay_new_port(patchbay_ptr, port_name, jack_port_flags(port_ptr), jack_port_type_id(port_ptr));
  1336. }
  1337. else
  1338. {
  1339. jack_log("port '%s' destroyed", port_name);
  1340. graph_port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port_name);
  1341. if (graph_port_ptr == NULL)
  1342. {
  1343. jack_error("Failed to find port '%s' to destroy", port_name);
  1344. return;
  1345. }
  1346. jack_controller_patchbay_remove_port(patchbay_ptr, graph_port_ptr);
  1347. }
  1348. }
  1349. void
  1350. jack_controller_port_connect_callback(
  1351. jack_port_id_t port1_id,
  1352. jack_port_id_t port2_id,
  1353. int connect,
  1354. void *context)
  1355. {
  1356. jack_port_t *port1;
  1357. jack_port_t *port2;
  1358. const char *port1_name;
  1359. const char *port2_name;
  1360. struct jack_graph_port *port1_ptr;
  1361. struct jack_graph_port *port2_ptr;
  1362. struct jack_graph_connection *connection_ptr;
  1363. port1 = jack_port_by_id(controller_ptr->client, port1_id);
  1364. port2 = jack_port_by_id(controller_ptr->client, port2_id);
  1365. port1_name = jack_port_name(port1);
  1366. port2_name = jack_port_name(port2);
  1367. port1_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port1_name);
  1368. if (port1_ptr == NULL)
  1369. {
  1370. jack_error("Failed to find port '%s' to [dis]connect", port1_name);
  1371. return;
  1372. }
  1373. port2_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port2_name);
  1374. if (port2_ptr == NULL)
  1375. {
  1376. jack_error("Failed to find port '%s' to [dis]connect", port2_name);
  1377. return;
  1378. }
  1379. if (connect)
  1380. {
  1381. jack_info("Connecting '%s' to '%s'", port1_name, port2_name);
  1382. connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr);
  1383. if (connection_ptr != NULL)
  1384. {
  1385. jack_error("'%s' and '%s' are already connected", port1_name, port2_name);
  1386. return;
  1387. }
  1388. jack_controller_patchbay_create_connection(patchbay_ptr, port1_ptr, port2_ptr);
  1389. }
  1390. else
  1391. {
  1392. jack_info("Disconnecting '%s' from '%s'", port1_name, port2_name);
  1393. connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr);
  1394. if (connection_ptr == NULL)
  1395. {
  1396. jack_error("Cannot find connection being removed");
  1397. return;
  1398. }
  1399. jack_controller_patchbay_destroy_connection(patchbay_ptr, connection_ptr);
  1400. }
  1401. }
  1402. void jack_controller_port_rename_callback(jack_port_id_t port, const char * old_name, const char * new_name, void * context)
  1403. {
  1404. struct jack_graph_port * port_ptr;
  1405. const char * port_new_short_name;
  1406. const char * port_old_short_name;
  1407. char * name_buffer;
  1408. jack_info("port renamed: '%s' -> '%s'", old_name, new_name);
  1409. port_new_short_name = strchr(new_name, ':');
  1410. if (port_new_short_name == NULL)
  1411. {
  1412. jack_error("renamed port new name '%s' does not contain ':' separator char", new_name);
  1413. return;
  1414. }
  1415. port_new_short_name++; /* skip ':' separator char */
  1416. port_old_short_name = strchr(old_name, ':');
  1417. if (port_old_short_name == NULL)
  1418. {
  1419. jack_error("renamed port old name '%s' does not contain ':' separator char", old_name);
  1420. return;
  1421. }
  1422. port_old_short_name++; /* skip ':' separator char */
  1423. port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, old_name);
  1424. if (port_ptr == NULL)
  1425. {
  1426. jack_error("renamed port '%s' not found", old_name);
  1427. return;
  1428. }
  1429. name_buffer = strdup(port_new_short_name);
  1430. if (name_buffer == NULL)
  1431. {
  1432. jack_error("strdup() call for port name '%s' failed.", port_new_short_name);
  1433. return;
  1434. }
  1435. free(port_ptr->name);
  1436. port_ptr->name = name_buffer;
  1437. pthread_mutex_lock(&patchbay_ptr->lock);
  1438. patchbay_ptr->graph.version++;
  1439. jack_controller_patchbay_send_signal_port_renamed(
  1440. patchbay_ptr->graph.version,
  1441. port_ptr->client->id,
  1442. port_ptr->client->name,
  1443. port_ptr->id,
  1444. port_old_short_name,
  1445. port_ptr->name);
  1446. jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
  1447. pthread_mutex_unlock(&patchbay_ptr->lock);
  1448. }
  1449. #undef controller_ptr
  1450. void
  1451. jack_controller_patchbay_uninit(
  1452. struct jack_controller * controller_ptr)
  1453. {
  1454. struct jack_graph_client *client_ptr;
  1455. struct jack_graph_port *port_ptr;
  1456. /* jack_info("jack_controller_patchbay_uninit() called"); */
  1457. while (!list_empty(&patchbay_ptr->graph.ports))
  1458. {
  1459. port_ptr = list_entry(patchbay_ptr->graph.ports.next, struct jack_graph_port, siblings_graph);
  1460. jack_controller_patchbay_remove_port(patchbay_ptr, port_ptr);
  1461. }
  1462. while (!list_empty(&patchbay_ptr->graph.clients))
  1463. {
  1464. client_ptr = list_entry(patchbay_ptr->graph.clients.next, struct jack_graph_client, siblings);
  1465. jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr);
  1466. }
  1467. pthread_mutex_destroy(&patchbay_ptr->lock);
  1468. }
  1469. #undef patchbay_ptr
  1470. bool
  1471. jack_controller_patchbay_init(
  1472. struct jack_controller * controller_ptr)
  1473. {
  1474. int ret;
  1475. struct jack_controller_patchbay * patchbay_ptr;
  1476. pthread_mutexattr_t attr;
  1477. /* jack_info("jack_controller_patchbay_init() called"); */
  1478. patchbay_ptr = malloc(sizeof(struct jack_controller_patchbay));
  1479. if (patchbay_ptr == NULL)
  1480. {
  1481. jack_error("Memory allocation of jack_controller_patchbay structure failed.");
  1482. goto fail;
  1483. }
  1484. ret = pthread_mutexattr_init(&attr);
  1485. if (ret != 0)
  1486. {
  1487. goto fail;
  1488. }
  1489. ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  1490. if (ret != 0)
  1491. {
  1492. goto fail;
  1493. }
  1494. pthread_mutex_init(&patchbay_ptr->lock, &attr);
  1495. INIT_LIST_HEAD(&patchbay_ptr->graph.clients);
  1496. INIT_LIST_HEAD(&patchbay_ptr->graph.ports);
  1497. INIT_LIST_HEAD(&patchbay_ptr->graph.connections);
  1498. patchbay_ptr->graph.version = 1;
  1499. patchbay_ptr->next_client_id = 1;
  1500. patchbay_ptr->next_port_id = 1;
  1501. patchbay_ptr->next_connection_id = 1;
  1502. controller_ptr->patchbay_context = patchbay_ptr;
  1503. ret = jack_set_graph_order_callback(controller_ptr->client, jack_controller_graph_order_callback, controller_ptr);
  1504. if (ret != 0)
  1505. {
  1506. jack_error("jack_set_graph_order_callback() failed with error %d", ret);
  1507. goto fail_uninit_mutex;
  1508. }
  1509. ret = jack_set_client_registration_callback(controller_ptr->client, jack_controller_client_registration_callback, controller_ptr);
  1510. if (ret != 0)
  1511. {
  1512. jack_error("jack_set_client_registration_callback() failed with error %d", ret);
  1513. goto fail_uninit_mutex;
  1514. }
  1515. ret = jack_set_port_registration_callback(controller_ptr->client, jack_controller_port_registration_callback, controller_ptr);
  1516. if (ret != 0)
  1517. {
  1518. jack_error("jack_set_port_registration_callback() failed with error %d", ret);
  1519. goto fail_uninit_mutex;
  1520. }
  1521. ret = jack_set_port_connect_callback(controller_ptr->client, jack_controller_port_connect_callback, controller_ptr);
  1522. if (ret != 0)
  1523. {
  1524. jack_error("jack_set_port_connect_callback() failed with error %d", ret);
  1525. goto fail_uninit_mutex;
  1526. }
  1527. ret = jack_set_port_rename_callback(controller_ptr->client, jack_controller_port_rename_callback, controller_ptr);
  1528. if (ret != 0)
  1529. {
  1530. jack_error("jack_set_port_rename_callback() failed with error %d", ret);
  1531. goto fail_uninit_mutex;
  1532. }
  1533. return true;
  1534. fail_uninit_mutex:
  1535. pthread_mutex_destroy(&patchbay_ptr->lock);
  1536. fail:
  1537. return false;
  1538. }
  1539. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAllPorts)
  1540. JACK_DBUS_METHOD_ARGUMENT("ports_list", "as", true)
  1541. JACK_DBUS_METHOD_ARGUMENTS_END
  1542. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetGraph)
  1543. JACK_DBUS_METHOD_ARGUMENT("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, false)
  1544. JACK_DBUS_METHOD_ARGUMENT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, true)
  1545. JACK_DBUS_METHOD_ARGUMENT("clients_and_ports", "a(tsa(tsuu))", true)
  1546. JACK_DBUS_METHOD_ARGUMENT("connections", "a(tstststst)", true)
  1547. JACK_DBUS_METHOD_ARGUMENTS_END
  1548. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByName)
  1549. JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false)
  1550. JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false)
  1551. JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false)
  1552. JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false)
  1553. JACK_DBUS_METHOD_ARGUMENTS_END
  1554. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByID)
  1555. JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false)
  1556. JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false)
  1557. JACK_DBUS_METHOD_ARGUMENTS_END
  1558. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByName)
  1559. JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false)
  1560. JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false)
  1561. JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false)
  1562. JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false)
  1563. JACK_DBUS_METHOD_ARGUMENTS_END
  1564. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByID)
  1565. JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false)
  1566. JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false)
  1567. JACK_DBUS_METHOD_ARGUMENTS_END
  1568. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByConnectionID)
  1569. JACK_DBUS_METHOD_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING, false)
  1570. JACK_DBUS_METHOD_ARGUMENTS_END
  1571. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientPID)
  1572. JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING, false)
  1573. JACK_DBUS_METHOD_ARGUMENT("process_id", DBUS_TYPE_INT64_AS_STRING, true)
  1574. JACK_DBUS_METHOD_ARGUMENTS_END
  1575. JACK_DBUS_METHODS_BEGIN
  1576. JACK_DBUS_METHOD_DESCRIBE(GetAllPorts, jack_controller_dbus_get_all_ports)
  1577. JACK_DBUS_METHOD_DESCRIBE(GetGraph, jack_controller_dbus_get_graph)
  1578. JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByName, jack_controller_dbus_connect_ports_by_name)
  1579. JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByID, jack_controller_dbus_connect_ports_by_id)
  1580. JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByName, jack_controller_dbus_disconnect_ports_by_name)
  1581. JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByID, jack_controller_dbus_disconnect_ports_by_id)
  1582. JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByConnectionID, jack_controller_dbus_disconnect_ports_by_connection_id)
  1583. JACK_DBUS_METHOD_DESCRIBE(GetClientPID, jack_controller_dbus_get_client_pid)
  1584. JACK_DBUS_METHODS_END
  1585. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(GraphChanged)
  1586. JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
  1587. JACK_DBUS_SIGNAL_ARGUMENTS_END
  1588. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientAppeared)
  1589. JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
  1590. JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
  1591. JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
  1592. JACK_DBUS_SIGNAL_ARGUMENTS_END
  1593. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientDisappeared)
  1594. JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
  1595. JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
  1596. JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
  1597. JACK_DBUS_SIGNAL_ARGUMENTS_END
  1598. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortAppeared)
  1599. JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
  1600. JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
  1601. JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
  1602. JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING)
  1603. JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING)
  1604. JACK_DBUS_SIGNAL_ARGUMENT("port_flags", DBUS_TYPE_UINT32_AS_STRING)
  1605. JACK_DBUS_SIGNAL_ARGUMENT("port_type", DBUS_TYPE_UINT32_AS_STRING)
  1606. JACK_DBUS_SIGNAL_ARGUMENTS_END
  1607. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortDisappeared)
  1608. JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
  1609. JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
  1610. JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
  1611. JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING)
  1612. JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING)
  1613. JACK_DBUS_SIGNAL_ARGUMENTS_END
  1614. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsConnected)
  1615. JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
  1616. JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING)
  1617. JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING)
  1618. JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING)
  1619. JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING)
  1620. JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING)
  1621. JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING)
  1622. JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING)
  1623. JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING)
  1624. JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING)
  1625. JACK_DBUS_SIGNAL_ARGUMENTS_END
  1626. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsDisconnected)
  1627. JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
  1628. JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING)
  1629. JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING)
  1630. JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING)
  1631. JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING)
  1632. JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING)
  1633. JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING)
  1634. JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING)
  1635. JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING)
  1636. JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING)
  1637. JACK_DBUS_SIGNAL_ARGUMENTS_END
  1638. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortRenamed)
  1639. JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
  1640. JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING)
  1641. JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
  1642. JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
  1643. JACK_DBUS_SIGNAL_ARGUMENT("port_old_name", DBUS_TYPE_STRING_AS_STRING)
  1644. JACK_DBUS_SIGNAL_ARGUMENT("port_new_name", DBUS_TYPE_STRING_AS_STRING)
  1645. JACK_DBUS_SIGNAL_ARGUMENTS_END
  1646. JACK_DBUS_SIGNALS_BEGIN
  1647. JACK_DBUS_SIGNAL_DESCRIBE(GraphChanged)
  1648. JACK_DBUS_SIGNAL_DESCRIBE(ClientAppeared)
  1649. JACK_DBUS_SIGNAL_DESCRIBE(ClientDisappeared)
  1650. JACK_DBUS_SIGNAL_DESCRIBE(PortAppeared)
  1651. JACK_DBUS_SIGNAL_DESCRIBE(PortDisappeared)
  1652. JACK_DBUS_SIGNAL_DESCRIBE(PortsConnected)
  1653. JACK_DBUS_SIGNAL_DESCRIBE(PortsDisconnected)
  1654. JACK_DBUS_SIGNAL_DESCRIBE(PortRenamed)
  1655. JACK_DBUS_SIGNALS_END
  1656. JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_patchbay, JACK_DBUS_IFACE_NAME)
  1657. JACK_DBUS_IFACE_EXPOSE_METHODS
  1658. JACK_DBUS_IFACE_EXPOSE_SIGNALS
  1659. JACK_DBUS_IFACE_END