fix debug message when acquiring the "problem" lock
[jack.git] / libjack / port.c
blob49778038332d76634a07721192c8f9fa3c958070
1 /*
2 Copyright (C) 2001-2003 Paul Davis
3 Copyright (C) 2005 Jussi Laako
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include <string.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include <config.h>
27 #include <jack/jack.h>
28 #include <jack/types.h>
29 #include <jack/internal.h>
30 #include <jack/engine.h>
31 #include <jack/pool.h>
32 #include <jack/port.h>
33 #include <jack/midiport.h>
34 #include <jack/jslist.h>
35 #include <jack/intsimd.h>
37 #include "local.h"
39 static void jack_generic_buffer_init(void *port_buffer,
40 size_t buffer_size,
41 jack_nframes_t nframes);
43 static void jack_audio_port_mixdown (jack_port_t *port,
44 jack_nframes_t nframes);
46 /* These function pointers are local to each address space. For
47 * internal clients they reside within jackd; for external clients in
48 * the application process. */
49 jack_port_functions_t jack_builtin_audio_functions = {
50 .buffer_init = jack_generic_buffer_init,
51 .mixdown = jack_audio_port_mixdown,
54 extern jack_port_functions_t jack_builtin_midi_functions;
56 jack_port_functions_t jack_builtin_NULL_functions = {
57 .buffer_init = jack_generic_buffer_init,
58 .mixdown = NULL,
61 /* Only the Audio and MIDI port types are currently built in. */
62 jack_port_type_info_t jack_builtin_port_types[] = {
63 { .type_name = JACK_DEFAULT_AUDIO_TYPE,
64 .buffer_scale_factor = 1,
66 { .type_name = JACK_DEFAULT_MIDI_TYPE,
67 .buffer_scale_factor = 1,
69 { .type_name = "", }
72 /* these functions have been taken from libDSP X86.c -jl */
74 #ifdef USE_DYNSIMD
76 static void (*opt_copy) (float *, const float *, int);
77 static void (*opt_mix) (float *, const float *, int);
79 static void
80 gen_copyf (float *dest, const float *src, int length)
82 memcpy(dest, src, length * sizeof(float));
85 static void
86 gen_mixf (float *dest, const float *src, int length)
88 int n;
90 n = length;
91 while (n--)
92 *dest++ += *src++;
93 /*for (iSample = 0; iSample < iDataLength; iSample++)
94 fpDest[iSample] += fpSrc[iSample];*/
97 #ifdef ARCH_X86
99 void jack_port_set_funcs ()
101 if (ARCH_X86_HAVE_SSE2(cpu_type)) {
102 opt_copy = x86_sse_copyf;
103 opt_mix = x86_sse_add2f;
105 else if (ARCH_X86_HAVE_3DNOW(cpu_type)) {
106 opt_copy = x86_3dnow_copyf;
107 opt_mix = x86_3dnow_add2f;
109 else {
110 opt_copy = gen_copyf;
111 opt_mix = gen_mixf;
115 #else /* ARCH_X86 */
117 void jack_port_set_funcs ()
119 opt_copy = gen_copyf;
120 opt_mix = gen_mixf;
123 #endif /* ARCH_X86 */
125 #endif /* USE_DYNSIMD */
128 jack_port_name_equals (jack_port_shared_t* port, const char* target)
130 char buf[JACK_PORT_NAME_SIZE+1];
132 /* this nasty, nasty kludge is here because between 0.109.0 and 0.109.1,
133 the ALSA audio backend had the name "ALSA", whereas as before and
134 after it, it was called "alsa_pcm". this stops breakage for
135 any setups that have saved "alsa_pcm" or "ALSA" in their connection
136 state.
139 if (strncmp (target, "ALSA:capture", 12) == 0 || strncmp (target, "ALSA:playback", 13) == 0) {
140 snprintf (buf, sizeof (buf), "alsa_pcm%s", target+4);
141 target = buf;
144 return (strcmp (port->name, target) == 0 ||
145 strcmp (port->alias1, target) == 0 ||
146 strcmp (port->alias2, target) == 0);
149 jack_port_functions_t *
150 jack_get_port_functions(jack_port_type_id_t ptid)
152 switch (ptid) {
153 case JACK_AUDIO_PORT_TYPE:
154 return &jack_builtin_audio_functions;
155 case JACK_MIDI_PORT_TYPE:
156 return &jack_builtin_midi_functions;
157 /* no other builtin functions */
158 default:
159 return NULL;
164 * Fills buffer with zeroes. For audio ports, engine->silent_buffer relies on it.
166 static void
167 jack_generic_buffer_init(void *buffer, size_t size, jack_nframes_t nframes)
169 memset(buffer, 0, size);
173 jack_port_t *
174 jack_port_new (const jack_client_t *client, jack_port_id_t port_id,
175 jack_control_t *control)
177 jack_port_shared_t *shared = &control->ports[port_id];
178 jack_port_type_id_t ptid = shared->ptype_id;
179 jack_port_t *port = (jack_port_t *) malloc (sizeof (jack_port_t));
181 port->mix_buffer = NULL;
182 port->client_segment_base = NULL;
183 port->shared = shared;
184 port->type_info = &client->engine->port_types[ptid];
185 pthread_mutex_init (&port->connection_lock, NULL);
186 port->connections = 0;
187 port->tied = NULL;
189 if (client->control->id == port->shared->client_id) {
191 /* It's our port, so initialize the pointers to port
192 * functions within this address space. These builtin
193 * definitions can be overridden by the client.
195 jack_port_functions_t *port_functions = jack_get_port_functions(ptid);
196 if (port_functions == NULL)
197 port_functions = &jack_builtin_NULL_functions;
198 port->fptr = *port_functions;
199 port->shared->has_mixdown = (port->fptr.mixdown ? TRUE : FALSE);
202 /* set up a base address so that port->offset can be used to
203 compute the correct location. we don't store the location
204 directly, because port->client_segment_base and/or
205 port->offset can change if the buffer size or port counts
206 are changed.
209 port->client_segment_base =
210 (void **) &client->port_segment[ptid].attached_at;
212 return port;
215 jack_port_t *
216 jack_port_register (jack_client_t *client,
217 const char *port_name,
218 const char *port_type,
219 unsigned long flags,
220 unsigned long buffer_size)
222 jack_request_t req;
223 jack_port_t *port = 0;
224 int length ;
226 req.type = RegisterPort;
228 length = strlen ((const char *) client->control->name)
229 + 1 + strlen (port_name);
230 if ( length >= sizeof (req.x.port_info.name) ) {
231 jack_error ("\"%s:%s\" is too long to be used as a JACK port name.\n"
232 "Please use %lu characters or less.",
233 client->control->name ,
234 port_name,
235 sizeof (req.x.port_info.name) - 1);
236 return NULL ;
239 strcpy ((char *) req.x.port_info.name,
240 (const char *) client->control->name);
241 strcat ((char *) req.x.port_info.name, ":");
242 strcat ((char *) req.x.port_info.name, port_name);
244 snprintf (req.x.port_info.type, sizeof (req.x.port_info.type),
245 "%s", port_type);
246 req.x.port_info.flags = flags;
247 req.x.port_info.buffer_size = buffer_size;
248 req.x.port_info.client_id = client->control->id;
250 if (jack_client_deliver_request (client, &req)) {
251 jack_error ("cannot deliver port registration request");
252 return NULL;
255 if ((port = jack_port_new (client, req.x.port_info.port_id,
256 client->engine)) == NULL) {
257 jack_error ("cannot allocate client side port structure");
258 return NULL;
261 client->ports = jack_slist_prepend (client->ports, port);
263 return port;
266 int
267 jack_port_unregister (jack_client_t *client, jack_port_t *port)
269 jack_request_t req;
271 req.type = UnRegisterPort;
272 req.x.port_info.port_id = port->shared->id;
273 req.x.port_info.client_id = client->control->id;
275 return jack_client_deliver_request (client, &req);
278 /* LOCAL (in-client) connection querying only */
281 jack_port_connected (const jack_port_t *port)
283 return jack_slist_length (port->connections);
287 jack_port_connected_to (const jack_port_t *port, const char *portname)
289 JSList *node;
290 int ret = FALSE;
292 /* XXX this really requires a cross-process lock
293 so that ports/connections cannot go away
294 while we are checking for them. that's hard,
295 and has a non-trivial performance impact
296 for jackd.
299 pthread_mutex_lock (&((jack_port_t *) port)->connection_lock);
301 for (node = port->connections; node; node = jack_slist_next (node)) {
302 jack_port_t *other_port = (jack_port_t *) node->data;
304 if (jack_port_name_equals (other_port->shared, portname)) {
305 ret = TRUE;
306 break;
310 pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock);
311 return ret;
314 const char **
315 jack_port_get_connections (const jack_port_t *port)
317 const char **ret = NULL;
318 JSList *node;
319 unsigned int n;
321 /* XXX this really requires a cross-process lock
322 so that ports/connections cannot go away
323 while we are checking for them. that's hard,
324 and has a non-trivial performance impact
325 for jackd.
328 pthread_mutex_lock (&((jack_port_t *) port)->connection_lock);
330 if (port->connections != NULL) {
332 ret = (const char **)
333 malloc (sizeof (char *)
334 * (jack_slist_length (port->connections) + 1));
335 for (n = 0, node = port->connections; node;
336 node = jack_slist_next (node), ++n) {
337 jack_port_t* other =(jack_port_t *) node->data;
338 ret[n] = other->shared->name;
340 ret[n] = NULL;
343 pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock);
344 return ret;
347 /* SERVER-SIDE (all) connection querying */
349 const char **
350 jack_port_get_all_connections (const jack_client_t *client,
351 const jack_port_t *port)
353 const char **ret;
354 jack_request_t req;
355 jack_port_t *tmp;
356 unsigned int i;
357 int need_free = FALSE;
359 if (port == NULL) {
360 return NULL;
363 req.type = GetPortConnections;
365 req.x.port_info.name[0] = '\0';
366 req.x.port_info.type[0] = '\0';
367 req.x.port_info.flags = 0;
368 req.x.port_info.buffer_size = 0;
369 req.x.port_info.client_id = 0;
370 req.x.port_info.port_id = port->shared->id;
372 jack_client_deliver_request (client, &req);
374 if (req.status != 0 || req.x.port_connections.nports == 0) {
375 return NULL;
378 if (client->request_fd < 0) {
379 /* internal client, .ports is in our own address space */
380 return req.x.port_connections.ports;
383 ret = (const char **)
384 malloc (sizeof (char *) * (req.x.port_connections.nports + 1));
386 for (i = 0; i < req.x.port_connections.nports; ++i ) {
387 jack_port_id_t port_id;
389 if (read (client->request_fd, &port_id, sizeof (port_id))
390 != sizeof (port_id)) {
391 jack_error ("cannot read port id from server");
392 return 0;
394 tmp = jack_port_by_id_int (client, port_id, &need_free);
395 ret[i] = tmp->shared->name;
396 if (need_free) {
397 free (tmp);
398 need_free = FALSE;
402 ret[i] = NULL;
404 return ret;
407 jack_port_t *
408 jack_port_by_id_int (const jack_client_t *client, jack_port_id_t id, int* free)
410 JSList *node;
412 for (node = client->ports; node; node = jack_slist_next (node)) {
413 if (((jack_port_t *) node->data)->shared->id == id) {
414 *free = FALSE;
415 return (jack_port_t *) node->data;
419 if (id >= client->engine->port_max)
420 return NULL;
422 if (client->engine->ports[id].in_use) {
423 *free = TRUE;
424 return jack_port_new (client, id, client->engine);
427 return NULL;
430 jack_port_t *
431 jack_port_by_id (jack_client_t *client, jack_port_id_t id)
433 JSList *node;
434 jack_port_t* port;
435 int need_free = FALSE;
436 for (node = client->ports_ext; node; node = jack_slist_next (node)) {
437 port = node->data;
438 if (port->shared->id == id) { // Found port, return the cached structure
439 return port;
443 // Otherwise possibly allocate a new port structure, keep it in the ports_ext list for later use
444 port = jack_port_by_id_int (client,id,&need_free);
445 if (port != NULL && need_free)
446 client->ports_ext =
447 jack_slist_prepend (client->ports_ext, port);
448 return port;
451 jack_port_t *
452 jack_port_by_name_int (jack_client_t *client, const char *port_name)
454 unsigned long i, limit;
455 jack_port_shared_t *port;
457 limit = client->engine->port_max;
458 port = &client->engine->ports[0];
460 for (i = 0; i < limit; i++) {
461 if (port[i].in_use && jack_port_name_equals (&port[i], port_name)) {
462 return jack_port_new (client, port[i].id,
463 client->engine);
467 return NULL;
470 jack_port_t *
471 jack_port_by_name (jack_client_t *client, const char *port_name)
473 JSList *node;
474 jack_port_t* port;
475 for (node = client->ports_ext; node; node = jack_slist_next (node)) {
476 port = node->data;
477 if (jack_port_name_equals (port->shared, port_name)) {
478 /* Found port, return the cached structure. */
479 return port;
483 /* Otherwise allocate a new port structure, keep it in the
484 * ports_ext list for later use. */
485 port = jack_port_by_name_int (client, port_name);
486 if (port != NULL)
487 client->ports_ext =
488 jack_slist_prepend (client->ports_ext, port);
489 return port;
492 jack_nframes_t
493 jack_port_get_latency (jack_port_t *port)
495 return port->shared->latency;
498 jack_nframes_t
499 jack_port_get_total_latency (jack_client_t *client, jack_port_t *port)
501 return port->shared->total_latency;
504 void
505 jack_port_set_latency (jack_port_t *port, jack_nframes_t nframes)
507 port->shared->latency = nframes;
510 void *
511 jack_port_get_buffer (jack_port_t *port, jack_nframes_t nframes)
513 JSList *node, *next;
515 /* Output port. The buffer was assigned by the engine
516 when the port was registered.
518 if (port->shared->flags & JackPortIsOutput) {
519 if (port->tied) {
520 return jack_port_get_buffer (port->tied, nframes);
523 return jack_output_port_buffer (port);
526 /* Input port. Since this can only be called from the
527 process() callback, and since no connections can be
528 made/broken during this phase (enforced by the jack
529 server), there is no need to take the connection lock here
531 if ((node = port->connections) == NULL) {
533 /* no connections; return a zero-filled buffer */
534 return (void *) (*(port->client_segment_base) + port->type_info->zero_buffer_offset);
537 if ((next = jack_slist_next (node)) == NULL) {
539 /* one connection: use zero-copy mode - just pass
540 the buffer of the connected (output) port.
542 return jack_port_get_buffer (((jack_port_t *) node->data),
543 nframes);
546 /* Multiple connections. Use a local buffer and mix the
547 incoming data into that buffer. We have already
548 established the existence of a mixdown function during the
549 connection process.
551 if (port->mix_buffer == NULL) {
552 size_t buffer_size =
553 port->type_info->buffer_scale_factor
554 * sizeof (jack_default_audio_sample_t)
555 * nframes;
556 port->mix_buffer = jack_pool_alloc (buffer_size);
557 port->fptr.buffer_init (port->mix_buffer, buffer_size, nframes);
559 port->fptr.mixdown (port, nframes);
560 return (void *) port->mix_buffer;
564 jack_port_tie (jack_port_t *src, jack_port_t *dst)
567 if (dst->shared->client_id != src->shared->client_id) {
568 jack_error ("cannot tie ports not owned by the same client");
569 return -1;
572 if (dst->shared->flags & JackPortIsOutput) {
573 jack_error ("cannot tie an input port");
574 return -1;
577 dst->tied = src;
578 return 0;
582 jack_port_untie (jack_port_t *port)
584 if (port->tied == NULL) {
585 jack_error ("port \"%s\" is not tied", port->shared->name);
586 return -1;
588 port->tied = NULL;
589 return 0;
592 int
593 jack_port_request_monitor (jack_port_t *port, int onoff)
596 if (onoff) {
597 port->shared->monitor_requests++;
598 } else if (port->shared->monitor_requests) {
599 port->shared->monitor_requests--;
602 if ((port->shared->flags & JackPortIsOutput) == 0) {
604 JSList *node;
606 /* this port is for input, so recurse over each of the
607 connected ports.
610 pthread_mutex_lock (&port->connection_lock);
611 for (node = port->connections; node;
612 node = jack_slist_next (node)) {
614 /* drop the lock because if there is a feedback loop,
615 we will deadlock. XXX much worse things will
616 happen if there is a feedback loop !!!
619 pthread_mutex_unlock (&port->connection_lock);
620 jack_port_request_monitor ((jack_port_t *) node->data,
621 onoff);
622 pthread_mutex_lock (&port->connection_lock);
624 pthread_mutex_unlock (&port->connection_lock);
627 return 0;
630 int
631 jack_port_request_monitor_by_name (jack_client_t *client,
632 const char *port_name, int onoff)
635 jack_port_t *port;
636 unsigned long i, limit;
637 jack_port_shared_t *ports;
639 limit = client->engine->port_max;
640 ports = &client->engine->ports[0];
642 for (i = 0; i < limit; i++) {
643 if (ports[i].in_use &&
644 strcmp (ports[i].name, port_name) == 0) {
645 port = jack_port_new (client, ports[i].id,
646 client->engine);
647 return jack_port_request_monitor (port, onoff);
648 free (port);
649 return 0;
653 return -1;
657 jack_port_ensure_monitor (jack_port_t *port, int yn)
659 if (yn) {
660 if (port->shared->monitor_requests == 0) {
661 port->shared->monitor_requests++;
663 } else {
664 if (port->shared->monitor_requests > 0) {
665 port->shared->monitor_requests = 0;
669 return 0;
673 jack_port_monitoring_input (jack_port_t *port)
675 return port->shared->monitor_requests > 0;
678 const char *
679 jack_port_name (const jack_port_t *port)
681 return port->shared->name;
685 jack_port_get_aliases (const jack_port_t *port, char* const aliases[2])
687 int cnt = 0;
689 if (port->shared->alias1[0] != '\0') {
690 snprintf (aliases[0], JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE, "%s", port->shared->alias1);
691 cnt++;
694 if (port->shared->alias2[0] != '\0') {
695 snprintf (aliases[1], JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE, "%s", port->shared->alias2);
696 cnt++;
699 return cnt;
702 const char *
703 jack_port_short_name (const jack_port_t *port)
705 /* we know there is always a colon, because we put
706 it there ...
709 return strchr (port->shared->name, ':') + 1;
712 int
713 jack_port_is_mine (const jack_client_t *client, const jack_port_t *port)
715 return port->shared->client_id == client->control->id;
719 jack_port_flags (const jack_port_t *port)
721 return port->shared->flags;
724 const char *
725 jack_port_type (const jack_port_t *port)
727 return port->type_info->type_name;
731 jack_port_set_name (jack_port_t *port, const char *new_name)
733 char *colon;
734 int len;
736 colon = strchr (port->shared->name, ':');
737 len = sizeof (port->shared->name) -
738 ((int) (colon - port->shared->name)) - 2;
739 snprintf (colon+1, len, "%s", new_name);
741 return 0;
745 jack_port_set_alias (jack_port_t *port, const char *alias)
747 if (port->shared->alias1[0] == '\0') {
748 snprintf (port->shared->alias1, sizeof (port->shared->alias1), "%s", alias);
749 } else if (port->shared->alias2[0] == '\0') {
750 snprintf (port->shared->alias2, sizeof (port->shared->alias2), "%s", alias);
751 } else {
752 return -1;
755 return 0;
759 jack_port_unset_alias (jack_port_t *port, const char *alias)
761 if (strcmp (port->shared->alias1, alias) == 0) {
762 port->shared->alias1[0] = '\0';
763 } else if (strcmp (port->shared->alias2, alias) == 0) {
764 port->shared->alias2[0] = '\0';
765 } else {
766 return -1;
769 return 0;
773 /* AUDIO PORT SUPPORT */
775 static inline float f_max(float x, float a)
777 x -= a;
778 x += fabs (x);
779 x *= 0.5;
780 x += a;
782 return (x);
785 static void
786 jack_audio_port_mixdown (jack_port_t *port, jack_nframes_t nframes)
788 JSList *node;
789 jack_port_t *input;
790 #ifndef ARCH_X86
791 jack_nframes_t n;
792 jack_default_audio_sample_t *dst, *src;
793 #endif
794 jack_default_audio_sample_t *buffer;
796 /* by the time we've called this, we've already established
797 the existence of more than one connection to this input
798 port and allocated a mix_buffer.
801 /* no need to take connection lock, since this is called
802 from the process() callback, and the jack server
803 ensures that no changes to connections happen
804 during this time.
807 node = port->connections;
808 input = (jack_port_t *) node->data;
809 buffer = port->mix_buffer;
811 #ifndef USE_DYNSIMD
812 memcpy (buffer, jack_output_port_buffer (input),
813 sizeof (jack_default_audio_sample_t) * nframes);
814 #else /* USE_DYNSIMD */
815 opt_copy (buffer, jack_output_port_buffer (input), nframes);
816 #endif /* USE_DYNSIMD */
818 for (node = jack_slist_next (node); node;
819 node = jack_slist_next (node)) {
821 input = (jack_port_t *) node->data;
823 #ifndef USE_DYNSIMD
824 n = nframes;
825 dst = buffer;
826 src = jack_output_port_buffer (input);
828 while (n--) {
829 *dst++ += *src++;
831 #else /* USE_DYNSIMD */
832 opt_mix (buffer, jack_output_port_buffer (input), nframes);
833 #endif /* USE_DYNSIMD */