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.

985 lines
23KB

  1. /*
  2. Copyright (C) 2001-2003 Paul Davis
  3. Copyright (C) 2005 Jussi Laako
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  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 Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <config.h>
  20. #include <sys/mman.h>
  21. #include <jack/jack.h>
  22. #include <jack/types.h>
  23. #include <jack/midiport.h>
  24. #include <jack/uuid.h>
  25. #include <jack/jslist.h>
  26. #include "internal.h"
  27. #include "engine.h"
  28. #include "pool.h"
  29. #include "port.h"
  30. #include "intsimd.h"
  31. #include "local.h"
  32. static void jack_generic_buffer_init(void *port_buffer,
  33. size_t buffer_size,
  34. jack_nframes_t nframes);
  35. static void jack_audio_port_mixdown(jack_port_t *port,
  36. jack_nframes_t nframes);
  37. /* These function pointers are local to each address space. For
  38. * internal clients they reside within jackd; for external clients in
  39. * the application process. */
  40. jack_port_functions_t jack_builtin_audio_functions = {
  41. .buffer_init = jack_generic_buffer_init,
  42. .mixdown = jack_audio_port_mixdown,
  43. };
  44. extern jack_port_functions_t jack_builtin_midi_functions;
  45. jack_port_functions_t jack_builtin_NULL_functions = {
  46. .buffer_init = jack_generic_buffer_init,
  47. .mixdown = NULL,
  48. };
  49. /* Only the Audio and MIDI port types are currently built in. */
  50. jack_port_type_info_t jack_builtin_port_types[] = {
  51. { .type_name = JACK_DEFAULT_AUDIO_TYPE,
  52. .buffer_scale_factor = 1, },
  53. { .type_name = JACK_DEFAULT_MIDI_TYPE,
  54. .buffer_scale_factor = -1,
  55. .buffer_size = 2048 },
  56. { .type_name = "", }
  57. };
  58. /* these functions have been taken from libDSP X86.c -jl */
  59. #ifdef USE_DYNSIMD
  60. static void (*opt_copy)(float *, const float *, int);
  61. static void (*opt_mix)(float *, const float *, int);
  62. static void
  63. gen_copyf (float *dest, const float *src, int length)
  64. {
  65. memcpy (dest, src, length * sizeof(float));
  66. }
  67. static void
  68. gen_mixf (float *dest, const float *src, int length)
  69. {
  70. int n;
  71. n = length;
  72. while (n--)
  73. *dest++ += *src++;
  74. /*for (iSample = 0; iSample < iDataLength; iSample++)
  75. fpDest[iSample] += fpSrc[iSample];*/
  76. }
  77. #ifdef ARCH_X86
  78. void jack_port_set_funcs ()
  79. {
  80. if (ARCH_X86_HAVE_SSE2 (cpu_type)) {
  81. opt_copy = x86_sse_copyf;
  82. opt_mix = x86_sse_add2f;
  83. } else if (ARCH_X86_HAVE_3DNOW (cpu_type)) {
  84. opt_copy = x86_3dnow_copyf;
  85. opt_mix = x86_3dnow_add2f;
  86. } else {
  87. opt_copy = gen_copyf;
  88. opt_mix = gen_mixf;
  89. }
  90. }
  91. #else /* ARCH_X86 */
  92. void jack_port_set_funcs ()
  93. {
  94. opt_copy = gen_copyf;
  95. opt_mix = gen_mixf;
  96. }
  97. #endif /* ARCH_X86 */
  98. #endif /* USE_DYNSIMD */
  99. int
  100. jack_port_name_equals (jack_port_shared_t* port, const char* target)
  101. {
  102. char buf[JACK_PORT_NAME_SIZE + 1];
  103. /* this nasty, nasty kludge is here because between 0.109.0 and 0.109.1,
  104. the ALSA audio backend had the name "ALSA", whereas as before and
  105. after it, it was called "alsa_pcm". this stops breakage for
  106. any setups that have saved "alsa_pcm" or "ALSA" in their connection
  107. state.
  108. */
  109. if (strncmp (target, "ALSA:capture", 12) == 0 || strncmp (target, "ALSA:playback", 13) == 0) {
  110. snprintf (buf, sizeof(buf), "alsa_pcm%s", target + 4);
  111. target = buf;
  112. }
  113. return strcmp (port->name, target) == 0 ||
  114. strcmp (port->alias1, target) == 0 ||
  115. strcmp (port->alias2, target) == 0;
  116. }
  117. jack_port_functions_t *
  118. jack_get_port_functions (jack_port_type_id_t ptid)
  119. {
  120. switch (ptid) {
  121. case JACK_AUDIO_PORT_TYPE:
  122. return &jack_builtin_audio_functions;
  123. case JACK_MIDI_PORT_TYPE:
  124. return &jack_builtin_midi_functions;
  125. /* no other builtin functions */
  126. default:
  127. return NULL;
  128. }
  129. }
  130. /*
  131. * Fills buffer with zeroes. For audio ports, engine->silent_buffer relies on it.
  132. */
  133. static void
  134. jack_generic_buffer_init (void *buffer, size_t size, jack_nframes_t nframes)
  135. {
  136. memset (buffer, 0, size);
  137. }
  138. jack_port_t *
  139. jack_port_new (const jack_client_t *client, jack_port_id_t port_id,
  140. jack_control_t *control)
  141. {
  142. jack_port_shared_t *shared = &control->ports[port_id];
  143. jack_port_type_id_t ptid = shared->ptype_id;
  144. jack_port_t *port;
  145. if ((port = (jack_port_t*)malloc (sizeof(jack_port_t))) == NULL) {
  146. return NULL;
  147. }
  148. port->mix_buffer = NULL;
  149. port->client_segment_base = NULL;
  150. port->shared = shared;
  151. port->type_info = &client->engine->port_types[ptid];
  152. pthread_mutex_init (&port->connection_lock, NULL);
  153. port->connections = 0;
  154. port->tied = NULL;
  155. if (jack_uuid_compare (client->control->uuid, port->shared->client_id) == 0) {
  156. /* It's our port, so initialize the pointers to port
  157. * functions within this address space. These builtin
  158. * definitions can be overridden by the client.
  159. */
  160. jack_port_functions_t *port_functions = jack_get_port_functions (ptid);
  161. if (port_functions == NULL) {
  162. port_functions = &jack_builtin_NULL_functions;
  163. }
  164. port->fptr = *port_functions;
  165. port->shared->has_mixdown = (port->fptr.mixdown ? TRUE : FALSE);
  166. }
  167. /* set up a base address so that port->offset can be used to
  168. compute the correct location. we don't store the location
  169. directly, because port->client_segment_base and/or
  170. port->offset can change if the buffer size or port counts
  171. are changed.
  172. */
  173. port->client_segment_base =
  174. (void**)&client->port_segment[ptid].attached_at;
  175. return port;
  176. }
  177. size_t
  178. jack_port_type_get_buffer_size (jack_client_t *client, const char *port_type)
  179. {
  180. int i;
  181. for (i = 0; i < client->engine->n_port_types; i++)
  182. if (!strcmp (port_type, client->engine->port_types[i].type_name)) {
  183. break;
  184. }
  185. if (i == client->engine->n_port_types) {
  186. return 0;
  187. }
  188. return jack_port_type_buffer_size (&(client->engine->port_types[i]), client->engine->buffer_size);
  189. }
  190. jack_port_t *
  191. jack_port_register (jack_client_t *client,
  192. const char *port_name,
  193. const char *port_type,
  194. unsigned long flags,
  195. unsigned long buffer_size)
  196. {
  197. jack_request_t req;
  198. jack_port_t *port = 0;
  199. int length;
  200. VALGRIND_MEMSET (&req, 0, sizeof(req));
  201. req.type = RegisterPort;
  202. length = strlen ((const char*)client->control->name)
  203. + 1 + strlen (port_name);
  204. if ( length >= sizeof(req.x.port_info.name) ) {
  205. jack_error ("\"%s:%s\" is too long to be used as a JACK port name.\n"
  206. "Please use %lu characters or less.",
  207. client->control->name,
  208. port_name,
  209. sizeof(req.x.port_info.name) - 1);
  210. return NULL;
  211. }
  212. strcpy ((char*)req.x.port_info.name,
  213. (const char*)client->control->name);
  214. strcat ((char*)req.x.port_info.name, ":");
  215. strcat ((char*)req.x.port_info.name, port_name);
  216. snprintf (req.x.port_info.type, sizeof(req.x.port_info.type),
  217. "%s", port_type);
  218. req.x.port_info.flags = flags;
  219. req.x.port_info.buffer_size = buffer_size;
  220. jack_uuid_copy (&req.x.port_info.client_id, client->control->uuid);
  221. if (jack_client_deliver_request (client, &req)) {
  222. jack_error ("cannot deliver port registration request");
  223. return NULL;
  224. }
  225. if ((port = jack_port_new (client, req.x.port_info.port_id,
  226. client->engine)) == NULL) {
  227. jack_error ("cannot allocate client side port structure");
  228. return NULL;
  229. }
  230. client->ports = jack_slist_prepend (client->ports, port);
  231. return port;
  232. }
  233. int
  234. jack_port_unregister (jack_client_t *client, jack_port_t *port)
  235. {
  236. jack_request_t req;
  237. VALGRIND_MEMSET (&req, 0, sizeof(req));
  238. req.type = UnRegisterPort;
  239. req.x.port_info.port_id = port->shared->id;
  240. jack_uuid_copy (&req.x.port_info.client_id, client->control->uuid);
  241. return jack_client_deliver_request (client, &req);
  242. }
  243. /* LOCAL (in-client) connection querying only */
  244. int
  245. jack_port_connected (const jack_port_t *port)
  246. {
  247. return jack_slist_length (port->connections);
  248. }
  249. int
  250. jack_port_connected_to (const jack_port_t *port, const char *portname)
  251. {
  252. JSList *node;
  253. int ret = FALSE;
  254. /* XXX this really requires a cross-process lock
  255. so that ports/connections cannot go away
  256. while we are checking for them. that's hard,
  257. and has a non-trivial performance impact
  258. for jackd.
  259. */
  260. pthread_mutex_lock (&((jack_port_t*)port)->connection_lock);
  261. for (node = port->connections; node; node = jack_slist_next (node)) {
  262. jack_port_t *other_port = (jack_port_t*)node->data;
  263. if (jack_port_name_equals (other_port->shared, portname)) {
  264. ret = TRUE;
  265. break;
  266. }
  267. }
  268. pthread_mutex_unlock (&((jack_port_t*)port)->connection_lock);
  269. return ret;
  270. }
  271. const char **
  272. jack_port_get_connections (const jack_port_t *port)
  273. {
  274. const char **ret = NULL;
  275. JSList *node;
  276. unsigned int n;
  277. /* XXX this really requires a cross-process lock
  278. so that ports/connections cannot go away
  279. while we are checking for them. that's hard,
  280. and has a non-trivial performance impact
  281. for jackd.
  282. */
  283. pthread_mutex_lock (&((jack_port_t*)port)->connection_lock);
  284. if (port->connections != NULL) {
  285. ret = (const char**)
  286. malloc (sizeof(char *)
  287. * (jack_slist_length (port->connections) + 1));
  288. if (ret == NULL) {
  289. pthread_mutex_unlock (&((jack_port_t*)port)->connection_lock);
  290. return NULL;
  291. }
  292. for (n = 0, node = port->connections; node;
  293. node = jack_slist_next (node), ++n) {
  294. jack_port_t* other = (jack_port_t*)node->data;
  295. ret[n] = other->shared->name;
  296. }
  297. ret[n] = NULL;
  298. }
  299. pthread_mutex_unlock (&((jack_port_t*)port)->connection_lock);
  300. return ret;
  301. }
  302. /* SERVER-SIDE (all) connection querying */
  303. const char **
  304. jack_port_get_all_connections (const jack_client_t *client,
  305. const jack_port_t *port)
  306. {
  307. const char **ret;
  308. jack_request_t req;
  309. jack_port_t *tmp;
  310. unsigned int i;
  311. int need_free = FALSE;
  312. if (port == NULL) {
  313. return NULL;
  314. }
  315. VALGRIND_MEMSET (&req, 0, sizeof(req));
  316. req.type = GetPortConnections;
  317. req.x.port_info.name[0] = '\0';
  318. req.x.port_info.type[0] = '\0';
  319. req.x.port_info.flags = 0;
  320. req.x.port_info.buffer_size = 0;
  321. jack_uuid_clear (&req.x.port_info.client_id);
  322. req.x.port_info.port_id = port->shared->id;
  323. jack_client_deliver_request (client, &req);
  324. if (req.status != 0 || req.x.port_connections.nports == 0) {
  325. return NULL;
  326. }
  327. if (client->request_fd < 0) {
  328. /* internal client, .ports is in our own address space */
  329. return req.x.port_connections.ports;
  330. }
  331. if ((ret = (const char**)malloc (sizeof(char *) * (req.x.port_connections.nports + 1))) == NULL) {
  332. return NULL;
  333. }
  334. for (i = 0; i < req.x.port_connections.nports; ++i ) {
  335. jack_port_id_t port_id;
  336. if (read (client->request_fd, &port_id, sizeof(port_id))
  337. != sizeof(port_id)) {
  338. jack_error ("cannot read port id from server");
  339. return 0;
  340. }
  341. tmp = jack_port_by_id_int (client, port_id, &need_free);
  342. ret[i] = tmp->shared->name;
  343. if (need_free) {
  344. free (tmp);
  345. need_free = FALSE;
  346. }
  347. }
  348. ret[i] = NULL;
  349. return ret;
  350. }
  351. jack_port_t *
  352. jack_port_by_id_int (const jack_client_t *client, jack_port_id_t id, int* free)
  353. {
  354. JSList *node;
  355. for (node = client->ports; node; node = jack_slist_next (node)) {
  356. if (((jack_port_t*)node->data)->shared->id == id) {
  357. *free = FALSE;
  358. return (jack_port_t*)node->data;
  359. }
  360. }
  361. if (id >= client->engine->port_max) {
  362. return NULL;
  363. }
  364. if (client->engine->ports[id].in_use) {
  365. *free = TRUE;
  366. return jack_port_new (client, id, client->engine);
  367. }
  368. return NULL;
  369. }
  370. jack_port_t *
  371. jack_port_by_id (jack_client_t *client, jack_port_id_t id)
  372. {
  373. JSList *node;
  374. jack_port_t* port;
  375. int need_free = FALSE;
  376. for (node = client->ports_ext; node; node = jack_slist_next (node)) {
  377. port = node->data;
  378. if (port->shared->id == id) { // Found port, return the cached structure
  379. return port;
  380. }
  381. }
  382. // Otherwise possibly allocate a new port structure, keep it in the ports_ext list for later use
  383. port = jack_port_by_id_int (client, id, &need_free);
  384. if (port != NULL && need_free) {
  385. client->ports_ext =
  386. jack_slist_prepend (client->ports_ext, port);
  387. }
  388. return port;
  389. }
  390. jack_port_t *
  391. jack_port_by_name_int (jack_client_t *client, const char *port_name, int* free)
  392. {
  393. JSList *node;
  394. for (node = client->ports; node; node = jack_slist_next (node)) {
  395. if (jack_port_name_equals(((jack_port_t *) node->data)->shared, port_name)) {
  396. *free = FALSE;
  397. return (jack_port_t *) node->data;
  398. }
  399. }
  400. unsigned long i, limit;
  401. jack_port_shared_t *port;
  402. limit = client->engine->port_max;
  403. port = &client->engine->ports[0];
  404. for (i = 0; i < limit; i++) {
  405. if (port[i].in_use && jack_port_name_equals (&port[i], port_name)) {
  406. *free = TRUE;
  407. return jack_port_new (client, port[i].id,
  408. client->engine);
  409. }
  410. }
  411. return NULL;
  412. }
  413. jack_port_t *
  414. jack_port_by_name (jack_client_t *client, const char *port_name)
  415. {
  416. JSList *node;
  417. jack_port_t* port;
  418. int need_free = FALSE;
  419. for (node = client->ports_ext; node; node = jack_slist_next (node)) {
  420. port = node->data;
  421. if (jack_port_name_equals (port->shared, port_name)) {
  422. /* Found port, return the cached structure. */
  423. return port;
  424. }
  425. }
  426. /* Otherwise allocate a new port structure, keep it in the
  427. * ports_ext list for later use. */
  428. port = jack_port_by_name_int (client, port_name, &need_free);
  429. if (port != NULL && need_free) {
  430. client->ports_ext =
  431. jack_slist_prepend (client->ports_ext, port);
  432. }
  433. return port;
  434. }
  435. jack_nframes_t
  436. jack_port_get_latency (jack_port_t *port)
  437. {
  438. return port->shared->latency;
  439. }
  440. jack_nframes_t
  441. jack_port_get_total_latency (jack_client_t *client, jack_port_t *port)
  442. {
  443. return port->shared->total_latency;
  444. }
  445. void
  446. jack_port_set_latency (jack_port_t *port, jack_nframes_t nframes)
  447. {
  448. port->shared->latency = nframes;
  449. /* setup the new latency values here,
  450. * so we dont need to change the backend codes.
  451. */
  452. if (port->shared->flags & JackPortIsOutput) {
  453. port->shared->capture_latency.min = nframes;
  454. port->shared->capture_latency.max = nframes;
  455. }
  456. if (port->shared->flags & JackPortIsInput) {
  457. port->shared->playback_latency.min = nframes;
  458. port->shared->playback_latency.max = nframes;
  459. }
  460. }
  461. void *
  462. jack_port_get_buffer (jack_port_t *port, jack_nframes_t nframes)
  463. {
  464. JSList *node, *next;
  465. /* Output port. The buffer was assigned by the engine
  466. when the port was registered.
  467. */
  468. if (port->shared->flags & JackPortIsOutput) {
  469. if (port->tied) {
  470. return jack_port_get_buffer (port->tied, nframes);
  471. }
  472. if (port->client_segment_base == NULL || *port->client_segment_base == MAP_FAILED) {
  473. return NULL;
  474. }
  475. return jack_output_port_buffer (port);
  476. }
  477. /* Input port. Since this can only be called from the
  478. process() callback, and since no connections can be
  479. made/broken during this phase (enforced by the jack
  480. server), there is no need to take the connection lock here
  481. */
  482. if ((node = port->connections) == NULL) {
  483. if (port->client_segment_base == NULL || *port->client_segment_base == MAP_FAILED) {
  484. return NULL;
  485. }
  486. /* no connections; return a zero-filled buffer */
  487. return (void*)(*(port->client_segment_base) + port->type_info->zero_buffer_offset);
  488. }
  489. if ((next = jack_slist_next (node)) == NULL) {
  490. /* one connection: use zero-copy mode - just pass
  491. the buffer of the connected (output) port.
  492. */
  493. return jack_port_get_buffer (((jack_port_t*)node->data),
  494. nframes);
  495. }
  496. /* Multiple connections. Use a local buffer and mix the
  497. incoming data into that buffer. We have already
  498. established the existence of a mixdown function during the
  499. connection process.
  500. */
  501. if (port->mix_buffer == NULL) {
  502. jack_error ( "internal jack error: mix_buffer not allocated" );
  503. return NULL;
  504. }
  505. port->fptr.mixdown (port, nframes);
  506. return (void*)port->mix_buffer;
  507. }
  508. size_t
  509. jack_port_type_buffer_size (jack_port_type_info_t* port_type_info, jack_nframes_t nframes)
  510. {
  511. if ( port_type_info->buffer_scale_factor < 0 ) {
  512. return port_type_info->buffer_size;
  513. }
  514. return port_type_info->buffer_scale_factor
  515. * sizeof(jack_default_audio_sample_t)
  516. * nframes;
  517. }
  518. int
  519. jack_port_tie (jack_port_t *src, jack_port_t *dst)
  520. {
  521. if (dst->shared->client_id != src->shared->client_id) {
  522. jack_error ("cannot tie ports not owned by the same client");
  523. return -1;
  524. }
  525. if (dst->shared->flags & JackPortIsOutput) {
  526. jack_error ("cannot tie an input port");
  527. return -1;
  528. }
  529. dst->tied = src;
  530. return 0;
  531. }
  532. int
  533. jack_port_untie (jack_port_t *port)
  534. {
  535. if (port->tied == NULL) {
  536. jack_error ("port \"%s\" is not tied", port->shared->name);
  537. return -1;
  538. }
  539. port->tied = NULL;
  540. return 0;
  541. }
  542. int
  543. jack_port_request_monitor (jack_port_t *port, int onoff)
  544. {
  545. if (onoff) {
  546. port->shared->monitor_requests++;
  547. } else if (port->shared->monitor_requests) {
  548. port->shared->monitor_requests--;
  549. }
  550. if ((port->shared->flags & JackPortIsOutput) == 0) {
  551. JSList *node;
  552. /* this port is for input, so recurse over each of the
  553. connected ports.
  554. */
  555. pthread_mutex_lock (&port->connection_lock);
  556. for (node = port->connections; node;
  557. node = jack_slist_next (node)) {
  558. /* drop the lock because if there is a feedback loop,
  559. we will deadlock. XXX much worse things will
  560. happen if there is a feedback loop !!!
  561. */
  562. pthread_mutex_unlock (&port->connection_lock);
  563. jack_port_request_monitor ((jack_port_t*)node->data,
  564. onoff);
  565. pthread_mutex_lock (&port->connection_lock);
  566. }
  567. pthread_mutex_unlock (&port->connection_lock);
  568. }
  569. return 0;
  570. }
  571. int
  572. jack_port_request_monitor_by_name (jack_client_t *client,
  573. const char *port_name, int onoff)
  574. {
  575. jack_port_t *port;
  576. unsigned long i, limit;
  577. jack_port_shared_t *ports;
  578. limit = client->engine->port_max;
  579. ports = &client->engine->ports[0];
  580. for (i = 0; i < limit; i++) {
  581. if (ports[i].in_use &&
  582. strcmp (ports[i].name, port_name) == 0) {
  583. port = jack_port_new (client, ports[i].id,
  584. client->engine);
  585. return jack_port_request_monitor (port, onoff);
  586. free (port);
  587. return 0;
  588. }
  589. }
  590. return -1;
  591. }
  592. int
  593. jack_port_ensure_monitor (jack_port_t *port, int yn)
  594. {
  595. if (yn) {
  596. if (port->shared->monitor_requests == 0) {
  597. port->shared->monitor_requests++;
  598. }
  599. } else {
  600. if (port->shared->monitor_requests > 0) {
  601. port->shared->monitor_requests = 0;
  602. }
  603. }
  604. return 0;
  605. }
  606. int
  607. jack_port_monitoring_input (jack_port_t *port)
  608. {
  609. return port->shared->monitor_requests > 0;
  610. }
  611. const char *
  612. jack_port_name (const jack_port_t *port)
  613. {
  614. return port->shared->name;
  615. }
  616. jack_uuid_t
  617. jack_port_uuid (const jack_port_t *port)
  618. {
  619. return port->shared->uuid;
  620. }
  621. int
  622. jack_port_get_aliases (const jack_port_t *port, char* const aliases[2])
  623. {
  624. int cnt = 0;
  625. if (port->shared->alias1[0] != '\0') {
  626. snprintf (aliases[0], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", port->shared->alias1);
  627. cnt++;
  628. }
  629. if (port->shared->alias2[0] != '\0') {
  630. snprintf (aliases[1], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", port->shared->alias2);
  631. cnt++;
  632. }
  633. return cnt;
  634. }
  635. const char *
  636. jack_port_short_name (const jack_port_t *port)
  637. {
  638. /* we know there is always a colon, because we put
  639. it there ...
  640. */
  641. return strchr (port->shared->name, ':') + 1;
  642. }
  643. int
  644. jack_port_is_mine (const jack_client_t *client, const jack_port_t *port)
  645. {
  646. return jack_uuid_compare (port->shared->client_id, client->control->uuid) == 0;
  647. }
  648. int
  649. jack_port_flags (const jack_port_t *port)
  650. {
  651. return port->shared->flags;
  652. }
  653. const char *
  654. jack_port_type (const jack_port_t *port)
  655. {
  656. return port->type_info->type_name;
  657. }
  658. int
  659. jack_port_rename (jack_client_t* client, jack_port_t *port, const char *new_name)
  660. {
  661. int ret;
  662. char* old_name = strdup (port->shared->name);
  663. if ((ret = jack_port_set_name (port, new_name)) == 0) {
  664. /* tell server about name change */
  665. jack_request_t req;
  666. req.type = PortNameChanged;
  667. /* re-purpose an appropriate part of the request union to convey the names */
  668. snprintf ((char*)req.x.connect.source_port, JACK_PORT_NAME_SIZE - 1, "%s", old_name);
  669. snprintf ((char*)req.x.connect.destination_port, JACK_PORT_NAME_SIZE - 1, "%s", new_name);
  670. (void)jack_client_deliver_request (client, &req);
  671. }
  672. free (old_name);
  673. return ret;
  674. }
  675. int
  676. jack_port_set_name (jack_port_t *port, const char *new_name)
  677. {
  678. char *colon;
  679. int len;
  680. if (strcmp (new_name, port->shared->name) == 0) {
  681. return 0;
  682. }
  683. colon = strchr (port->shared->name, ':');
  684. len = sizeof(port->shared->name) -
  685. ((int)(colon - port->shared->name)) - 2;
  686. snprintf (colon + 1, len, "%s", new_name);
  687. return 0;
  688. }
  689. int
  690. jack_port_set_alias (jack_port_t *port, const char *alias)
  691. {
  692. if (port->shared->alias1[0] == '\0') {
  693. snprintf (port->shared->alias1, sizeof(port->shared->alias1), "%s", alias);
  694. } else if (port->shared->alias2[0] == '\0') {
  695. snprintf (port->shared->alias2, sizeof(port->shared->alias2), "%s", alias);
  696. } else {
  697. return -1;
  698. }
  699. return 0;
  700. }
  701. int
  702. jack_port_unset_alias (jack_port_t *port, const char *alias)
  703. {
  704. if (strcmp (port->shared->alias1, alias) == 0) {
  705. port->shared->alias1[0] = '\0';
  706. } else if (strcmp (port->shared->alias2, alias) == 0) {
  707. port->shared->alias2[0] = '\0';
  708. } else {
  709. return -1;
  710. }
  711. return 0;
  712. }
  713. void
  714. jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
  715. {
  716. if (mode == JackCaptureLatency) {
  717. port->shared->capture_latency = *range;
  718. /* hack to set port->shared->latency up for
  719. * backend ports
  720. */
  721. if ((port->shared->flags & JackPortIsOutput) && (port->shared->flags & JackPortIsPhysical)) {
  722. port->shared->latency = (range->min + range->max) / 2;
  723. }
  724. } else {
  725. port->shared->playback_latency = *range;
  726. /* hack to set port->shared->latency up for
  727. * backend ports
  728. */
  729. if ((port->shared->flags & JackPortIsInput) && (port->shared->flags & JackPortIsPhysical)) {
  730. port->shared->latency = (range->min + range->max) / 2;
  731. }
  732. }
  733. }
  734. void
  735. jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
  736. {
  737. if (mode == JackCaptureLatency) {
  738. *range = port->shared->capture_latency;
  739. } else {
  740. *range = port->shared->playback_latency;
  741. }
  742. }
  743. /* AUDIO PORT SUPPORT */
  744. static inline float f_max (float x, float a)
  745. {
  746. x -= a;
  747. x += fabs (x);
  748. x *= 0.5;
  749. x += a;
  750. return x;
  751. }
  752. static void
  753. jack_audio_port_mixdown (jack_port_t *port, jack_nframes_t nframes)
  754. {
  755. JSList *node;
  756. jack_port_t *input;
  757. #ifndef ARCH_X86
  758. jack_nframes_t n;
  759. jack_default_audio_sample_t *dst, *src;
  760. #endif
  761. jack_default_audio_sample_t *buffer;
  762. /* by the time we've called this, we've already established
  763. the existence of more than one connection to this input
  764. port and allocated a mix_buffer.
  765. */
  766. /* no need to take connection lock, since this is called
  767. from the process() callback, and the jack server
  768. ensures that no changes to connections happen
  769. during this time.
  770. */
  771. node = port->connections;
  772. input = (jack_port_t*)node->data;
  773. buffer = port->mix_buffer;
  774. #ifndef USE_DYNSIMD
  775. memcpy (buffer, jack_output_port_buffer (input),
  776. sizeof(jack_default_audio_sample_t) * nframes);
  777. #else /* USE_DYNSIMD */
  778. opt_copy (buffer, jack_output_port_buffer (input), nframes);
  779. #endif /* USE_DYNSIMD */
  780. for (node = jack_slist_next (node); node;
  781. node = jack_slist_next (node)) {
  782. input = (jack_port_t*)node->data;
  783. #ifndef USE_DYNSIMD
  784. n = nframes;
  785. dst = buffer;
  786. src = jack_output_port_buffer (input);
  787. while (n--)
  788. *dst++ += *src++;
  789. #else /* USE_DYNSIMD */
  790. opt_mix (buffer, jack_output_port_buffer (input), nframes);
  791. #endif /* USE_DYNSIMD */
  792. }
  793. }