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.

729 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. jack_port_t *
  31. jack_port_new (const jack_client_t *client, jack_port_id_t port_id,
  32. jack_control_t *control)
  33. {
  34. jack_port_t *port;
  35. jack_port_shared_t *shared;
  36. jack_port_segment_info_t *si;
  37. JSList *node;
  38. shared = &control->ports[port_id];
  39. port = (jack_port_t *) malloc (sizeof (jack_port_t));
  40. port->client_segment_base = 0;
  41. port->shared = shared;
  42. pthread_mutex_init (&port->connection_lock, NULL);
  43. port->connections = 0;
  44. port->shared->tied = NULL;
  45. /* reset function pointers to be within client address space */
  46. switch (client->control->type) {
  47. case ClientExternal:
  48. if (client->control->id == port->shared->client_id) {
  49. /* its our port, and therefore we need to make
  50. sure that the function pointers in the
  51. shared memory object that refer to
  52. functions called within the client's
  53. address space point to the location of the
  54. correct functions within the
  55. client. without this, they point to those
  56. same functions in the server's address
  57. space, and that's a recipe for disaster.
  58. */
  59. port->shared->type_info.mixdown =
  60. jack_builtin_port_types[
  61. port->shared->type_info.type_id
  62. ].mixdown;
  63. port->shared->type_info.peak =
  64. jack_builtin_port_types[
  65. port->shared->type_info.type_id].peak;
  66. port->shared->type_info.power =
  67. jack_builtin_port_types[
  68. port->shared->type_info.type_id].power;
  69. }
  70. break;
  71. default:
  72. break;
  73. }
  74. /* now find the shared memory segment that contains the buffer
  75. * for this port */
  76. for (node = client->port_segments; node;
  77. node = jack_slist_next (node)) {
  78. si = (jack_port_segment_info_t *) node->data;
  79. if (strcmp (si->shm_name,
  80. port->shared->type_info.shm_info.shm_name) == 0) {
  81. break;
  82. }
  83. }
  84. if (node == NULL) {
  85. jack_error ("cannot find port memory segment [%s] for"
  86. " new port\n",
  87. port->shared->type_info.shm_info.shm_name);
  88. return NULL;
  89. }
  90. /* set up a base address so that port->offset can be used to
  91. compute the correct location. we don't store the location
  92. directly, because port->client_segment_base and/or
  93. port->offset can change if the buffer size or port counts
  94. are changed.
  95. */
  96. port->client_segment_base = si->address;
  97. return port;
  98. }
  99. jack_port_t *
  100. jack_port_register (jack_client_t *client,
  101. const char *port_name,
  102. const char *port_type,
  103. unsigned long flags,
  104. unsigned long buffer_size)
  105. {
  106. jack_request_t req;
  107. jack_port_t *port = 0;
  108. int length ;
  109. req.type = RegisterPort;
  110. length = strlen ( (const char *) client->control->name )
  111. + 1 + strlen ( port_name ) ;
  112. if ( length >= sizeof (req.x.port_info.name) ) {
  113. jack_error ("\"%s:%s\" is too long to be used as a JACK port name.\n"
  114. "Please use %lu characters or less.",
  115. client->control->name ,
  116. port_name ,
  117. sizeof (req.x.port_info.name) - 1);
  118. return NULL ;
  119. }
  120. strcpy ((char *) req.x.port_info.name,
  121. (const char *) client->control->name);
  122. strcat ((char *) req.x.port_info.name, ":");
  123. strcat ((char *) req.x.port_info.name, port_name);
  124. snprintf (req.x.port_info.type, sizeof (req.x.port_info.type),
  125. "%s", port_type);
  126. req.x.port_info.flags = flags;
  127. req.x.port_info.buffer_size = buffer_size;
  128. req.x.port_info.client_id = client->control->id;
  129. if (jack_client_deliver_request (client, &req)) {
  130. return NULL;
  131. }
  132. if ((port = jack_port_new (client, req.x.port_info.port_id,
  133. client->engine)) == NULL) {
  134. return NULL;
  135. }
  136. client->ports = jack_slist_prepend (client->ports, port);
  137. return port;
  138. }
  139. int
  140. jack_port_unregister (jack_client_t *client, jack_port_t *port)
  141. {
  142. jack_request_t req;
  143. req.type = UnRegisterPort;
  144. req.x.port_info.port_id = port->shared->id;
  145. req.x.port_info.client_id = client->control->id;
  146. return jack_client_deliver_request (client, &req);
  147. }
  148. int
  149. jack_port_lock (jack_client_t *client, jack_port_t *port)
  150. {
  151. if (port) {
  152. port->shared->locked = 1;
  153. return 0;
  154. }
  155. return -1;
  156. }
  157. int
  158. jack_port_unlock (jack_client_t *client, jack_port_t *port)
  159. {
  160. if (port) {
  161. port->shared->locked = 0;
  162. return 0;
  163. }
  164. return -1;
  165. }
  166. /* LOCAL (in-client) connection querying only */
  167. int
  168. jack_port_connected (const jack_port_t *port)
  169. {
  170. return jack_slist_length (port->connections);
  171. }
  172. int
  173. jack_port_connected_to (const jack_port_t *port, const char *portname)
  174. {
  175. JSList *node;
  176. int ret = FALSE;
  177. /* XXX this really requires a cross-process lock
  178. so that ports/connections cannot go away
  179. while we are checking for them. that's hard,
  180. and has a non-trivial performance impact
  181. for jackd.
  182. */
  183. pthread_mutex_lock (&((jack_port_t *) port)->connection_lock);
  184. for (node = port->connections; node; node = jack_slist_next (node)) {
  185. jack_port_t *other_port = (jack_port_t *) node->data;
  186. if (strcmp (other_port->shared->name, portname) == 0) {
  187. ret = TRUE;
  188. break;
  189. }
  190. }
  191. pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock);
  192. return ret;
  193. }
  194. const char **
  195. jack_port_get_connections (const jack_port_t *port)
  196. {
  197. const char **ret = NULL;
  198. JSList *node;
  199. unsigned int n;
  200. /* XXX this really requires a cross-process lock
  201. so that ports/connections cannot go away
  202. while we are checking for them. that's hard,
  203. and has a non-trivial performance impact
  204. for jackd.
  205. */
  206. pthread_mutex_lock (&((jack_port_t *) port)->connection_lock);
  207. if (port->connections != NULL) {
  208. ret = (const char **)
  209. malloc (sizeof (char *)
  210. * (jack_slist_length (port->connections) + 1));
  211. for (n = 0, node = port->connections; node;
  212. node = jack_slist_next (node), ++n) {
  213. ret[n] = ((jack_port_t *) node->data)->shared->name;
  214. }
  215. ret[n] = NULL;
  216. }
  217. pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock);
  218. return ret;
  219. }
  220. /* SERVER-SIDE (all) connection querying */
  221. const char **
  222. jack_port_get_all_connections (const jack_client_t *client,
  223. const jack_port_t *port)
  224. {
  225. const char **ret;
  226. jack_request_t req;
  227. unsigned int i;
  228. if (port == NULL) {
  229. return NULL;
  230. }
  231. req.type = GetPortConnections;
  232. req.x.port_info.name[0] = '\0';
  233. req.x.port_info.type[0] = '\0';
  234. req.x.port_info.flags = 0;
  235. req.x.port_info.buffer_size = 0;
  236. req.x.port_info.client_id = 0;
  237. req.x.port_info.port_id = port->shared->id;
  238. jack_client_deliver_request (client, &req);
  239. if (req.status != 0 || req.x.port_connections.nports == 0) {
  240. return NULL;
  241. }
  242. if (client->request_fd < 0) {
  243. /* internal client */
  244. return req.x.port_connections.ports;
  245. }
  246. ret = (const char **)
  247. malloc (sizeof (char *) * (req.x.port_connections.nports + 1));
  248. for (i = 0; i < req.x.port_connections.nports; ++i ) {
  249. jack_port_id_t port_id;
  250. if (read (client->request_fd, &port_id, sizeof (port_id))
  251. != sizeof (port_id)) {
  252. jack_error ("cannot read port id from server");
  253. return 0;
  254. }
  255. ret[i] = jack_port_by_id (client, port_id)->shared->name;
  256. }
  257. ret[i] = NULL;
  258. return ret;
  259. }
  260. jack_port_t *
  261. jack_port_by_id (const jack_client_t *client, jack_port_id_t id)
  262. {
  263. JSList *node;
  264. for (node = client->ports; node; node = jack_slist_next (node)) {
  265. if (((jack_port_t *) node->data)->shared->id == id) {
  266. return (jack_port_t *) node->data;
  267. }
  268. }
  269. if (id >= client->engine->port_max)
  270. return NULL;
  271. if (client->engine->ports[id].in_use)
  272. return jack_port_new (client, id, client->engine);
  273. return NULL;
  274. }
  275. jack_port_t *
  276. jack_port_by_name (jack_client_t *client, const char *port_name)
  277. {
  278. unsigned long i, limit;
  279. jack_port_shared_t *port;
  280. limit = client->engine->port_max;
  281. port = &client->engine->ports[0];
  282. for (i = 0; i < limit; i++) {
  283. if (port[i].in_use && strcmp (port[i].name, port_name) == 0) {
  284. return jack_port_new (client, port[i].id,
  285. client->engine);
  286. }
  287. }
  288. return NULL;
  289. }
  290. jack_nframes_t
  291. jack_port_get_latency (jack_port_t *port)
  292. {
  293. return port->shared->latency;
  294. }
  295. jack_nframes_t
  296. jack_port_get_total_latency (jack_client_t *client, jack_port_t *port)
  297. {
  298. return port->shared->total_latency;
  299. }
  300. void
  301. jack_port_set_latency (jack_port_t *port, jack_nframes_t nframes)
  302. {
  303. port->shared->latency = nframes;
  304. }
  305. void *
  306. jack_port_get_buffer (jack_port_t *port, jack_nframes_t nframes)
  307. {
  308. JSList *node, *next;
  309. /* Output port. The buffer was assigned by the engine
  310. when the port was registered.
  311. */
  312. if (port->shared->flags & JackPortIsOutput) {
  313. if (port->shared->tied) {
  314. return jack_port_get_buffer (port->shared->tied,
  315. nframes);
  316. }
  317. return jack_port_buffer (port);
  318. }
  319. /* Input port.
  320. */
  321. /* since this can only be called from the process() callback,
  322. and since no connections can be made/broken during this
  323. phase (enforced by the jack server), there is no need
  324. to take the connection lock here
  325. */
  326. if ((node = port->connections) == NULL) {
  327. /* no connections; return a zero-filled buffer */
  328. return jack_zero_filled_buffer;
  329. }
  330. if ((next = jack_slist_next (node)) == NULL) {
  331. /* one connection: use zero-copy mode - just pass
  332. the buffer of the connected (output) port.
  333. */
  334. return jack_port_get_buffer (((jack_port_t *) node->data),
  335. nframes);
  336. }
  337. /* multiple connections. use a local buffer and mixdown
  338. the incoming data to that buffer. we have already
  339. established the existence of a mixdown function
  340. during the connection process.
  341. no port can have an offset of 0 - that offset refers
  342. to the zero-filled area at the start of a shared port
  343. segment area. so, use the offset to store the location
  344. of a locally allocated buffer, and reset the client_segment_base
  345. so that the jack_port_buffer() computation works correctly.
  346. */
  347. if (port->shared->offset == 0) {
  348. port->shared->offset = (size_t)
  349. jack_pool_alloc (
  350. port->shared->type_info.buffer_scale_factor
  351. * sizeof (jack_default_audio_sample_t)
  352. * nframes);
  353. port->client_segment_base = 0;
  354. }
  355. port->shared->type_info.mixdown (port, nframes);
  356. return (jack_default_audio_sample_t *) port->shared->offset;
  357. }
  358. int
  359. jack_port_tie (jack_port_t *src, jack_port_t *dst)
  360. {
  361. if (dst->shared->client_id != src->shared->client_id) {
  362. jack_error ("cannot tie ports not owned by the same client");
  363. return -1;
  364. }
  365. if (dst->shared->flags & JackPortIsOutput) {
  366. jack_error ("cannot tie an input port");
  367. return -1;
  368. }
  369. dst->shared->tied = src;
  370. return 0;
  371. }
  372. int
  373. jack_port_untie (jack_port_t *port)
  374. {
  375. if (port->shared->tied == NULL) {
  376. jack_error ("port \"%s\" is not tied", port->shared->name);
  377. return -1;
  378. }
  379. port->shared->tied = NULL;
  380. return 0;
  381. }
  382. int
  383. jack_port_request_monitor (jack_port_t *port, int onoff)
  384. {
  385. if (onoff) {
  386. port->shared->monitor_requests++;
  387. } else if (port->shared->monitor_requests) {
  388. port->shared->monitor_requests--;
  389. }
  390. if ((port->shared->flags & JackPortIsOutput) == 0) {
  391. JSList *node;
  392. /* this port is for input, so recurse over each of the
  393. connected ports.
  394. */
  395. pthread_mutex_lock (&port->connection_lock);
  396. for (node = port->connections; node;
  397. node = jack_slist_next (node)) {
  398. /* drop the lock because if there is a feedback loop,
  399. we will deadlock. XXX much worse things will
  400. happen if there is a feedback loop !!!
  401. */
  402. pthread_mutex_unlock (&port->connection_lock);
  403. jack_port_request_monitor ((jack_port_t *) node->data,
  404. onoff);
  405. pthread_mutex_lock (&port->connection_lock);
  406. }
  407. pthread_mutex_unlock (&port->connection_lock);
  408. }
  409. return 0;
  410. }
  411. int
  412. jack_port_request_monitor_by_name (jack_client_t *client,
  413. const char *port_name, int onoff)
  414. {
  415. jack_port_t *port;
  416. unsigned long i, limit;
  417. jack_port_shared_t *ports;
  418. limit = client->engine->port_max;
  419. ports = &client->engine->ports[0];
  420. for (i = 0; i < limit; i++) {
  421. if (ports[i].in_use &&
  422. strcmp (ports[i].name, port_name) == 0) {
  423. port = jack_port_new (client, ports[i].id,
  424. client->engine);
  425. return jack_port_request_monitor (port, onoff);
  426. free (port);
  427. return 0;
  428. }
  429. }
  430. return -1;
  431. }
  432. int
  433. jack_ensure_port_monitor_input (jack_port_t *port, int yn)
  434. {
  435. if (yn) {
  436. if (port->shared->monitor_requests == 0) {
  437. port->shared->monitor_requests++;
  438. }
  439. } else {
  440. if (port->shared->monitor_requests > 0) {
  441. port->shared->monitor_requests = 0;
  442. }
  443. }
  444. return 0;
  445. }
  446. int
  447. jack_port_monitoring_input (jack_port_t *port)
  448. {
  449. return port->shared->monitor_requests > 0;
  450. }
  451. const char *
  452. jack_port_name (const jack_port_t *port)
  453. {
  454. return port->shared->name;
  455. }
  456. const char *
  457. jack_port_short_name (const jack_port_t *port)
  458. {
  459. /* we know there is always a colon, because we put
  460. it there ...
  461. */
  462. return strchr (port->shared->name, ':') + 1;
  463. }
  464. int
  465. jack_port_is_mine (const jack_client_t *client, const jack_port_t *port)
  466. {
  467. return port->shared->client_id == client->control->id;
  468. }
  469. int
  470. jack_port_flags (const jack_port_t *port)
  471. {
  472. return port->shared->flags;
  473. }
  474. const char *
  475. jack_port_type (const jack_port_t *port)
  476. {
  477. return port->shared->type_info.type_name;
  478. }
  479. int
  480. jack_port_set_name (jack_port_t *port, const char *new_name)
  481. {
  482. char *colon;
  483. int len;
  484. colon = strchr (port->shared->name, ':');
  485. len = sizeof (port->shared->name) -
  486. ((int) (colon - port->shared->name)) - 2;
  487. snprintf (colon+1, len, "%s", new_name);
  488. return 0;
  489. }
  490. void
  491. jack_port_set_peak_function (jack_port_t *port,
  492. double (*func)(jack_port_t* port, jack_nframes_t))
  493. {
  494. port->shared->type_info.peak = func;
  495. }
  496. void
  497. jack_port_set_power_function (jack_port_t *port,
  498. double (*func)(jack_port_t* port, jack_nframes_t))
  499. {
  500. port->shared->type_info.power = func;
  501. }
  502. double
  503. jack_port_get_peak (jack_port_t* port, jack_nframes_t nframes)
  504. {
  505. if (port->shared->type_info.peak (port, nframes)) {
  506. return port->shared->type_info.peak (port, nframes);
  507. } else {
  508. return 0;
  509. }
  510. }
  511. double
  512. jack_port_get_power (jack_port_t* port, jack_nframes_t nframes)
  513. {
  514. if (port->shared->type_info.power) {
  515. return port->shared->type_info.power (port, nframes);
  516. } else {
  517. return 0;
  518. }
  519. }
  520. /* AUDIO PORT SUPPORT */
  521. static inline float f_max(float x, float a)
  522. {
  523. x -= a;
  524. x += fabs (x);
  525. x *= 0.5;
  526. x += a;
  527. return (x);
  528. }
  529. static double
  530. jack_audio_port_peak (jack_port_t *port, jack_nframes_t nframes)
  531. {
  532. jack_nframes_t n;
  533. jack_default_audio_sample_t *buf = (jack_default_audio_sample_t *)
  534. jack_port_get_buffer (port, nframes);
  535. float max = 0;
  536. for (n = 0; n < nframes; ++n) {
  537. max = f_max (buf[n], max);
  538. }
  539. return max;
  540. }
  541. static void
  542. jack_audio_port_mixdown (jack_port_t *port, jack_nframes_t nframes)
  543. {
  544. JSList *node;
  545. jack_port_t *input;
  546. jack_nframes_t n;
  547. jack_default_audio_sample_t *buffer;
  548. jack_default_audio_sample_t *dst, *src;
  549. /* by the time we've called this, we've already established
  550. the existence of more than 1 connection to this input port.
  551. */
  552. /* no need to take connection lock, since this is called
  553. from the process() callback, and the jack server
  554. ensures that no changes to connections happen
  555. during this time.
  556. */
  557. node = port->connections;
  558. input = (jack_port_t *) node->data;
  559. buffer = jack_port_buffer (port);
  560. memcpy (buffer, jack_port_buffer (input),
  561. sizeof (jack_default_audio_sample_t) * nframes);
  562. for (node = jack_slist_next (node); node;
  563. node = jack_slist_next (node)) {
  564. input = (jack_port_t *) node->data;
  565. n = nframes;
  566. dst = buffer;
  567. src = jack_port_buffer (input);
  568. while (n--) {
  569. *dst++ += *src++;
  570. }
  571. }
  572. }
  573. jack_port_type_info_t jack_builtin_port_types[] = {
  574. { .type_name = JACK_DEFAULT_AUDIO_TYPE,
  575. .mixdown = jack_audio_port_mixdown,
  576. .peak = jack_audio_port_peak,
  577. .power = NULL,
  578. .buffer_scale_factor = 1,
  579. },
  580. { .type_name = "",
  581. }
  582. };