jack1 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.

690 lines
16KB

  1. /*
  2. Copyright (C) 2001-2003 Paul Davis
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. $Id$
  15. */
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <config.h>
  20. #include <jack/jack.h>
  21. #include <jack/types.h>
  22. #include <jack/internal.h>
  23. #include <jack/engine.h>
  24. #include <jack/pool.h>
  25. #include <jack/port.h>
  26. #include <jack/jslist.h>
  27. #include "local.h"
  28. static void jack_audio_port_mixdown (jack_port_t *port,
  29. jack_nframes_t nframes);
  30. /* These function pointers are local to each address space. For
  31. * internal clients they reside within jackd; for external clients in
  32. * the application process. */
  33. jack_port_functions_t jack_builtin_audio_functions = {
  34. .mixdown = jack_audio_port_mixdown,
  35. };
  36. jack_port_functions_t jack_builtin_NULL_functions = {
  37. .mixdown = NULL,
  38. };
  39. /* Only the Audio port type is currently built in. */
  40. jack_port_type_info_t jack_builtin_port_types[] = {
  41. { .type_name = JACK_DEFAULT_AUDIO_TYPE,
  42. .buffer_scale_factor = 1,
  43. },
  44. { .type_name = "", }
  45. };
  46. jack_port_t *
  47. jack_port_new (const jack_client_t *client, jack_port_id_t port_id,
  48. jack_control_t *control)
  49. {
  50. jack_port_shared_t *shared = &control->ports[port_id];
  51. jack_port_type_id_t ptid = shared->ptype_id;
  52. jack_port_t *port = (jack_port_t *) malloc (sizeof (jack_port_t));
  53. port->mix_buffer = NULL;
  54. port->client_segment_base = NULL;
  55. port->shared = shared;
  56. port->type_info = &client->engine->port_types[ptid];
  57. pthread_mutex_init (&port->connection_lock, NULL);
  58. port->connections = 0;
  59. port->tied = NULL;
  60. if (client->control->id == port->shared->client_id) {
  61. /* It's our port, so initialize the pointers to port
  62. * functions within this address space. These builtin
  63. * definitions can be overridden by the client.
  64. */
  65. if (ptid == JACK_AUDIO_PORT_TYPE) {
  66. port->fptr = jack_builtin_audio_functions;
  67. port->shared->has_mixdown = TRUE;
  68. } else { /* no other builtin functions */
  69. port->fptr = jack_builtin_NULL_functions;
  70. port->shared->has_mixdown = FALSE;
  71. }
  72. }
  73. /* set up a base address so that port->offset can be used to
  74. compute the correct location. we don't store the location
  75. directly, because port->client_segment_base and/or
  76. port->offset can change if the buffer size or port counts
  77. are changed.
  78. */
  79. port->client_segment_base =
  80. (void **) &client->port_segment[ptid].attached_at;
  81. return port;
  82. }
  83. jack_port_t *
  84. jack_port_register (jack_client_t *client,
  85. const char *port_name,
  86. const char *port_type,
  87. unsigned long flags,
  88. unsigned long buffer_size)
  89. {
  90. jack_request_t req;
  91. jack_port_t *port = 0;
  92. int length ;
  93. req.type = RegisterPort;
  94. length = strlen ((const char *) client->control->name)
  95. + 1 + strlen (port_name);
  96. if ( length >= sizeof (req.x.port_info.name) ) {
  97. jack_error ("\"%s:%s\" is too long to be used as a JACK port name.\n"
  98. "Please use %lu characters or less.",
  99. client->control->name ,
  100. port_name,
  101. sizeof (req.x.port_info.name) - 1);
  102. return NULL ;
  103. }
  104. strcpy ((char *) req.x.port_info.name,
  105. (const char *) client->control->name);
  106. strcat ((char *) req.x.port_info.name, ":");
  107. strcat ((char *) req.x.port_info.name, port_name);
  108. snprintf (req.x.port_info.type, sizeof (req.x.port_info.type),
  109. "%s", port_type);
  110. req.x.port_info.flags = flags;
  111. req.x.port_info.buffer_size = buffer_size;
  112. req.x.port_info.client_id = client->control->id;
  113. if (jack_client_deliver_request (client, &req)) {
  114. jack_error ("cannot deliver port registration request");
  115. return NULL;
  116. }
  117. if ((port = jack_port_new (client, req.x.port_info.port_id,
  118. client->engine)) == NULL) {
  119. jack_error ("cannot allocate client side port structure");
  120. return NULL;
  121. }
  122. client->ports = jack_slist_prepend (client->ports, port);
  123. return port;
  124. }
  125. int
  126. jack_port_unregister (jack_client_t *client, jack_port_t *port)
  127. {
  128. jack_request_t req;
  129. req.type = UnRegisterPort;
  130. req.x.port_info.port_id = port->shared->id;
  131. req.x.port_info.client_id = client->control->id;
  132. return jack_client_deliver_request (client, &req);
  133. }
  134. int
  135. jack_port_lock (jack_client_t *client, jack_port_t *port)
  136. {
  137. if (port) {
  138. port->shared->locked = 1;
  139. return 0;
  140. }
  141. return -1;
  142. }
  143. int
  144. jack_port_unlock (jack_client_t *client, jack_port_t *port)
  145. {
  146. if (port) {
  147. port->shared->locked = 0;
  148. return 0;
  149. }
  150. return -1;
  151. }
  152. /* LOCAL (in-client) connection querying only */
  153. int
  154. jack_port_connected (const jack_port_t *port)
  155. {
  156. return jack_slist_length (port->connections);
  157. }
  158. int
  159. jack_port_connected_to (const jack_port_t *port, const char *portname)
  160. {
  161. JSList *node;
  162. int ret = FALSE;
  163. /* XXX this really requires a cross-process lock
  164. so that ports/connections cannot go away
  165. while we are checking for them. that's hard,
  166. and has a non-trivial performance impact
  167. for jackd.
  168. */
  169. pthread_mutex_lock (&((jack_port_t *) port)->connection_lock);
  170. for (node = port->connections; node; node = jack_slist_next (node)) {
  171. jack_port_t *other_port = (jack_port_t *) node->data;
  172. if (strcmp (other_port->shared->name, portname) == 0) {
  173. ret = TRUE;
  174. break;
  175. }
  176. }
  177. pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock);
  178. return ret;
  179. }
  180. const char **
  181. jack_port_get_connections (const jack_port_t *port)
  182. {
  183. const char **ret = NULL;
  184. JSList *node;
  185. unsigned int n;
  186. /* XXX this really requires a cross-process lock
  187. so that ports/connections cannot go away
  188. while we are checking for them. that's hard,
  189. and has a non-trivial performance impact
  190. for jackd.
  191. */
  192. pthread_mutex_lock (&((jack_port_t *) port)->connection_lock);
  193. if (port->connections != NULL) {
  194. ret = (const char **)
  195. malloc (sizeof (char *)
  196. * (jack_slist_length (port->connections) + 1));
  197. for (n = 0, node = port->connections; node;
  198. node = jack_slist_next (node), ++n) {
  199. ret[n] = ((jack_port_t *) node->data)->shared->name;
  200. }
  201. ret[n] = NULL;
  202. }
  203. pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock);
  204. return ret;
  205. }
  206. /* SERVER-SIDE (all) connection querying */
  207. const char **
  208. jack_port_get_all_connections (const jack_client_t *client,
  209. const jack_port_t *port)
  210. {
  211. const char **ret;
  212. jack_request_t req;
  213. jack_port_t *tmp;
  214. unsigned int i;
  215. int need_free = FALSE;
  216. if (port == NULL) {
  217. return NULL;
  218. }
  219. req.type = GetPortConnections;
  220. req.x.port_info.name[0] = '\0';
  221. req.x.port_info.type[0] = '\0';
  222. req.x.port_info.flags = 0;
  223. req.x.port_info.buffer_size = 0;
  224. req.x.port_info.client_id = 0;
  225. req.x.port_info.port_id = port->shared->id;
  226. jack_client_deliver_request (client, &req);
  227. if (req.status != 0 || req.x.port_connections.nports == 0) {
  228. return NULL;
  229. }
  230. if (client->request_fd < 0) {
  231. /* internal client */
  232. return req.x.port_connections.ports;
  233. }
  234. ret = (const char **)
  235. malloc (sizeof (char *) * (req.x.port_connections.nports + 1));
  236. for (i = 0; i < req.x.port_connections.nports; ++i ) {
  237. jack_port_id_t port_id;
  238. if (read (client->request_fd, &port_id, sizeof (port_id))
  239. != sizeof (port_id)) {
  240. jack_error ("cannot read port id from server");
  241. return 0;
  242. }
  243. tmp = jack_port_by_id_int (client, port_id, &need_free);
  244. ret[i] = tmp->shared->name;
  245. if (need_free) {
  246. free (tmp);
  247. need_free = FALSE;
  248. }
  249. }
  250. ret[i] = NULL;
  251. return ret;
  252. }
  253. jack_port_t *
  254. jack_port_by_id_int (const jack_client_t *client, jack_port_id_t id, int* free)
  255. {
  256. JSList *node;
  257. for (node = client->ports; node; node = jack_slist_next (node)) {
  258. if (((jack_port_t *) node->data)->shared->id == id) {
  259. *free = FALSE;
  260. return (jack_port_t *) node->data;
  261. }
  262. }
  263. if (id >= client->engine->port_max)
  264. return NULL;
  265. if (client->engine->ports[id].in_use) {
  266. *free = TRUE;
  267. return jack_port_new (client, id, client->engine);
  268. }
  269. return NULL;
  270. }
  271. jack_port_t *
  272. jack_port_by_id (jack_client_t *client, jack_port_id_t id)
  273. {
  274. JSList *node;
  275. jack_port_t* port;
  276. int need_free = FALSE;
  277. for (node = client->ports_ext; node; node = jack_slist_next (node)) {
  278. port = node->data;
  279. if (port->shared->id == id) { // Found port, return the cached structure
  280. return port;
  281. }
  282. }
  283. // Otherwise possibly allocate a new port structure, keep it in the ports_ext list for later use
  284. port = jack_port_by_id_int (client,id,&need_free);
  285. if (port != NULL && need_free)
  286. client->ports_ext =
  287. jack_slist_prepend (client->ports_ext, port);
  288. return port;
  289. }
  290. jack_port_t *
  291. jack_port_by_name_int (jack_client_t *client, const char *port_name)
  292. {
  293. unsigned long i, limit;
  294. jack_port_shared_t *port;
  295. limit = client->engine->port_max;
  296. port = &client->engine->ports[0];
  297. for (i = 0; i < limit; i++) {
  298. if (port[i].in_use && strcmp (port[i].name, port_name) == 0) {
  299. return jack_port_new (client, port[i].id,
  300. client->engine);
  301. }
  302. }
  303. return NULL;
  304. }
  305. jack_port_t *
  306. jack_port_by_name (jack_client_t *client, const char *port_name)
  307. {
  308. JSList *node;
  309. jack_port_t* port;
  310. for (node = client->ports_ext; node; node = jack_slist_next (node)) {
  311. port = node->data;
  312. if (strcmp (port->shared->name, port_name) == 0) {
  313. /* Found port, return the cached structure. */
  314. return port;
  315. }
  316. }
  317. /* Otherwise allocate a new port structure, keep it in the
  318. * ports_ext list for later use. */
  319. port = jack_port_by_name_int (client, port_name);
  320. if (port != NULL)
  321. client->ports_ext =
  322. jack_slist_prepend (client->ports_ext, port);
  323. return port;
  324. }
  325. jack_nframes_t
  326. jack_port_get_latency (jack_port_t *port)
  327. {
  328. return port->shared->latency;
  329. }
  330. jack_nframes_t
  331. jack_port_get_total_latency (jack_client_t *client, jack_port_t *port)
  332. {
  333. return port->shared->total_latency;
  334. }
  335. void
  336. jack_port_set_latency (jack_port_t *port, jack_nframes_t nframes)
  337. {
  338. port->shared->latency = nframes;
  339. }
  340. void *
  341. jack_port_get_buffer (jack_port_t *port, jack_nframes_t nframes)
  342. {
  343. JSList *node, *next;
  344. /* Output port. The buffer was assigned by the engine
  345. when the port was registered.
  346. */
  347. if (port->shared->flags & JackPortIsOutput) {
  348. if (port->tied) {
  349. return jack_port_get_buffer (port->tied, nframes);
  350. }
  351. return jack_output_port_buffer (port);
  352. }
  353. /* Input port. Since this can only be called from the
  354. process() callback, and since no connections can be
  355. made/broken during this phase (enforced by the jack
  356. server), there is no need to take the connection lock here
  357. */
  358. if ((node = port->connections) == NULL) {
  359. /* no connections; return a zero-filled buffer */
  360. return jack_zero_filled_buffer;
  361. }
  362. if ((next = jack_slist_next (node)) == NULL) {
  363. /* one connection: use zero-copy mode - just pass
  364. the buffer of the connected (output) port.
  365. */
  366. return jack_port_get_buffer (((jack_port_t *) node->data),
  367. nframes);
  368. }
  369. /* Multiple connections. Use a local buffer and mix the
  370. incoming data into that buffer. We have already
  371. established the existence of a mixdown function during the
  372. connection process.
  373. */
  374. if (port->mix_buffer == NULL) {
  375. port->mix_buffer =
  376. jack_pool_alloc (
  377. port->type_info->buffer_scale_factor
  378. * sizeof (jack_default_audio_sample_t)
  379. * nframes);
  380. }
  381. port->fptr.mixdown (port, nframes);
  382. return (jack_default_audio_sample_t *) port->mix_buffer;
  383. }
  384. int
  385. jack_port_tie (jack_port_t *src, jack_port_t *dst)
  386. {
  387. if (dst->shared->client_id != src->shared->client_id) {
  388. jack_error ("cannot tie ports not owned by the same client");
  389. return -1;
  390. }
  391. if (dst->shared->flags & JackPortIsOutput) {
  392. jack_error ("cannot tie an input port");
  393. return -1;
  394. }
  395. dst->tied = src;
  396. return 0;
  397. }
  398. int
  399. jack_port_untie (jack_port_t *port)
  400. {
  401. if (port->tied == NULL) {
  402. jack_error ("port \"%s\" is not tied", port->shared->name);
  403. return -1;
  404. }
  405. port->tied = NULL;
  406. return 0;
  407. }
  408. int
  409. jack_port_request_monitor (jack_port_t *port, int onoff)
  410. {
  411. if (onoff) {
  412. port->shared->monitor_requests++;
  413. } else if (port->shared->monitor_requests) {
  414. port->shared->monitor_requests--;
  415. }
  416. if ((port->shared->flags & JackPortIsOutput) == 0) {
  417. JSList *node;
  418. /* this port is for input, so recurse over each of the
  419. connected ports.
  420. */
  421. pthread_mutex_lock (&port->connection_lock);
  422. for (node = port->connections; node;
  423. node = jack_slist_next (node)) {
  424. /* drop the lock because if there is a feedback loop,
  425. we will deadlock. XXX much worse things will
  426. happen if there is a feedback loop !!!
  427. */
  428. pthread_mutex_unlock (&port->connection_lock);
  429. jack_port_request_monitor ((jack_port_t *) node->data,
  430. onoff);
  431. pthread_mutex_lock (&port->connection_lock);
  432. }
  433. pthread_mutex_unlock (&port->connection_lock);
  434. }
  435. return 0;
  436. }
  437. int
  438. jack_port_request_monitor_by_name (jack_client_t *client,
  439. const char *port_name, int onoff)
  440. {
  441. jack_port_t *port;
  442. unsigned long i, limit;
  443. jack_port_shared_t *ports;
  444. limit = client->engine->port_max;
  445. ports = &client->engine->ports[0];
  446. for (i = 0; i < limit; i++) {
  447. if (ports[i].in_use &&
  448. strcmp (ports[i].name, port_name) == 0) {
  449. port = jack_port_new (client, ports[i].id,
  450. client->engine);
  451. return jack_port_request_monitor (port, onoff);
  452. free (port);
  453. return 0;
  454. }
  455. }
  456. return -1;
  457. }
  458. int
  459. jack_ensure_port_monitor_input (jack_port_t *port, int yn)
  460. {
  461. if (yn) {
  462. if (port->shared->monitor_requests == 0) {
  463. port->shared->monitor_requests++;
  464. }
  465. } else {
  466. if (port->shared->monitor_requests > 0) {
  467. port->shared->monitor_requests = 0;
  468. }
  469. }
  470. return 0;
  471. }
  472. int
  473. jack_port_monitoring_input (jack_port_t *port)
  474. {
  475. return port->shared->monitor_requests > 0;
  476. }
  477. const char *
  478. jack_port_name (const jack_port_t *port)
  479. {
  480. return port->shared->name;
  481. }
  482. const char *
  483. jack_port_short_name (const jack_port_t *port)
  484. {
  485. /* we know there is always a colon, because we put
  486. it there ...
  487. */
  488. return strchr (port->shared->name, ':') + 1;
  489. }
  490. int
  491. jack_port_is_mine (const jack_client_t *client, const jack_port_t *port)
  492. {
  493. return port->shared->client_id == client->control->id;
  494. }
  495. int
  496. jack_port_flags (const jack_port_t *port)
  497. {
  498. return port->shared->flags;
  499. }
  500. const char *
  501. jack_port_type (const jack_port_t *port)
  502. {
  503. return port->type_info->type_name;
  504. }
  505. int
  506. jack_port_set_name (jack_port_t *port, const char *new_name)
  507. {
  508. char *colon;
  509. int len;
  510. colon = strchr (port->shared->name, ':');
  511. len = sizeof (port->shared->name) -
  512. ((int) (colon - port->shared->name)) - 2;
  513. snprintf (colon+1, len, "%s", new_name);
  514. return 0;
  515. }
  516. /* AUDIO PORT SUPPORT */
  517. static inline float f_max(float x, float a)
  518. {
  519. x -= a;
  520. x += fabs (x);
  521. x *= 0.5;
  522. x += a;
  523. return (x);
  524. }
  525. static void
  526. jack_audio_port_mixdown (jack_port_t *port, jack_nframes_t nframes)
  527. {
  528. JSList *node;
  529. jack_port_t *input;
  530. jack_nframes_t n;
  531. jack_default_audio_sample_t *buffer;
  532. jack_default_audio_sample_t *dst, *src;
  533. /* by the time we've called this, we've already established
  534. the existence of more than one connection to this input
  535. port and allocated a mix_buffer.
  536. */
  537. /* no need to take connection lock, since this is called
  538. from the process() callback, and the jack server
  539. ensures that no changes to connections happen
  540. during this time.
  541. */
  542. node = port->connections;
  543. input = (jack_port_t *) node->data;
  544. buffer = port->mix_buffer;
  545. memcpy (buffer, jack_output_port_buffer (input),
  546. sizeof (jack_default_audio_sample_t) * nframes);
  547. for (node = jack_slist_next (node); node;
  548. node = jack_slist_next (node)) {
  549. input = (jack_port_t *) node->data;
  550. n = nframes;
  551. dst = buffer;
  552. src = jack_output_port_buffer (input);
  553. while (n--) {
  554. *dst++ += *src++;
  555. }
  556. }
  557. }