netjack changes from torben (packet loss handling leads to "dummy" backend-like behav...
[jack.git] / jackd / engine.c
blob2a6d390a4a1a78fe54e84d1281da752892c217a0
1 /* -*- mode: c; c-file-style: "bsd"; -*- */
2 /*
3 Copyright (C) 2001-2003 Paul Davis
4 Copyright (C) 2004 Jack O'Quin
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <config.h>
24 #include <math.h>
25 #include <unistd.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <sys/stat.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #ifdef HAVE_STDINT_H
34 #include <stdint.h>
35 #endif
36 #include <dirent.h>
37 #include <signal.h>
38 #include <sys/types.h>
39 #include <string.h>
40 #include <limits.h>
42 #include <jack/internal.h>
43 #include <jack/engine.h>
44 #include <jack/messagebuffer.h>
45 #include <jack/driver.h>
46 #include <jack/shm.h>
47 #include <jack/thread.h>
48 #include <sysdeps/poll.h>
49 #include <sysdeps/ipc.h>
51 #ifdef USE_MLOCK
52 #include <sys/mman.h>
53 #endif /* USE_MLOCK */
55 #ifdef USE_CAPABILITIES
56 /* capgetp and capsetp are linux only extensions, not posix */
57 #undef _POSIX_SOURCE
58 #include <sys/capability.h>
59 #endif
61 #include "clientengine.h"
62 #include "transengine.h"
64 #include "libjack/local.h"
66 typedef struct {
68 jack_port_internal_t *source;
69 jack_port_internal_t *destination;
70 signed int dir; /* -1 = feedback, 0 = self, 1 = forward */
71 jack_client_internal_t *srcclient;
72 jack_client_internal_t *dstclient;
73 } jack_connection_internal_t;
75 typedef struct _jack_driver_info {
76 jack_driver_t *(*initialize)(jack_client_t*, const JSList *);
77 void (*finish);
78 char (*client_name);
79 dlhandle handle;
80 } jack_driver_info_t;
82 jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;
84 static int jack_port_assign_buffer (jack_engine_t *,
85 jack_port_internal_t *);
86 static jack_port_internal_t *jack_get_port_by_name (jack_engine_t *,
87 const char *name);
88 static int jack_rechain_graph (jack_engine_t *engine);
89 static void jack_clear_fifos (jack_engine_t *engine);
90 static int jack_port_do_connect (jack_engine_t *engine,
91 const char *source_port,
92 const char *destination_port);
93 static int jack_port_do_disconnect (jack_engine_t *engine,
94 const char *source_port,
95 const char *destination_port);
96 static int jack_port_do_disconnect_all (jack_engine_t *engine,
97 jack_port_id_t);
98 static int jack_port_do_unregister (jack_engine_t *engine, jack_request_t *);
99 static int jack_port_do_register (jack_engine_t *engine, jack_request_t *, int);
100 static int jack_do_get_port_connections (jack_engine_t *engine,
101 jack_request_t *req, int reply_fd);
102 static int jack_port_disconnect_internal (jack_engine_t *engine,
103 jack_port_internal_t *src,
104 jack_port_internal_t *dst);
105 static int jack_send_connection_notification (jack_engine_t *,
106 jack_client_id_t,
107 jack_port_id_t,
108 jack_port_id_t, int);
109 static int jack_deliver_event (jack_engine_t *, jack_client_internal_t *,
110 jack_event_t *);
111 static void jack_deliver_event_to_all (jack_engine_t *engine,
112 jack_event_t *event);
113 static void jack_notify_all_port_interested_clients (jack_engine_t *engine,
114 jack_client_id_t exclude_src_id,
115 jack_client_id_t exclude_dst_id,
116 jack_port_id_t a,
117 jack_port_id_t b,
118 int connect);
119 static void jack_engine_post_process (jack_engine_t *);
120 static int jack_use_driver (jack_engine_t *engine, jack_driver_t *driver);
121 static int jack_run_cycle (jack_engine_t *engine, jack_nframes_t nframes,
122 float delayed_usecs);
123 static void jack_engine_delay (jack_engine_t *engine,
124 float delayed_usecs);
125 static void jack_engine_driver_exit (jack_engine_t* engine);
126 static int jack_start_freewheeling (jack_engine_t* engine);
127 static int jack_stop_freewheeling (jack_engine_t* engine);
128 static int jack_client_feeds_transitive (jack_client_internal_t *source,
129 jack_client_internal_t *dest);
130 static int jack_client_sort (jack_client_internal_t *a,
131 jack_client_internal_t *b);
132 static void jack_check_acyclic (jack_engine_t* engine);
133 static void jack_compute_all_port_total_latencies (jack_engine_t *engine);
134 static void jack_compute_port_total_latency (jack_engine_t *engine, jack_port_shared_t*);
137 static inline int
138 jack_rolling_interval (jack_time_t period_usecs)
140 return floor ((JACK_ENGINE_ROLLING_INTERVAL * 1000.0f) / period_usecs);
143 void
144 jack_engine_reset_rolling_usecs (jack_engine_t *engine)
146 memset (engine->rolling_client_usecs, 0,
147 sizeof (engine->rolling_client_usecs));
148 engine->rolling_client_usecs_index = 0;
149 engine->rolling_client_usecs_cnt = 0;
151 if (engine->driver) {
152 engine->rolling_interval =
153 jack_rolling_interval (engine->driver->period_usecs);
154 } else {
155 engine->rolling_interval = JACK_ENGINE_ROLLING_INTERVAL;
158 engine->spare_usecs = 0;
161 static inline jack_port_type_info_t *
162 jack_port_type_info (jack_engine_t *engine, jack_port_internal_t *port)
164 /* Returns a pointer to the port type information in the
165 engine's shared control structure.
167 return &engine->control->port_types[port->shared->ptype_id];
170 static inline jack_port_buffer_list_t *
171 jack_port_buffer_list (jack_engine_t *engine, jack_port_internal_t *port)
173 /* Points to the engine's private port buffer list struct. */
174 return &engine->port_buffers[port->shared->ptype_id];
177 static int
178 make_directory (const char *path)
180 struct stat statbuf;
182 if (stat (path, &statbuf)) {
184 if (errno == ENOENT) {
185 int mode;
187 if (getenv ("JACK_PROMISCUOUS_SERVER")) {
188 mode = 0777;
189 } else {
190 mode = 0700;
193 if (mkdir (path, mode) < 0){
194 jack_error ("cannot create %s directory (%s)\n",
195 path, strerror (errno));
196 return -1;
198 } else {
199 jack_error ("cannot stat() %s\n", path);
200 return -1;
203 } else {
205 if (!S_ISDIR (statbuf.st_mode)) {
206 jack_error ("%s already exists, but is not"
207 " a directory!\n", path);
208 return -1;
212 return 0;
215 static int
216 make_socket_subdirectories (const char *server_name)
218 struct stat statbuf;
219 char server_dir[PATH_MAX+1] = "";
221 /* check tmpdir directory */
222 if (stat (jack_tmpdir, &statbuf)) {
223 jack_error ("cannot stat() %s (%s)\n",
224 jack_tmpdir, strerror (errno));
225 return -1;
226 } else {
227 if (!S_ISDIR(statbuf.st_mode)) {
228 jack_error ("%s exists, but is not a directory!\n",
229 jack_tmpdir);
230 return -1;
234 /* create user subdirectory */
235 if (make_directory (jack_user_dir ()) < 0) {
236 return -1;
239 /* create server_name subdirectory */
240 if (make_directory (jack_server_dir (server_name, server_dir)) < 0) {
241 return -1;
244 return 0;
247 static int
248 make_sockets (const char *server_name, int fd[2])
250 struct sockaddr_un addr;
251 int i;
252 char server_dir[PATH_MAX+1] = "";
254 if (make_socket_subdirectories (server_name) < 0) {
255 return -1;
258 /* First, the master server socket */
260 if ((fd[0] = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) {
261 jack_error ("cannot create server socket (%s)",
262 strerror (errno));
263 return -1;
266 addr.sun_family = AF_UNIX;
267 for (i = 0; i < 999; i++) {
268 snprintf (addr.sun_path, sizeof (addr.sun_path) - 1,
269 "%s/jack_%d", jack_server_dir (server_name, server_dir), i);
270 if (access (addr.sun_path, F_OK) != 0) {
271 break;
275 if (i == 999) {
276 jack_error ("all possible server socket names in use!!!");
277 close (fd[0]);
278 return -1;
281 if (bind (fd[0], (struct sockaddr *) &addr, sizeof (addr)) < 0) {
282 jack_error ("cannot bind server to socket (%s)",
283 strerror (errno));
284 close (fd[0]);
285 return -1;
288 if (listen (fd[0], 1) < 0) {
289 jack_error ("cannot enable listen on server socket (%s)",
290 strerror (errno));
291 close (fd[0]);
292 return -1;
295 /* Now the client/server event ack server socket */
297 if ((fd[1] = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) {
298 jack_error ("cannot create event ACK socket (%s)",
299 strerror (errno));
300 close (fd[0]);
301 return -1;
304 addr.sun_family = AF_UNIX;
305 for (i = 0; i < 999; i++) {
306 snprintf (addr.sun_path, sizeof (addr.sun_path) - 1,
307 "%s/jack_ack_%d", jack_server_dir (server_name, server_dir), i);
308 if (access (addr.sun_path, F_OK) != 0) {
309 break;
313 if (i == 999) {
314 jack_error ("all possible server ACK socket names in use!!!");
315 close (fd[0]);
316 close (fd[1]);
317 return -1;
320 if (bind (fd[1], (struct sockaddr *) &addr, sizeof (addr)) < 0) {
321 jack_error ("cannot bind server to socket (%s)",
322 strerror (errno));
323 close (fd[0]);
324 close (fd[1]);
325 return -1;
328 if (listen (fd[1], 1) < 0) {
329 jack_error ("cannot enable listen on server socket (%s)",
330 strerror (errno));
331 close (fd[0]);
332 close (fd[1]);
333 return -1;
336 return 0;
339 void
340 jack_engine_place_port_buffers (jack_engine_t* engine,
341 jack_port_type_id_t ptid,
342 jack_shmsize_t one_buffer,
343 jack_shmsize_t size,
344 unsigned long nports,
345 jack_nframes_t nframes)
347 jack_shmsize_t offset; /* shared memory offset */
348 jack_port_buffer_info_t *bi;
349 jack_port_buffer_list_t* pti = &engine->port_buffers[ptid];
350 jack_port_functions_t *pfuncs = jack_get_port_functions(ptid);
352 pthread_mutex_lock (&pti->lock);
353 offset = 0;
355 if (pti->info) {
357 /* Buffer info array already allocated for this port
358 * type. This must be a resize operation, so
359 * recompute the buffer offsets, but leave the free
360 * list alone.
362 int i;
364 bi = pti->info;
365 while (offset < size) {
366 bi->offset = offset;
367 offset += one_buffer;
368 ++bi;
371 /* update any existing output port offsets */
372 for (i = 0; i < engine->port_max; i++) {
373 jack_port_shared_t *port = &engine->control->ports[i];
374 if (port->in_use &&
375 (port->flags & JackPortIsOutput) &&
376 port->ptype_id == ptid) {
377 bi = engine->internal_ports[i].buffer_info;
378 if (bi) {
379 port->offset = bi->offset;
384 } else {
385 jack_port_type_info_t* port_type = &engine->control->port_types[ptid];
387 /* Allocate an array of buffer info structures for all
388 * the buffers in the segment. Chain them to the free
389 * list in memory address order, offset zero must come
390 * first.
392 bi = pti->info = (jack_port_buffer_info_t *)
393 malloc (nports * sizeof (jack_port_buffer_info_t));
395 while (offset < size) {
396 bi->offset = offset;
397 pti->freelist = jack_slist_append (pti->freelist, bi);
398 offset += one_buffer;
399 ++bi;
402 /* Allocate the first buffer of the port segment
403 * for an empy buffer area.
404 * NOTE: audio buffer is zeroed in its buffer_init function.
406 bi = (jack_port_buffer_info_t *) pti->freelist->data;
407 pti->freelist = jack_slist_remove_link (pti->freelist,
408 pti->freelist);
409 port_type->zero_buffer_offset = bi->offset;
410 if (ptid == JACK_AUDIO_PORT_TYPE)
411 engine->silent_buffer = bi;
413 /* initialize buffers */
415 int i;
416 jack_shm_info_t *shm_info = &engine->port_segment[ptid];
417 char* shm_segment = (char *) jack_shm_addr(shm_info);
419 bi = pti->info;
420 for (i=0; i<nports; ++i, ++bi)
421 pfuncs->buffer_init(shm_segment + bi->offset, one_buffer, nframes);
424 pthread_mutex_unlock (&pti->lock);
427 // JOQ: this should have a return code...
428 static void
429 jack_resize_port_segment (jack_engine_t *engine,
430 jack_port_type_id_t ptid,
431 unsigned long nports)
433 jack_event_t event;
434 jack_shmsize_t one_buffer; /* size of one buffer */
435 jack_shmsize_t size; /* segment size */
436 jack_port_type_info_t* port_type = &engine->control->port_types[ptid];
437 jack_shm_info_t* shm_info = &engine->port_segment[ptid];
439 if (port_type->buffer_scale_factor < 0) {
440 one_buffer = port_type->buffer_size;
441 } else {
442 one_buffer = sizeof (jack_default_audio_sample_t)
443 * port_type->buffer_scale_factor
444 * engine->control->buffer_size;
447 size = nports * one_buffer;
449 if (shm_info->attached_at == 0) {
451 if (jack_shmalloc (size, shm_info)) {
452 jack_error ("cannot create new port segment of %d"
453 " bytes (%s)",
454 size,
455 strerror (errno));
456 return;
459 if (jack_attach_shm (shm_info)) {
460 jack_error ("cannot attach to new port segment "
461 "(%s)", strerror (errno));
462 return;
465 engine->control->port_types[ptid].shm_registry_index =
466 shm_info->index;
468 } else {
470 /* resize existing buffer segment */
471 if (jack_resize_shm (shm_info, size)) {
472 jack_error ("cannot resize port segment to %d bytes,"
473 " (%s)", size,
474 strerror (errno));
475 return;
479 jack_engine_place_port_buffers (engine, ptid, one_buffer, size, nports, engine->control->buffer_size);
481 #ifdef USE_MLOCK
482 if (engine->control->real_time) {
484 /* Although we've called mlockall(CURRENT|FUTURE), the
485 * Linux VM manager still allows newly allocated pages
486 * to fault on first reference. This mlock() ensures
487 * that any new pages are present before restarting
488 * the process cycle. Since memory locks do not
489 * stack, they can still be unlocked with a single
490 * munlockall().
493 int rc = mlock (jack_shm_addr (shm_info), size);
494 if (rc < 0) {
495 jack_error("JACK: unable to mlock() port buffers: "
496 "%s", strerror(errno));
499 #endif /* USE_MLOCK */
501 /* Tell everybody about this segment. */
502 event.type = AttachPortSegment;
503 event.y.ptid = ptid;
504 jack_deliver_event_to_all (engine, &event);
507 /* The driver invokes this callback both initially and whenever its
508 * buffer size changes.
510 static int
511 jack_driver_buffer_size (jack_engine_t *engine, jack_nframes_t nframes)
513 int i;
514 jack_event_t event;
515 JSList *node;
517 VERBOSE (engine, "new buffer size %" PRIu32, nframes);
519 engine->control->buffer_size = nframes;
520 if (engine->driver)
521 engine->rolling_interval =
522 jack_rolling_interval (engine->driver->period_usecs);
524 for (i = 0; i < engine->control->n_port_types; ++i) {
525 jack_resize_port_segment (engine, i, engine->control->port_max);
528 /* update shared client copy of nframes */
529 jack_lock_graph (engine);
530 for (node = engine->clients; node; node = jack_slist_next (node)) {
531 jack_client_internal_t *client = node->data;
532 client->control->nframes = nframes;
534 jack_unlock_graph (engine);
536 event.type = BufferSizeChange;
537 jack_deliver_event_to_all (engine, &event);
539 return 0;
542 /* handle client SetBufferSize request */
544 jack_set_buffer_size_request (jack_engine_t *engine, jack_nframes_t nframes)
546 /* precondition: caller holds the request_lock */
547 int rc;
548 jack_driver_t* driver = engine->driver;
550 if (driver == NULL)
551 return ENXIO; /* no such device */
553 if (!jack_power_of_two(nframes)) {
554 jack_error("buffer size %" PRIu32 " not a power of 2",
555 nframes);
556 return EINVAL;
559 rc = driver->bufsize(driver, nframes);
560 if (rc != 0)
561 jack_error("driver does not support %" PRIu32
562 "-frame buffers", nframes);
564 return rc;
568 static JSList *
569 jack_process_internal(jack_engine_t *engine, JSList *node,
570 jack_nframes_t nframes)
572 jack_client_internal_t *client;
573 jack_client_control_t *ctl;
575 client = (jack_client_internal_t *) node->data;
576 ctl = client->control;
578 /* internal client */
580 DEBUG ("invoking an internal client's callbacks");
581 ctl->state = Running;
582 engine->current_client = client;
584 /* XXX how to time out an internal client? */
586 if (ctl->sync_cb_cbset)
587 jack_call_sync_client (client->private_client);
589 if (ctl->process_cbset)
590 if (client->private_client->process (nframes, client->private_client->process_arg)) {
591 jack_error ("internal client %s failed", ctl->name);
592 engine->process_errors++;
595 if (ctl->timebase_cb_cbset)
596 jack_call_timebase_master (client->private_client);
598 ctl->state = Finished;
600 if (engine->process_errors)
601 return NULL; /* will stop the loop */
602 else
603 return jack_slist_next (node);
606 #ifdef __linux
608 /* Linux kernels somewhere between 2.6.18 and 2.6.24 had a bug
609 in poll(2) that led poll to return early. To fix it, we need
610 to know that that jack_get_microseconds() is monotonic.
613 #ifdef HAVE_CLOCK_GETTIME
614 static const int system_clock_monotonic = 1;
615 #else
616 static const int system_clock_monotonic = 0;
617 #endif
619 static int
620 linux_poll_bug_encountered (jack_engine_t* engine, jack_time_t then, jack_time_t *required)
622 if (engine->control->clock_source != JACK_TIMER_SYSTEM_CLOCK || system_clock_monotonic) {
623 jack_time_t now = jack_get_microseconds ();
625 if ((now - then) < *required) {
628 So, adjust poll timeout to account for time already spent waiting.
631 VERBOSE (engine, "FALSE WAKEUP (%lldusecs vs. %lld usec)", (now - then), *required);
632 *required -= (now - then);
634 /* allow 0.25msec slop */
635 return 1;
638 return 0;
640 #endif
642 #ifdef JACK_USE_MACH_THREADS
643 static JSList *
644 jack_process_external(jack_engine_t *engine, JSList *node)
646 jack_client_internal_t * client = (jack_client_internal_t *) node->data;
647 jack_client_control_t *ctl;
649 client = (jack_client_internal_t *) node->data;
650 ctl = client->control;
652 engine->current_client = client;
654 // a race exists if we do this after the write(2)
655 ctl->state = Triggered;
656 ctl->signalled_at = jack_get_microseconds();
658 if (jack_client_resume(client) < 0) {
659 jack_error("Client will be removed\n");
660 ctl->state = Finished;
663 return jack_slist_next (node);
665 #else /* !JACK_USE_MACH_THREADS */
666 static JSList *
667 jack_process_external(jack_engine_t *engine, JSList *node)
669 int status = 0;
670 char c = 0;
671 struct pollfd pfd[1];
672 int poll_timeout;
673 jack_time_t poll_timeout_usecs;
674 jack_client_internal_t *client;
675 jack_client_control_t *ctl;
676 jack_time_t now, then;
677 int pollret;
679 client = (jack_client_internal_t *) node->data;
681 ctl = client->control;
683 /* external subgraph */
685 /* a race exists if we do this after the write(2) */
686 ctl->state = Triggered;
688 ctl->signalled_at = jack_get_microseconds();
690 engine->current_client = client;
692 DEBUG ("calling process() on an external subgraph, fd==%d",
693 client->subgraph_start_fd);
695 if (write (client->subgraph_start_fd, &c, sizeof (c)) != sizeof (c)) {
696 jack_error ("cannot initiate graph processing (%s)",
697 strerror (errno));
698 engine->process_errors++;
699 jack_lock_problems (engine);
700 engine->problems++;
701 jack_unlock_problems (engine);
702 return NULL; /* will stop the loop */
705 then = jack_get_microseconds ();
707 if (engine->freewheeling) {
708 poll_timeout_usecs = 10000000; /* 10 seconds */
709 } else {
710 poll_timeout_usecs = (engine->client_timeout_msecs > 0 ?
711 engine->client_timeout_msecs * 1000 :
712 engine->driver->period_usecs);
715 again:
716 poll_timeout = 1 + poll_timeout_usecs / 1000;
717 pfd[0].fd = client->subgraph_wait_fd;
718 pfd[0].events = POLLERR|POLLIN|POLLHUP|POLLNVAL;
720 DEBUG ("waiting on fd==%d for process() subgraph to finish (timeout = %d, period_usecs = %d)",
721 client->subgraph_wait_fd, poll_timeout, engine->driver->period_usecs);
723 if ((pollret = poll (pfd, 1, poll_timeout)) < 0) {
724 jack_error ("poll on subgraph processing failed (%s)",
725 strerror (errno));
726 status = -1;
729 DEBUG ("\n\n\n\n\n back from subgraph poll, revents = 0x%x\n\n\n", pfd[0].revents);
731 if (pfd[0].revents & ~POLLIN) {
732 jack_error ("subgraph starting at %s lost client",
733 client->control->name);
734 status = -2;
737 if (pfd[0].revents & POLLIN) {
739 status = 0;
741 } else if (status == 0) {
743 /* no events, no errors, we woke up because poll()
744 decided that time was up ...
747 #ifdef __linux
748 if (linux_poll_bug_encountered (engine, then, &poll_timeout_usecs)) {
749 goto again;
752 if (poll_timeout_usecs < 200) {
753 VERBOSE (engine, "FALSE WAKEUP skipped, remaining = %lld usec", poll_timeout_usecs);
754 } else {
755 #endif
757 jack_error ("subgraph starting at %s timed out "
758 "(subgraph_wait_fd=%d, status = %d, state = %s, pollret = %d revents = 0x%x)",
759 client->control->name,
760 client->subgraph_wait_fd, status,
761 jack_client_state_name (client),
762 pollret, pfd[0].revents);
763 status = 1;
764 #ifdef __linux
766 #endif
769 now = jack_get_microseconds ();
771 if (status != 0) {
772 VERBOSE (engine, "at %" PRIu64
773 " waiting on %d for %" PRIu64
774 " usecs, status = %d sig = %" PRIu64
775 " awa = %" PRIu64 " fin = %" PRIu64
776 " dur=%" PRIu64,
777 now,
778 client->subgraph_wait_fd,
779 now - then,
780 status,
781 ctl->signalled_at,
782 ctl->awake_at,
783 ctl->finished_at,
784 ctl->finished_at? (ctl->finished_at -
785 ctl->signalled_at): 0);
787 jack_check_clients (engine, 1);
789 engine->process_errors++;
790 return NULL; /* will stop the loop */
792 } else {
794 DEBUG ("reading byte from subgraph_wait_fd==%d",
795 client->subgraph_wait_fd);
797 if (read (client->subgraph_wait_fd, &c, sizeof(c))
798 != sizeof (c)) {
799 jack_error ("pp: cannot clean up byte from graph wait "
800 "fd (%s)", strerror (errno));
801 client->error++;
802 return NULL; /* will stop the loop */
806 /* Move to next internal client (or end of client list) */
807 while (node) {
808 if (jack_client_is_internal ((jack_client_internal_t *)
809 node->data)) {
810 break;
812 node = jack_slist_next (node);
815 return node;
818 #endif /* JACK_USE_MACH_THREADS */
820 static int
821 jack_engine_process (jack_engine_t *engine, jack_nframes_t nframes)
823 /* precondition: caller has graph_lock */
824 jack_client_internal_t *client;
825 JSList *node;
827 engine->process_errors = 0;
828 engine->watchdog_check = 1;
830 for (node = engine->clients; node; node = jack_slist_next (node)) {
831 jack_client_control_t *ctl =
832 ((jack_client_internal_t *) node->data)->control;
833 ctl->state = NotTriggered;
834 ctl->nframes = nframes;
835 ctl->timed_out = 0;
836 ctl->awake_at = 0;
837 ctl->finished_at = 0;
840 for (node = engine->clients; engine->process_errors == 0 && node; ) {
842 client = (jack_client_internal_t *) node->data;
844 DEBUG ("considering client %s for processing",
845 client->control->name);
847 if (!client->control->active || client->control->dead) {
848 node = jack_slist_next (node);
849 } else if (jack_client_is_internal (client)) {
850 node = jack_process_internal (engine, node, nframes);
851 } else {
852 node = jack_process_external (engine, node);
856 return engine->process_errors > 0;
859 static void
860 jack_calc_cpu_load(jack_engine_t *engine)
862 jack_time_t cycle_end = jack_get_microseconds ();
864 /* store the execution time for later averaging */
866 engine->rolling_client_usecs[engine->rolling_client_usecs_index++] =
867 cycle_end - engine->control->current_time.usecs;
869 //jack_info ("cycle_end - engine->control->current_time.usecs %ld",
870 // (long) (cycle_end - engine->control->current_time.usecs));
872 if (engine->rolling_client_usecs_index >= JACK_ENGINE_ROLLING_COUNT) {
873 engine->rolling_client_usecs_index = 0;
876 /* every so often, recompute the current maximum use over the
877 last JACK_ENGINE_ROLLING_COUNT client iterations.
880 if (++engine->rolling_client_usecs_cnt
881 % engine->rolling_interval == 0) {
882 float max_usecs = 0.0f;
883 int i;
885 for (i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) {
886 if (engine->rolling_client_usecs[i] > max_usecs) {
887 max_usecs = engine->rolling_client_usecs[i];
891 if (max_usecs > engine->max_usecs) {
892 engine->max_usecs = max_usecs;
895 if (max_usecs < engine->driver->period_usecs) {
896 engine->spare_usecs =
897 engine->driver->period_usecs - max_usecs;
898 } else {
899 engine->spare_usecs = 0;
902 engine->control->cpu_load =
903 (1.0f - (engine->spare_usecs /
904 engine->driver->period_usecs)) * 50.0f
905 + (engine->control->cpu_load * 0.5f);
907 VERBOSE (engine, "load = %.4f max usecs: %.3f, "
908 "spare = %.3f", engine->control->cpu_load,
909 max_usecs, engine->spare_usecs);
914 static void
915 jack_engine_post_process (jack_engine_t *engine)
917 /* precondition: caller holds the graph lock. */
919 jack_transport_cycle_end (engine);
920 jack_calc_cpu_load (engine);
921 jack_check_clients (engine, 0);
924 #ifdef JACK_USE_MACH_THREADS
926 static int
927 jack_start_watchdog (jack_engine_t *engine)
929 /* Stephane Letz : letz@grame.fr Watch dog thread is
930 * not needed on MacOSX since CoreAudio drivers
931 * already contains a similar mechanism.
933 return 0;
936 #else
938 static void *
939 jack_watchdog_thread (void *arg)
941 jack_engine_t *engine = (jack_engine_t *) arg;
942 struct timespec timo;
944 timo.tv_sec = JACKD_WATCHDOG_TIMEOUT / 1000;
945 timo.tv_nsec = (JACKD_WATCHDOG_TIMEOUT - (timo.tv_sec * 1000)) * 1000;
946 engine->watchdog_check = 0;
948 while (1) {
949 nanosleep (&timo, NULL);
950 if (!engine->freewheeling && engine->watchdog_check == 0) {
952 jack_error ("jackd watchdog: timeout - killing jackd");
954 /* Kill the current client (guilt by association). */
955 if (engine->current_client) {
956 kill (engine->current_client->
957 control->pid, SIGKILL);
960 /* kill our process group, try to get a dump */
961 kill (-getpgrp(), SIGABRT);
962 /*NOTREACHED*/
963 exit (1);
965 engine->watchdog_check = 0;
969 static int
970 jack_start_watchdog (jack_engine_t *engine)
972 int watchdog_priority = engine->rtpriority + 10;
973 #ifndef __OpenBSD__
974 int max_priority = sched_get_priority_max (SCHED_FIFO);
975 #else
976 int max_priority = -1;
977 #endif
979 if ((max_priority != -1) &&
980 (max_priority < watchdog_priority))
981 watchdog_priority = max_priority;
983 if (jack_client_create_thread (NULL, &engine->watchdog_thread, watchdog_priority,
984 TRUE, jack_watchdog_thread, engine)) {
985 jack_error ("cannot start watchdog thread");
986 return -1;
989 return 0;
991 #endif /* !JACK_USE_MACH_THREADS */
994 static jack_driver_info_t *
995 jack_load_driver (jack_engine_t *engine, jack_driver_desc_t * driver_desc)
997 const char *errstr;
998 jack_driver_info_t *info;
1000 info = (jack_driver_info_t *) calloc (1, sizeof (*info));
1002 info->handle = dlopen (driver_desc->file, RTLD_NOW|RTLD_GLOBAL);
1004 if (info->handle == NULL) {
1005 if ((errstr = dlerror ()) != 0) {
1006 jack_error ("can't load \"%s\": %s", driver_desc->file,
1007 errstr);
1008 } else {
1009 jack_error ("bizarre error loading driver shared "
1010 "object %s", driver_desc->file);
1012 goto fail;
1015 info->initialize = dlsym (info->handle, "driver_initialize");
1017 if ((errstr = dlerror ()) != 0) {
1018 jack_error ("no initialize function in shared object %s\n",
1019 driver_desc->file);
1020 goto fail;
1023 info->finish = dlsym (info->handle, "driver_finish");
1025 if ((errstr = dlerror ()) != 0) {
1026 jack_error ("no finish function in in shared driver object %s",
1027 driver_desc->file);
1028 goto fail;
1031 info->client_name = (char *) dlsym (info->handle, "driver_client_name");
1033 if ((errstr = dlerror ()) != 0) {
1034 jack_error ("no client name in in shared driver object %s",
1035 driver_desc->file);
1036 goto fail;
1039 return info;
1041 fail:
1042 if (info->handle) {
1043 dlclose (info->handle);
1045 free (info);
1046 return NULL;
1050 void
1051 jack_driver_unload (jack_driver_t *driver)
1053 void* handle = driver->handle;
1054 driver->finish (driver);
1055 dlclose (handle);
1059 jack_engine_load_driver (jack_engine_t *engine,
1060 jack_driver_desc_t * driver_desc,
1061 JSList * driver_params)
1063 jack_client_internal_t *client;
1064 jack_driver_t *driver;
1065 jack_driver_info_t *info;
1067 if ((info = jack_load_driver (engine, driver_desc)) == NULL) {
1068 return -1;
1071 if ((client = jack_create_driver_client (engine, info->client_name)
1072 ) == NULL) {
1073 return -1;
1076 if ((driver = info->initialize (client->private_client,
1077 driver_params)) == NULL) {
1078 free (info);
1079 return -1;
1082 driver->handle = info->handle;
1083 driver->finish = info->finish;
1084 driver->internal_client = client;
1085 free (info);
1087 if (jack_use_driver (engine, driver) < 0) {
1088 jack_client_delete (engine, client);
1089 return -1;
1092 engine->driver_desc = driver_desc;
1093 engine->driver_params = driver_params;
1095 if (engine->control->real_time) {
1096 if (jack_start_watchdog (engine)) {
1097 return -1;
1099 engine->watchdog_check = 1;
1101 return 0;
1104 #ifdef USE_CAPABILITIES
1106 static int check_capabilities (jack_engine_t *engine)
1108 cap_t caps = cap_init();
1109 cap_flag_value_t cap;
1110 pid_t pid;
1111 int have_all_caps = 1;
1113 if (caps == NULL) {
1114 VERBOSE (engine, "check: could not allocate capability"
1115 " working storage");
1116 return 0;
1118 pid = getpid ();
1119 cap_clear (caps);
1120 if (capgetp (pid, caps)) {
1121 VERBOSE (engine, "check: could not get capabilities "
1122 "for process %d", pid);
1123 return 0;
1125 /* check that we are able to give capabilites to other processes */
1126 cap_get_flag(caps, CAP_SETPCAP, CAP_EFFECTIVE, &cap);
1127 if (cap == CAP_CLEAR) {
1128 have_all_caps = 0;
1129 goto done;
1131 /* check that we have the capabilities we want to transfer */
1132 cap_get_flag(caps, CAP_SYS_NICE, CAP_EFFECTIVE, &cap);
1133 if (cap == CAP_CLEAR) {
1134 have_all_caps = 0;
1135 goto done;
1137 cap_get_flag(caps, CAP_SYS_RESOURCE, CAP_EFFECTIVE, &cap);
1138 if (cap == CAP_CLEAR) {
1139 have_all_caps = 0;
1140 goto done;
1142 cap_get_flag(caps, CAP_IPC_LOCK, CAP_EFFECTIVE, &cap);
1143 if (cap == CAP_CLEAR) {
1144 have_all_caps = 0;
1145 goto done;
1147 done:
1148 cap_free (caps);
1149 return have_all_caps;
1153 static int give_capabilities (jack_engine_t *engine, pid_t pid)
1155 cap_t caps = cap_init();
1156 const unsigned caps_size = 3;
1157 cap_value_t cap_list[] = {CAP_SYS_NICE, CAP_SYS_RESOURCE, CAP_IPC_LOCK};
1159 if (caps == NULL) {
1160 VERBOSE (engine, "give: could not allocate capability"
1161 " working storage");
1162 return -1;
1164 cap_clear(caps);
1165 if (capgetp (pid, caps)) {
1166 VERBOSE (engine, "give: could not get current "
1167 "capabilities for process %d", pid);
1168 cap_clear(caps);
1170 cap_set_flag(caps, CAP_EFFECTIVE, caps_size, cap_list , CAP_SET);
1171 cap_set_flag(caps, CAP_INHERITABLE, caps_size, cap_list , CAP_SET);
1172 cap_set_flag(caps, CAP_PERMITTED, caps_size, cap_list , CAP_SET);
1173 if (capsetp (pid, caps)) {
1174 cap_free (caps);
1175 return -1;
1177 cap_free (caps);
1178 return 0;
1181 static int
1182 jack_set_client_capabilities (jack_engine_t *engine, pid_t cap_pid)
1184 int ret = -1;
1186 /* before sending this request the client has
1187 already checked that the engine has
1188 realtime capabilities, that it is running
1189 realtime and that the pid is defined
1192 if ((ret = give_capabilities (engine, cap_pid)) != 0) {
1193 jack_error ("could not give capabilities to "
1194 "process %d",
1195 cap_pid);
1196 } else {
1197 VERBOSE (engine, "gave capabilities to"
1198 " process %d",
1199 cap_pid);
1202 return ret;
1205 #endif /* USE_CAPABILITIES */
1207 /* perform internal or external client request
1209 * reply_fd is NULL for internal requests
1211 static void
1212 do_request (jack_engine_t *engine, jack_request_t *req, int *reply_fd)
1214 /* The request_lock serializes internal requests (from any
1215 * thread in the server) with external requests (always from "the"
1216 * server thread).
1218 pthread_mutex_lock (&engine->request_lock);
1220 DEBUG ("got a request of type %d", req->type);
1222 switch (req->type) {
1223 case RegisterPort:
1224 req->status = jack_port_do_register (engine, req, reply_fd ? FALSE : TRUE);
1225 break;
1227 case UnRegisterPort:
1228 req->status = jack_port_do_unregister (engine, req);
1229 break;
1231 case ConnectPorts:
1232 req->status = jack_port_do_connect
1233 (engine, req->x.connect.source_port,
1234 req->x.connect.destination_port);
1235 break;
1237 case DisconnectPort:
1238 req->status = jack_port_do_disconnect_all
1239 (engine, req->x.port_info.port_id);
1240 break;
1242 case DisconnectPorts:
1243 req->status = jack_port_do_disconnect
1244 (engine, req->x.connect.source_port,
1245 req->x.connect.destination_port);
1246 break;
1248 case ActivateClient:
1249 req->status = jack_client_activate (engine, req->x.client_id);
1250 break;
1252 case DeactivateClient:
1253 req->status = jack_client_deactivate (engine, req->x.client_id);
1254 break;
1256 case SetTimeBaseClient:
1257 req->status = jack_timebase_set (engine,
1258 req->x.timebase.client_id,
1259 req->x.timebase.conditional);
1260 break;
1262 case ResetTimeBaseClient:
1263 req->status = jack_timebase_reset (engine, req->x.client_id);
1264 break;
1266 case SetSyncClient:
1267 req->status =
1268 jack_transport_client_set_sync (engine,
1269 req->x.client_id);
1270 break;
1272 case ResetSyncClient:
1273 req->status =
1274 jack_transport_client_reset_sync (engine,
1275 req->x.client_id);
1276 break;
1278 case SetSyncTimeout:
1279 req->status = jack_transport_set_sync_timeout (engine,
1280 req->x.timeout);
1281 break;
1283 #ifdef USE_CAPABILITIES
1284 case SetClientCapabilities:
1285 req->status = jack_set_client_capabilities (engine,
1286 req->x.cap_pid);
1287 break;
1288 #endif /* USE_CAPABILITIES */
1290 case GetPortConnections:
1291 case GetPortNConnections:
1292 //JOQ bug: reply_fd may be NULL if internal request
1293 if ((req->status =
1294 jack_do_get_port_connections (engine, req, *reply_fd))
1295 == 0) {
1296 /* we have already replied, don't do it again */
1297 *reply_fd = -1;
1299 break;
1301 case FreeWheel:
1302 req->status = jack_start_freewheeling (engine);
1303 break;
1305 case StopFreeWheel:
1306 req->status = jack_stop_freewheeling (engine);
1307 break;
1309 case SetBufferSize:
1310 req->status = jack_set_buffer_size_request (engine,
1311 req->x.nframes);
1312 break;
1314 case IntClientHandle:
1315 jack_intclient_handle_request (engine, req);
1316 break;
1318 case IntClientLoad:
1319 jack_intclient_load_request (engine, req);
1320 break;
1322 case IntClientName:
1323 jack_intclient_name_request (engine, req);
1324 break;
1326 case IntClientUnload:
1327 jack_intclient_unload_request (engine, req);
1328 break;
1330 case RecomputeTotalLatencies:
1331 jack_lock_graph (engine);
1332 jack_compute_all_port_total_latencies (engine);
1333 jack_unlock_graph (engine);
1334 req->status = 0;
1335 break;
1337 case RecomputeTotalLatency:
1338 jack_lock_graph (engine);
1339 jack_compute_port_total_latency (engine, &engine->control->ports[req->x.port_info.port_id]);
1340 jack_unlock_graph (engine);
1341 req->status = 0;
1342 break;
1344 default:
1345 /* some requests are handled entirely on the client
1346 * side, by adjusting the shared memory area(s) */
1347 break;
1350 pthread_mutex_unlock (&engine->request_lock);
1352 DEBUG ("status of request: %d", req->status);
1356 internal_client_request (void* ptr, jack_request_t *request)
1358 do_request ((jack_engine_t*) ptr, request, NULL);
1359 return request->status;
1362 static int
1363 handle_external_client_request (jack_engine_t *engine, int fd)
1365 /* CALLER holds read lock on graph */
1367 jack_request_t req;
1368 jack_client_internal_t *client = 0;
1369 int reply_fd;
1370 JSList *node;
1371 ssize_t r;
1373 for (node = engine->clients; node; node = jack_slist_next (node)) {
1374 if (((jack_client_internal_t *) node->data)->request_fd == fd) {
1375 client = (jack_client_internal_t *) node->data;
1376 break;
1380 if (client == NULL) {
1381 jack_error ("client input on unknown fd %d!", fd);
1382 return -1;
1385 if ((r = read (client->request_fd, &req, sizeof (req)))
1386 < (ssize_t) sizeof (req)) {
1387 if (r == 0) {
1388 #ifdef JACK_USE_MACH_THREADS
1389 /* poll is implemented using
1390 select (see the macosx/fakepoll
1391 code). When the socket is closed
1392 select does not return any error,
1393 POLLIN is true and the next read
1394 will return 0 bytes. This
1395 behaviour is diffrent from the
1396 Linux poll behaviour. Thus we use
1397 this condition as a socket error
1398 and remove the client.
1400 jack_mark_client_socket_error (engine, fd);
1401 #endif /* JACK_USE_MACH_THREADS */
1402 return 1;
1403 } else {
1404 jack_error ("cannot read request from client (%d/%d/%s)",
1405 r, sizeof(req), strerror (errno));
1406 // XXX: shouldnt we mark this client as error now ?
1408 return -1;
1412 reply_fd = client->request_fd;
1414 jack_unlock_graph (engine);
1415 do_request (engine, &req, &reply_fd);
1416 jack_lock_graph (engine);
1418 if (reply_fd >= 0) {
1419 DEBUG ("replying to client");
1420 if (write (reply_fd, &req, sizeof (req))
1421 < (ssize_t) sizeof (req)) {
1422 jack_error ("cannot write request result to client");
1423 return -1;
1425 } else {
1426 DEBUG ("*not* replying to client");
1429 return 0;
1432 static int
1433 handle_client_ack_connection (jack_engine_t *engine, int client_fd)
1435 jack_client_internal_t *client;
1436 jack_client_connect_ack_request_t req;
1437 jack_client_connect_ack_result_t res;
1439 if (read (client_fd, &req, sizeof (req)) != sizeof (req)) {
1440 jack_error ("cannot read ACK connection request from client");
1441 return -1;
1444 if ((client = jack_client_internal_by_id (engine, req.client_id))
1445 == NULL) {
1446 jack_error ("unknown client ID in ACK connection request");
1447 return -1;
1450 client->event_fd = client_fd;
1451 VERBOSE (engine, "new client %s using %d for events", client->control->name,
1452 client->event_fd);
1454 res.status = 0;
1456 if (write (client->event_fd, &res, sizeof (res)) != sizeof (res)) {
1457 jack_error ("cannot write ACK connection response to client");
1458 return -1;
1461 return 0;
1465 static void *
1466 jack_server_thread (void *arg)
1469 jack_engine_t *engine = (jack_engine_t *) arg;
1470 struct sockaddr_un client_addr;
1471 socklen_t client_addrlen;
1472 int problemsProblemsPROBLEMS = 0;
1473 int client_socket;
1474 int done = 0;
1475 int i;
1476 const int fixed_fd_cnt = 3;
1478 while (!done) {
1479 JSList* node;
1480 int clients;
1482 jack_rdlock_graph (engine);
1484 clients = jack_slist_length (engine->clients);
1486 if (engine->pfd_size < fixed_fd_cnt + clients) {
1487 if (engine->pfd) {
1488 free (engine->pfd);
1490 engine->pfd = (struct pollfd *) malloc (sizeof(struct pollfd) * (fixed_fd_cnt + clients));
1493 engine->pfd[0].fd = engine->fds[0];
1494 engine->pfd[0].events = POLLIN|POLLERR;
1495 engine->pfd[1].fd = engine->fds[1];
1496 engine->pfd[1].events = POLLIN|POLLERR;
1497 engine->pfd[2].fd = engine->cleanup_fifo[0];
1498 engine->pfd[2].events = POLLIN|POLLERR;
1499 engine->pfd_max = fixed_fd_cnt;
1501 for (node = engine->clients; node; node = node->next) {
1503 jack_client_internal_t* client = (jack_client_internal_t*)(node->data);
1505 if (client->request_fd < 0 || client->control->dead || client->error >= JACK_ERROR_WITH_SOCKETS) {
1506 continue;
1508 engine->pfd[engine->pfd_max].fd = client->request_fd;
1509 engine->pfd[engine->pfd_max].events = POLLIN|POLLPRI|POLLERR|POLLHUP|POLLNVAL;
1510 engine->pfd_max++;
1513 jack_unlock_graph (engine);
1515 VERBOSE (engine, "start poll on %d fd's", engine->pfd_max);
1517 /* go to sleep for a long, long time, or until a request
1518 arrives, or until a communication channel is broken
1521 if (poll (engine->pfd, engine->pfd_max, -1) < 0) {
1522 if (errno == EINTR) {
1523 continue;
1525 jack_error ("poll failed (%s)", strerror (errno));
1526 break;
1529 VERBOSE(engine, "server thread back from poll");
1531 /* Stephane Letz: letz@grame.fr : has to be added
1532 * otherwise pthread_cancel() does not work on MacOSX */
1533 pthread_testcancel();
1536 /* empty cleanup FIFO if necessary */
1538 if (engine->pfd[2].revents & ~POLLIN) {
1539 /* time to die */
1540 break;
1543 if (engine->pfd[2].revents & POLLIN) {
1544 char c;
1545 while (read (engine->cleanup_fifo[0], &c, 1) == 1);
1548 /* check each client socket before handling other request*/
1550 jack_rdlock_graph (engine);
1552 for (i = fixed_fd_cnt; i < engine->pfd_max; i++) {
1554 if (engine->pfd[i].fd < 0) {
1555 continue;
1558 if (engine->pfd[i].revents & ~POLLIN) {
1560 jack_mark_client_socket_error (engine, engine->pfd[i].fd);
1561 jack_lock_problems (engine);
1562 engine->problems++;
1563 jack_unlock_problems (engine);
1565 } else if (engine->pfd[i].revents & POLLIN) {
1567 if (handle_external_client_request (engine, engine->pfd[i].fd)) {
1568 jack_error ("could not handle external"
1569 " client request");
1570 jack_lock_problems (engine);
1571 engine->problems++;
1572 jack_unlock_problems (engine);
1577 problemsProblemsPROBLEMS = engine->problems;
1579 jack_unlock_graph (engine);
1581 /* need to take write lock since we may/will rip out some clients,
1582 and reset engine->problems
1585 if (problemsProblemsPROBLEMS) {
1586 jack_lock_graph (engine);
1587 jack_lock_problems (engine);
1588 VERBOSE (engine, "we have problem clients");
1589 jack_remove_clients (engine);
1590 engine->problems = 0;
1591 jack_unlock_problems (engine);
1592 jack_unlock_graph (engine);
1596 /* check the master server socket */
1598 if (engine->pfd[0].revents & POLLERR) {
1599 jack_error ("error on server socket");
1600 break;
1603 if (engine->control->engine_ok && engine->pfd[0].revents & POLLIN) {
1604 DEBUG ("pfd[0].revents & POLLIN");
1606 memset (&client_addr, 0, sizeof (client_addr));
1607 client_addrlen = sizeof (client_addr);
1609 if ((client_socket =
1610 accept (engine->fds[0],
1611 (struct sockaddr *) &client_addr,
1612 &client_addrlen)) < 0) {
1613 jack_error ("cannot accept new connection (%s)",
1614 strerror (errno));
1615 } else if (jack_client_create (engine, client_socket) < 0) {
1616 jack_error ("cannot complete client "
1617 "connection process");
1618 close (client_socket);
1622 /* check the ACK server socket */
1624 if (engine->pfd[1].revents & POLLERR) {
1625 jack_error ("error on server ACK socket");
1626 break;
1629 if (engine->control->engine_ok && engine->pfd[1].revents & POLLIN) {
1630 DEBUG ("pfd[1].revents & POLLIN");
1632 memset (&client_addr, 0, sizeof (client_addr));
1633 client_addrlen = sizeof (client_addr);
1635 if ((client_socket =
1636 accept (engine->fds[1],
1637 (struct sockaddr *) &client_addr,
1638 &client_addrlen)) < 0) {
1639 jack_error ("cannot accept new ACK connection"
1640 " (%s)", strerror (errno));
1641 } else if (handle_client_ack_connection
1642 (engine, client_socket)) {
1643 jack_error ("cannot complete client ACK "
1644 "connection process");
1645 close (client_socket);
1650 return 0;
1653 jack_engine_t *
1654 jack_engine_new (int realtime, int rtpriority, int do_mlock, int do_unlock,
1655 const char *server_name, int temporary, int verbose,
1656 int client_timeout, unsigned int port_max, pid_t wait_pid,
1657 jack_nframes_t frame_time_offset, int nozombies, JSList *drivers)
1659 jack_engine_t *engine;
1660 unsigned int i;
1661 char server_dir[PATH_MAX+1] = "";
1663 #ifdef USE_CAPABILITIES
1664 uid_t uid = getuid ();
1665 uid_t euid = geteuid ();
1666 #endif /* USE_CAPABILITIES */
1668 /* before we start allocating resources, make sure that if realtime was requested that we can
1669 actually do it.
1672 if (realtime) {
1673 if (jack_acquire_real_time_scheduling (pthread_self(), 10) != 0) {
1674 /* can't run realtime - time to bomb */
1675 return NULL;
1678 jack_drop_real_time_scheduling (pthread_self());
1680 #ifdef USE_MLOCK
1682 if (do_mlock && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) {
1683 jack_error ("cannot lock down memory for jackd (%s)",
1684 strerror (errno));
1685 #ifdef ENSURE_MLOCK
1686 return NULL;
1687 #endif /* ENSURE_MLOCK */
1689 #endif /* USE_MLOCK */
1692 /* start a thread to display messages from realtime threads */
1693 jack_messagebuffer_init();
1695 jack_init_time ();
1697 /* allocate the engine, zero the structure to ease debugging */
1698 engine = (jack_engine_t *) calloc (1, sizeof (jack_engine_t));
1700 engine->drivers = drivers;
1701 engine->driver = NULL;
1702 engine->driver_desc = NULL;
1703 engine->driver_params = NULL;
1705 engine->set_sample_rate = jack_set_sample_rate;
1706 engine->set_buffer_size = jack_driver_buffer_size;
1707 engine->run_cycle = jack_run_cycle;
1708 engine->delay = jack_engine_delay;
1709 engine->driver_exit = jack_engine_driver_exit;
1710 engine->transport_cycle_start = jack_transport_cycle_start;
1711 engine->client_timeout_msecs = client_timeout;
1712 engine->problems = 0;
1714 engine->next_client_id = 1; /* 0 is a NULL client ID */
1715 engine->port_max = port_max;
1716 engine->server_thread = 0;
1717 engine->watchdog_thread = 0;
1718 engine->rtpriority = rtpriority;
1719 engine->silent_buffer = 0;
1720 engine->verbose = verbose;
1721 engine->server_name = server_name;
1722 engine->temporary = temporary;
1723 engine->freewheeling = 0;
1724 engine->feedbackcount = 0;
1725 engine->wait_pid = wait_pid;
1726 engine->nozombies = nozombies;
1727 engine->removing_clients = 0;
1729 engine->audio_out_cnt = 0;
1730 engine->audio_in_cnt = 0;
1731 engine->midi_out_cnt = 0;
1732 engine->midi_in_cnt = 0;
1734 jack_engine_reset_rolling_usecs (engine);
1735 engine->max_usecs = 0.0f;
1737 pthread_rwlock_init (&engine->client_lock, 0);
1738 pthread_mutex_init (&engine->port_lock, 0);
1739 pthread_mutex_init (&engine->request_lock, 0);
1740 pthread_mutex_init (&engine->problem_lock, 0);
1742 engine->clients = 0;
1744 engine->pfd_size = 0;
1745 engine->pfd_max = 0;
1746 engine->pfd = 0;
1748 engine->fifo_size = 16;
1749 engine->fifo = (int *) malloc (sizeof (int) * engine->fifo_size);
1750 for (i = 0; i < engine->fifo_size; i++) {
1751 engine->fifo[i] = -1;
1754 if (pipe (engine->cleanup_fifo)) {
1755 jack_error ("cannot create cleanup FIFOs (%s)", strerror (errno));
1756 return NULL;
1759 if (fcntl (engine->cleanup_fifo[0], F_SETFL, O_NONBLOCK)) {
1760 jack_error ("cannot set O_NONBLOCK on cleanup read FIFO (%s)", strerror (errno));
1761 return NULL;
1764 if (fcntl (engine->cleanup_fifo[1], F_SETFL, O_NONBLOCK)) {
1765 jack_error ("cannot set O_NONBLOCK on cleanup write FIFO (%s)", strerror (errno));
1766 return NULL;
1769 engine->external_client_cnt = 0;
1771 srandom (time ((time_t *) 0));
1773 if (jack_shmalloc (sizeof (jack_control_t)
1774 + ((sizeof (jack_port_shared_t) * engine->port_max)),
1775 &engine->control_shm)) {
1776 jack_error ("cannot create engine control shared memory "
1777 "segment (%s)", strerror (errno));
1778 return NULL;
1781 if (jack_attach_shm (&engine->control_shm)) {
1782 jack_error ("cannot attach to engine control shared memory"
1783 " (%s)", strerror (errno));
1784 jack_destroy_shm (&engine->control_shm);
1785 return NULL;
1788 engine->control = (jack_control_t *)
1789 jack_shm_addr (&engine->control_shm);
1791 /* Setup port type information from builtins. buffer space is
1792 * allocated when the driver calls jack_driver_buffer_size().
1794 for (i = 0; jack_builtin_port_types[i].type_name[0]; ++i) {
1796 memcpy (&engine->control->port_types[i],
1797 &jack_builtin_port_types[i],
1798 sizeof (jack_port_type_info_t));
1800 VERBOSE (engine, "registered builtin port type %s",
1801 engine->control->port_types[i].type_name);
1803 /* the port type id is index into port_types array */
1804 engine->control->port_types[i].ptype_id = i;
1806 /* be sure to initialize mutex correctly */
1807 pthread_mutex_init (&engine->port_buffers[i].lock, NULL);
1809 /* set buffer list info correctly */
1810 engine->port_buffers[i].freelist = NULL;
1811 engine->port_buffers[i].info = NULL;
1813 /* mark each port segment as not allocated */
1814 engine->port_segment[i].index = -1;
1815 engine->port_segment[i].attached_at = 0;
1818 engine->control->n_port_types = i;
1820 /* Mark all ports as available */
1822 for (i = 0; i < engine->port_max; i++) {
1823 engine->control->ports[i].in_use = 0;
1824 engine->control->ports[i].id = i;
1825 engine->control->ports[i].alias1[0] = '\0';
1826 engine->control->ports[i].alias2[0] = '\0';
1829 /* allocate internal port structures so that we can keep track
1830 * of port connections.
1832 engine->internal_ports = (jack_port_internal_t *)
1833 malloc (sizeof (jack_port_internal_t) * engine->port_max);
1835 for (i = 0; i < engine->port_max; i++) {
1836 engine->internal_ports[i].connections = 0;
1839 if (make_sockets (engine->server_name, engine->fds) < 0) {
1840 jack_error ("cannot create server sockets");
1841 return NULL;
1844 engine->control->port_max = engine->port_max;
1845 engine->control->real_time = realtime;
1847 /* leave some headroom for other client threads to run
1848 with priority higher than the regular client threads
1849 but less than the server. see thread.h for
1850 jack_client_real_time_priority() and jack_client_max_real_time_priority()
1851 which are affected by this.
1854 engine->control->client_priority = (realtime
1855 ? engine->rtpriority - 5
1856 : 0);
1857 engine->control->max_client_priority = (realtime
1858 ? engine->rtpriority - 1
1859 : 0);
1860 engine->control->do_mlock = do_mlock;
1861 engine->control->do_munlock = do_unlock;
1862 engine->control->cpu_load = 0;
1863 engine->control->xrun_delayed_usecs = 0;
1864 engine->control->max_delayed_usecs = 0;
1866 jack_set_clock_source (clock_source);
1867 engine->control->clock_source = clock_source;
1869 VERBOSE (engine, "clock source = %s", jack_clock_source_name (clock_source));
1871 engine->control->frame_timer.frames = frame_time_offset;
1872 engine->control->frame_timer.reset_pending = 0;
1873 engine->control->frame_timer.current_wakeup = 0;
1874 engine->control->frame_timer.next_wakeup = 0;
1875 engine->control->frame_timer.initialized = 0;
1876 engine->control->frame_timer.filter_coefficient = 0.01;
1877 engine->control->frame_timer.second_order_integrator = 0;
1879 engine->first_wakeup = 1;
1881 engine->control->buffer_size = 0;
1882 jack_transport_init (engine);
1883 jack_set_sample_rate (engine, 0);
1884 engine->control->internal = 0;
1886 engine->control->has_capabilities = 0;
1888 #ifdef JACK_USE_MACH_THREADS
1889 /* specific resources for server/client real-time thread
1890 * communication */
1891 engine->servertask = mach_task_self();
1892 if (task_get_bootstrap_port(engine->servertask, &engine->bp)){
1893 jack_error("Jackd: Can't find bootstrap mach port");
1894 return NULL;
1896 engine->portnum = 0;
1897 #endif /* JACK_USE_MACH_THREADS */
1900 #ifdef USE_CAPABILITIES
1901 if (uid == 0 || euid == 0) {
1902 VERBOSE (engine, "running with uid=%d and euid=%d, "
1903 "will not try to use capabilites",
1904 uid, euid);
1905 } else {
1906 /* only try to use capabilities if not running as root */
1907 engine->control->has_capabilities = check_capabilities (engine);
1908 if (engine->control->has_capabilities == 0) {
1909 VERBOSE (engine, "required capabilities not "
1910 "available");
1912 if (engine->verbose) {
1913 size_t size;
1914 cap_t cap = cap_init();
1915 capgetp(0, cap);
1916 VERBOSE (engine, "capabilities: %s",
1917 cap_to_text(cap, &size));
1920 #endif /* USE_CAPABILITIES */
1922 engine->control->engine_ok = 1;
1924 snprintf (engine->fifo_prefix, sizeof (engine->fifo_prefix),
1925 "%s/jack-ack-fifo-%d",
1926 jack_server_dir (engine->server_name, server_dir), getpid ());
1928 (void) jack_get_fifo_fd (engine, 0);
1930 jack_client_create_thread (NULL, &engine->server_thread, 0, FALSE,
1931 &jack_server_thread, engine);
1933 return engine;
1936 static void
1937 jack_engine_delay (jack_engine_t *engine, float delayed_usecs)
1939 jack_event_t event;
1941 engine->control->frame_timer.reset_pending = 1;
1943 engine->control->xrun_delayed_usecs = delayed_usecs;
1945 if (delayed_usecs > engine->control->max_delayed_usecs)
1946 engine->control->max_delayed_usecs = delayed_usecs;
1948 event.type = XRun;
1950 jack_deliver_event_to_all (engine, &event);
1953 static inline void
1954 jack_inc_frame_time (jack_engine_t *engine, jack_nframes_t nframes)
1956 jack_frame_timer_t *timer = &engine->control->frame_timer;
1957 jack_time_t now = engine->driver->last_wait_ust; // effective time
1958 float delta;
1960 // really need a memory barrier here
1961 timer->guard1++;
1963 delta = (int64_t) now - (int64_t) timer->next_wakeup;
1965 timer->current_wakeup = timer->next_wakeup;
1966 timer->frames += nframes;
1967 timer->second_order_integrator += 0.5f *
1968 timer->filter_coefficient * delta;
1969 timer->next_wakeup = timer->current_wakeup +
1970 engine->driver->period_usecs +
1971 (int64_t) floorf ((timer->filter_coefficient *
1972 (delta + timer->second_order_integrator)));
1973 timer->initialized = 1;
1975 // might need a memory barrier here
1976 timer->guard2++;
1979 static void*
1980 jack_engine_freewheel (void *arg)
1982 jack_engine_t* engine = (jack_engine_t *) arg;
1984 VERBOSE (engine, "freewheel thread starting ...");
1986 /* we should not be running SCHED_FIFO, so we don't
1987 have to do anything about scheduling.
1990 while (engine->freewheeling) {
1992 jack_lock_graph (engine);
1994 if (jack_engine_process (engine,
1995 engine->control->buffer_size)) {
1996 jack_error ("process cycle within freewheel failed");
1997 jack_unlock_graph (engine);
1998 break;
2001 jack_engine_post_process (engine);
2003 jack_unlock_graph (engine);
2006 VERBOSE (engine, "freewheel came to an end, naturally");
2007 return 0;
2010 static int
2011 jack_start_freewheeling (jack_engine_t* engine)
2013 jack_event_t event;
2015 if (engine->freewheeling) {
2016 return 0;
2019 if (engine->driver == NULL) {
2020 jack_error ("cannot start freewheeling without a driver!");
2021 return -1;
2024 /* stop driver before telling anyone about it so
2025 there are no more process() calls being handled.
2028 if (engine->driver->stop (engine->driver)) {
2029 jack_error ("could not stop driver for freewheeling");
2030 return -1;
2033 engine->freewheeling = 1;
2035 event.type = StartFreewheel;
2036 jack_deliver_event_to_all (engine, &event);
2038 if (jack_client_create_thread (NULL, &engine->freewheel_thread, 0, FALSE,
2039 jack_engine_freewheel, engine)) {
2040 jack_error ("could not start create freewheel thread");
2041 return -1;
2044 return 0;
2047 static int
2048 jack_stop_freewheeling (jack_engine_t* engine)
2050 jack_event_t event;
2051 void *ftstatus;
2053 if (!engine->freewheeling) {
2054 return 0;
2057 if (engine->driver == NULL) {
2058 jack_error ("cannot start freewheeling without a driver!");
2059 return -1;
2062 if (!engine->freewheeling) {
2063 VERBOSE (engine, "stop freewheel when not freewheeling");
2064 return 0;
2067 /* tell the freewheel thread to stop, and wait for it
2068 to exit.
2071 engine->freewheeling = 0;
2072 VERBOSE (engine, "freewheeling stopped, waiting for thread");
2073 pthread_join (engine->freewheel_thread, &ftstatus);
2074 VERBOSE (engine, "freewheel thread has returned");
2076 /* tell everyone we've stopped */
2078 event.type = StopFreewheel;
2079 jack_deliver_event_to_all (engine, &event);
2081 /* restart the driver */
2083 if (engine->driver->start (engine->driver)) {
2084 jack_error ("could not restart driver after freewheeling");
2085 return -1;
2087 return 0;
2090 static int
2091 jack_run_one_cycle (jack_engine_t *engine, jack_nframes_t nframes,
2092 float delayed_usecs)
2094 jack_driver_t* driver = engine->driver;
2095 int ret = -1;
2096 static int consecutive_excessive_delays = 0;
2098 #define WORK_SCALE 1.0f
2100 if (engine->control->real_time &&
2101 engine->spare_usecs &&
2102 ((WORK_SCALE * engine->spare_usecs) <= delayed_usecs)) {
2104 MESSAGE("delay of %.3f usecs exceeds estimated spare"
2105 " time of %.3f; restart ...\n",
2106 delayed_usecs, WORK_SCALE * engine->spare_usecs);
2108 if (++consecutive_excessive_delays > 10) {
2109 jack_error ("too many consecutive interrupt delays "
2110 "... engine pausing");
2111 return -1; /* will exit the thread loop */
2114 jack_engine_delay (engine, delayed_usecs);
2116 return 0;
2118 } else {
2119 consecutive_excessive_delays = 0;
2122 DEBUG ("trying to acquire read lock");
2123 if (jack_try_rdlock_graph (engine)) {
2124 /* engine can't run. just throw away an entire cycle */
2125 VERBOSE (engine, "null cycle");
2126 driver->null_cycle (driver, nframes);
2127 return 0;
2130 if (engine->problems) {
2131 /* engine can't run. just throw away an entire cycle */
2132 VERBOSE (engine, "problem-driven null cycle");
2133 jack_unlock_graph (engine);
2134 driver->null_cycle (driver, nframes);
2135 return 0;
2138 if (!engine->freewheeling) {
2139 DEBUG("waiting for driver read\n");
2140 if (driver->read (driver, nframes)) {
2141 goto unlock;
2145 DEBUG("run process\n");
2147 if (jack_engine_process (engine, nframes) == 0) {
2148 if (!engine->freewheeling) {
2149 if (driver->write (driver, nframes)) {
2150 goto unlock;
2154 } else {
2156 JSList *node;
2157 DEBUG ("engine process cycle failed");
2159 /* we are already late, or something else went wrong,
2160 so it can't hurt to check the existence of all
2161 clients.
2164 for (node = engine->clients; node;
2165 node = jack_slist_next (node)) {
2166 jack_client_internal_t *client =
2167 (jack_client_internal_t *) node->data;
2169 if (client->control->type == ClientExternal) {
2170 if (kill (client->control->pid, 0)) {
2171 VERBOSE(engine,
2172 "client %s has died/exited",
2173 client->control->name);
2174 client->error++;
2176 if(client->control->last_status != 0) {
2177 VERBOSE(engine,
2178 "client %s has nonzero process callback status (%d)\n",
2179 client->control->name, client->control->last_status);
2180 client->error++;
2184 DEBUG ("client %s errors = %d", client->control->name,
2185 client->error);
2189 jack_engine_post_process (engine);
2191 if (delayed_usecs > engine->control->max_delayed_usecs)
2192 engine->control->max_delayed_usecs = delayed_usecs;
2194 ret = 0;
2196 unlock:
2197 jack_unlock_graph (engine);
2198 DEBUG("cycle finished, status = %d", ret);
2200 return ret;
2203 static void
2204 jack_engine_driver_exit (jack_engine_t* engine)
2206 jack_driver_t* driver = engine->driver;
2208 VERBOSE (engine, "stopping driver");
2209 driver->stop (driver);
2210 VERBOSE (engine, "detaching driver");
2211 driver->detach (driver, engine);
2213 /* tell anyone waiting that the driver exited. */
2214 kill (engine->wait_pid, SIGUSR2);
2216 engine->driver = NULL;
2219 static int
2220 jack_run_cycle (jack_engine_t *engine, jack_nframes_t nframes,
2221 float delayed_usecs)
2223 jack_nframes_t left;
2224 jack_nframes_t b_size = engine->control->buffer_size;
2225 jack_frame_timer_t* timer = &engine->control->frame_timer;
2226 int no_increment = 0;
2228 if (engine->first_wakeup) {
2230 /* the first wakeup */
2232 timer->next_wakeup =
2233 engine->driver->last_wait_ust +
2234 engine->driver->period_usecs;
2235 engine->first_wakeup = 0;
2237 /* if we got an xrun/delayed wakeup on the first cycle,
2238 reset the pending flag (we have no predicted wakeups
2239 to use), but avoid incrementing the frame timer.
2242 if (timer->reset_pending) {
2243 timer->reset_pending = 0;
2244 no_increment = 1;
2248 if (timer->reset_pending) {
2250 /* post xrun-handling */
2252 /* don't bother to increment the frame counter, because we missed 1 or more
2253 deadlines in the backend anyway.
2256 timer->current_wakeup = engine->driver->last_wait_ust;
2257 timer->next_wakeup = engine->driver->last_wait_ust +
2258 engine->driver->period_usecs;
2260 timer->reset_pending = 0;
2262 } else {
2264 /* normal condition */
2266 if (!no_increment) {
2267 jack_inc_frame_time (engine, nframes);
2271 if (engine->verbose) {
2272 if (nframes != b_size) {
2273 VERBOSE (engine,
2274 "late driver wakeup: nframes to process = %"
2275 PRIu32 ".", nframes);
2279 /* run as many cycles as it takes to consume nframes */
2280 for (left = nframes; left >= b_size; left -= b_size) {
2281 if (jack_run_one_cycle (engine, b_size, delayed_usecs)) {
2282 jack_error ("cycle execution failure, exiting");
2283 return EIO;
2287 return 0;
2290 void
2291 jack_engine_delete (jack_engine_t *engine)
2293 int i;
2295 if (engine == NULL)
2296 return;
2298 VERBOSE (engine, "starting server engine shutdown");
2300 engine->control->engine_ok = 0; /* tell clients we're going away */
2302 /* this will wake the server thread and cause it to exit */
2304 close (engine->cleanup_fifo[0]);
2305 close (engine->cleanup_fifo[1]);
2307 /* shutdown master socket to prevent new clients arriving */
2308 shutdown (engine->fds[0], SHUT_RDWR);
2309 // close (engine->fds[0]);
2311 /* now really tell them we're going away */
2313 for (i = 0; i < engine->pfd_max; ++i) {
2314 shutdown (engine->pfd[i].fd, SHUT_RDWR);
2317 if (engine->driver) {
2318 jack_driver_t* driver = engine->driver;
2320 VERBOSE (engine, "stopping driver");
2321 driver->stop (driver);
2322 // VERBOSE (engine, "detaching driver");
2323 // driver->detach (driver, engine);
2324 VERBOSE (engine, "unloading driver");
2325 jack_driver_unload (driver);
2326 engine->driver = NULL;
2329 VERBOSE (engine, "freeing shared port segments");
2330 for (i = 0; i < engine->control->n_port_types; ++i) {
2331 jack_release_shm (&engine->port_segment[i]);
2332 jack_destroy_shm (&engine->port_segment[i]);
2335 /* stop the other engine threads */
2336 VERBOSE (engine, "stopping server thread");
2338 #if JACK_USE_MACH_THREADS
2339 // MacOSX pthread_cancel still not implemented correctly in Darwin
2340 mach_port_t machThread = pthread_mach_thread_np (engine->server_thread);
2341 thread_terminate (machThread);
2342 #else
2343 pthread_cancel (engine->server_thread);
2344 pthread_join (engine->server_thread, NULL);
2345 #endif
2347 #ifndef JACK_USE_MACH_THREADS
2348 /* Cancel the watchdog thread and wait for it to terminate.
2350 * The watchdog thread is not used on MacOSX since CoreAudio
2351 * drivers already contain a similar mechanism.
2353 if (engine->control->real_time && engine->watchdog_thread) {
2354 VERBOSE (engine, "stopping watchdog thread");
2355 pthread_cancel (engine->watchdog_thread);
2356 pthread_join (engine->watchdog_thread, NULL);
2358 #endif
2360 VERBOSE (engine, "last xrun delay: %.3f usecs",
2361 engine->control->xrun_delayed_usecs);
2362 VERBOSE (engine, "max delay reported by backend: %.3f usecs",
2363 engine->control->max_delayed_usecs);
2365 /* free engine control shm segment */
2366 engine->control = NULL;
2367 VERBOSE (engine, "freeing engine shared memory");
2368 jack_release_shm (&engine->control_shm);
2369 jack_destroy_shm (&engine->control_shm);
2371 VERBOSE (engine, "max usecs: %.3f, engine deleted", engine->max_usecs);
2373 free (engine);
2375 jack_messagebuffer_exit();
2378 void
2379 jack_port_clear_connections (jack_engine_t *engine,
2380 jack_port_internal_t *port)
2382 JSList *node, *next;
2384 for (node = port->connections; node; ) {
2385 next = jack_slist_next (node);
2386 jack_port_disconnect_internal (
2387 engine, ((jack_connection_internal_t *)
2388 node->data)->source,
2389 ((jack_connection_internal_t *)
2390 node->data)->destination);
2391 node = next;
2394 jack_slist_free (port->connections);
2395 port->connections = 0;
2398 static void
2399 jack_deliver_event_to_all (jack_engine_t *engine, jack_event_t *event)
2401 JSList *node;
2403 jack_rdlock_graph (engine);
2404 for (node = engine->clients; node; node = jack_slist_next (node)) {
2405 jack_deliver_event (engine,
2406 (jack_client_internal_t *) node->data,
2407 event);
2409 jack_unlock_graph (engine);
2412 static void
2413 jack_notify_all_port_interested_clients (jack_engine_t *engine, jack_client_id_t src, jack_client_id_t dst, jack_port_id_t a, jack_port_id_t b, int connected)
2415 JSList *node;
2416 jack_event_t event;
2418 event.type = (connected ? PortConnected : PortDisconnected);
2419 event.x.self_id = a;
2420 event.y.other_id = b;
2422 /* GRAPH MUST BE LOCKED : see callers of jack_send_connection_notification()
2425 jack_client_internal_t* src_client = jack_client_internal_by_id (engine, src);
2426 jack_client_internal_t* dst_client = jack_client_internal_by_id (engine, dst);
2428 for (node = engine->clients; node; node = jack_slist_next (node)) {
2429 jack_client_internal_t* client = (jack_client_internal_t*) node->data;
2430 if (src_client != client && dst_client != client && client->control->port_connect_cbset != FALSE) {
2432 /* one of the ports belong to this client or it has a port connect callback */
2433 jack_deliver_event (engine, client, &event);
2438 static int
2439 jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client,
2440 jack_event_t *event)
2442 char status;
2444 /* caller must hold the graph lock */
2446 DEBUG ("delivering event (type %d)", event->type);
2448 /* we are not RT-constrained here, so use kill(2) to beef up
2449 our check on a client's continued well-being
2452 if (client->control->dead || client->error >= JACK_ERROR_WITH_SOCKETS
2453 || (client->control->type == ClientExternal && kill (client->control->pid, 0))) {
2454 DEBUG ("client %s is dead - no event sent",
2455 client->control->name);
2456 return 0;
2459 DEBUG ("client %s is still alive", client->control->name);
2461 if (jack_client_is_internal (client)) {
2463 switch (event->type) {
2464 case PortConnected:
2465 case PortDisconnected:
2466 jack_client_handle_port_connection
2467 (client->private_client, event);
2468 break;
2470 case BufferSizeChange:
2471 jack_client_invalidate_port_buffers
2472 (client->private_client);
2474 if (client->control->bufsize_cbset) {
2475 client->private_client->bufsize
2476 (event->x.n,
2477 client->private_client->bufsize_arg);
2479 break;
2481 case SampleRateChange:
2482 if (client->control->srate_cbset) {
2483 client->private_client->srate
2484 (event->x.n,
2485 client->private_client->srate_arg);
2487 break;
2489 case GraphReordered:
2490 if (client->control->graph_order_cbset) {
2491 client->private_client->graph_order
2492 (client->private_client->graph_order_arg);
2494 break;
2496 case XRun:
2497 if (client->control->xrun_cbset) {
2498 client->private_client->xrun
2499 (client->private_client->xrun_arg);
2501 break;
2503 default:
2504 /* internal clients don't need to know */
2505 break;
2508 } else {
2510 if (client->control->active) {
2512 /* there's a thread waiting for events, so
2513 * it's worth telling the client */
2515 DEBUG ("engine writing on event fd");
2517 if (write (client->event_fd, event, sizeof (*event))
2518 != sizeof (*event)) {
2519 jack_error ("cannot send event to client [%s]"
2520 " (%s)", client->control->name,
2521 strerror (errno));
2522 client->error += JACK_ERROR_WITH_SOCKETS;
2523 jack_lock_problems (engine);
2524 engine->problems++;
2525 jack_unlock_problems (engine);
2528 if (client->error) {
2529 status = 1;
2530 } else {
2531 // then we check whether there really is an error.... :)
2533 struct pollfd pfd[1];
2534 pfd[0].fd = client->event_fd;
2535 pfd[0].events = POLLERR|POLLIN|POLLHUP|POLLNVAL;
2536 jack_time_t poll_timeout = JACKD_CLIENT_EVENT_TIMEOUT;
2537 int poll_ret;
2538 jack_time_t then = jack_get_microseconds ();
2539 jack_time_t now;
2541 #ifdef __linux
2542 again:
2543 #endif
2544 VERBOSE(engine,"client event poll on %d for %s starts at %lld",
2545 client->event_fd, client->control->name, then);
2546 if ((poll_ret = poll (pfd, 1, poll_timeout)) < 0) {
2547 DEBUG ("client event poll not ok! (-1) poll returned an error");
2548 jack_error ("poll on subgraph processing failed (%s)", strerror (errno));
2549 status = -1;
2550 } else {
2552 DEBUG ("\n\n\n\n\n back from client event poll, revents = 0x%x\n\n\n", pfd[0].revents);
2553 now = jack_get_microseconds();
2554 VERBOSE(engine,"back from client event poll after %lld usecs", now - then);
2556 if (pfd[0].revents & ~POLLIN) {
2558 /* some kind of OOB socket event */
2560 DEBUG ("client event poll not ok! (-2), revents = %d\n", pfd[0].revents);
2561 jack_error ("subgraph starting at %s lost client", client->control->name);
2562 status = -2;
2564 } else if (pfd[0].revents & POLLIN) {
2566 /* client responded normally */
2568 DEBUG ("client event poll ok!");
2569 status = 0;
2571 } else if (poll_ret == 0) {
2573 /* no events, no errors, we woke up because poll()
2574 decided that time was up ...
2577 #ifdef __linux
2578 if (linux_poll_bug_encountered (engine, then, &poll_timeout)) {
2579 goto again;
2582 if (poll_timeout < 200) {
2583 VERBOSE (engine, "FALSE WAKEUP skipped, remaining = %lld usec", poll_timeout);
2584 status = 0;
2585 } else {
2586 #endif
2587 DEBUG ("client event poll not ok! (1 = poll timed out, revents = 0x%04x, poll_ret = %d)", pfd[0].revents, poll_ret);
2588 VERBOSE (engine,"client %s did not respond to event type %d in time"
2589 "(fd=%d, revents = 0x%04x, timeout was %lld)",
2590 client->control->name, event->type,
2591 client->event_fd,
2592 pfd[0].revents,
2593 poll_timeout);
2594 status = 1;
2595 #ifdef __linux
2597 #endif
2602 if (status == 0) {
2603 if (read (client->event_fd, &status, sizeof (status)) != sizeof (status)) {
2604 jack_error ("cannot read event response from "
2605 "client [%s] (%s)",
2606 client->control->name,
2607 strerror (errno));
2608 client->error += JACK_ERROR_WITH_SOCKETS;
2609 jack_lock_problems (engine);
2610 engine->problems++;
2611 jack_unlock_problems (engine);
2613 } else {
2614 jack_error ("bad status (%d) for client %s "
2615 "handling event (type = %d)",
2616 status,
2617 client->control->name,
2618 event->type);
2619 client->error += JACK_ERROR_WITH_SOCKETS;
2620 jack_lock_problems (engine);
2621 engine->problems++;
2622 jack_unlock_problems (engine);
2626 DEBUG ("event delivered");
2628 return 0;
2632 jack_rechain_graph (jack_engine_t *engine)
2634 JSList *node, *next;
2635 unsigned long n;
2636 int err = 0;
2637 jack_client_internal_t *client, *subgraph_client, *next_client;
2638 jack_event_t event;
2639 int upstream_is_jackd;
2641 jack_clear_fifos (engine);
2643 subgraph_client = 0;
2645 VERBOSE(engine, "++ jack_rechain_graph():");
2647 event.type = GraphReordered;
2649 for (n = 0, node = engine->clients, next = NULL; node; node = next) {
2651 next = jack_slist_next (node);
2653 VERBOSE(engine, "+++ client is now %s active ? %d",
2654 ((jack_client_internal_t *) node->data)->control->name,
2655 ((jack_client_internal_t *) node->data)->control->active);
2657 if (((jack_client_internal_t *) node->data)->control->active) {
2659 client = (jack_client_internal_t *) node->data;
2661 /* find the next active client. its ok for
2662 * this to be NULL */
2664 while (next) {
2665 if (((jack_client_internal_t *)
2666 next->data)->control->active) {
2667 break;
2669 next = jack_slist_next (next);
2672 if (next == NULL) {
2673 next_client = NULL;
2674 } else {
2675 next_client = (jack_client_internal_t *)
2676 next->data;
2679 client->execution_order = n;
2680 client->next_client = next_client;
2682 if (jack_client_is_internal (client)) {
2684 /* break the chain for the current
2685 * subgraph. the server will wait for
2686 * chain on the nth FIFO, and will
2687 * then execute this internal
2688 * client. */
2690 if (subgraph_client) {
2691 subgraph_client->subgraph_wait_fd =
2692 jack_get_fifo_fd (engine, n);
2693 VERBOSE (engine, "client %s: wait_fd="
2694 "%d, execution_order="
2695 "%lu.",
2696 subgraph_client->
2697 control->name,
2698 subgraph_client->
2699 subgraph_wait_fd, n);
2700 n++;
2703 VERBOSE (engine, "client %s: internal "
2704 "client, execution_order="
2705 "%lu.",
2706 client->control->name, n);
2708 /* this does the right thing for
2709 * internal clients too
2712 jack_deliver_event (engine, client, &event);
2714 subgraph_client = 0;
2716 } else {
2718 if (subgraph_client == NULL) {
2720 /* start a new subgraph. the
2721 * engine will start the chain
2722 * by writing to the nth
2723 * FIFO.
2726 subgraph_client = client;
2727 subgraph_client->subgraph_start_fd =
2728 jack_get_fifo_fd (engine, n);
2729 VERBOSE (engine, "client %s: "
2730 "start_fd=%d, execution"
2731 "_order=%lu.",
2732 subgraph_client->
2733 control->name,
2734 subgraph_client->
2735 subgraph_start_fd, n);
2737 /* this external client after
2738 this will have jackd as its
2739 upstream connection.
2742 upstream_is_jackd = 1;
2745 else {
2746 VERBOSE (engine, "client %s: in"
2747 " subgraph after %s, "
2748 "execution_order="
2749 "%lu.",
2750 client->control->name,
2751 subgraph_client->
2752 control->name, n);
2753 subgraph_client->subgraph_wait_fd = -1;
2755 /* this external client after
2756 this will have another
2757 client as its upstream
2758 connection.
2761 upstream_is_jackd = 0;
2764 /* make sure fifo for 'n + 1' exists
2765 * before issuing client reorder
2767 (void) jack_get_fifo_fd(
2768 engine, client->execution_order + 1);
2769 event.x.n = client->execution_order;
2770 event.y.n = upstream_is_jackd;
2771 jack_deliver_event (engine, client, &event);
2772 n++;
2777 if (subgraph_client) {
2778 subgraph_client->subgraph_wait_fd =
2779 jack_get_fifo_fd (engine, n);
2780 VERBOSE (engine, "client %s: wait_fd=%d, "
2781 "execution_order=%lu (last client).",
2782 subgraph_client->control->name,
2783 subgraph_client->subgraph_wait_fd, n);
2786 VERBOSE (engine, "-- jack_rechain_graph()");
2788 return err;
2791 static jack_nframes_t
2792 jack_get_port_total_latency (jack_engine_t *engine,
2793 jack_port_internal_t *port, int hop_count,
2794 int toward_port)
2796 JSList *node;
2797 jack_nframes_t latency;
2798 jack_nframes_t max_latency = 0;
2800 #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
2801 char prefix[32];
2802 int i;
2804 for (i = 0; i < hop_count; ++i) {
2805 prefix[i] = '\t';
2808 prefix[i] = '\0';
2809 #endif
2811 /* call tree must hold engine->client_lock. */
2813 latency = port->shared->latency;
2815 /* we don't prevent cyclic graphs, so we have to do something
2816 to bottom out in the event that they are created.
2819 if (hop_count > 8) {
2820 return latency;
2823 #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
2824 jack_info ("%sFor port %s (%s)", prefix, port->shared->name, (toward_port ? "toward" : "away"));
2825 #endif
2827 for (node = port->connections; node; node = jack_slist_next (node)) {
2829 jack_nframes_t this_latency;
2830 jack_connection_internal_t *connection;
2832 connection = (jack_connection_internal_t *) node->data;
2835 if ((toward_port &&
2836 (connection->source->shared == port->shared)) ||
2837 (!toward_port &&
2838 (connection->destination->shared == port->shared))) {
2840 #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
2841 jack_info ("%s\tskip connection %s->%s",
2842 prefix,
2843 connection->source->shared->name,
2844 connection->destination->shared->name);
2845 #endif
2847 continue;
2850 #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
2851 jack_info ("%s\tconnection %s->%s ... ",
2852 prefix,
2853 connection->source->shared->name,
2854 connection->destination->shared->name);
2855 #endif
2856 /* if we're a destination in the connection, recurse
2857 on the source to get its total latency
2860 if (connection->destination == port) {
2862 if (connection->source->shared->flags
2863 & JackPortIsTerminal) {
2864 this_latency = connection->source->
2865 shared->latency;
2866 } else {
2867 this_latency =
2868 jack_get_port_total_latency (
2869 engine, connection->source,
2870 hop_count + 1,
2871 toward_port);
2874 } else {
2876 /* "port" is the source, so get the latency of
2877 * the destination */
2878 if (connection->destination->shared->flags
2879 & JackPortIsTerminal) {
2880 this_latency = connection->destination->
2881 shared->latency;
2882 } else {
2883 this_latency =
2884 jack_get_port_total_latency (
2885 engine,
2886 connection->destination,
2887 hop_count + 1,
2888 toward_port);
2892 if (this_latency > max_latency) {
2893 max_latency = this_latency;
2897 #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
2898 jack_info ("%s\treturn %lu + %lu = %lu", prefix, latency, max_latency, latency + max_latency);
2899 #endif
2901 return latency + max_latency;
2904 static void
2905 jack_compute_port_total_latency (jack_engine_t* engine, jack_port_shared_t* port)
2907 if (port->in_use) {
2908 port->total_latency =
2909 jack_get_port_total_latency (
2910 engine, &engine->internal_ports[port->id],
2911 0, !(port->flags & JackPortIsOutput));
2915 static void
2916 jack_compute_all_port_total_latencies (jack_engine_t *engine)
2918 jack_port_shared_t *shared = engine->control->ports;
2919 unsigned int i;
2920 int toward_port;
2922 for (i = 0; i < engine->control->port_max; i++) {
2923 if (shared[i].in_use) {
2924 if (shared[i].flags & JackPortIsOutput) {
2925 toward_port = FALSE;
2926 } else {
2927 toward_port = TRUE;
2929 shared[i].total_latency =
2930 jack_get_port_total_latency (
2931 engine, &engine->internal_ports[i],
2932 0, toward_port);
2937 /* How the sort works:
2939 * Each client has a "sortfeeds" list of clients indicating which clients
2940 * it should be considered as feeding for the purposes of sorting the
2941 * graph. This list differs from the clients it /actually/ feeds in the
2942 * following ways:
2944 * 1. Connections from a client to itself are disregarded
2946 * 2. Connections to a driver client are disregarded
2948 * 3. If a connection from A to B is a feedback connection (ie there was
2949 * already a path from B to A when the connection was made) then instead
2950 * of B appearing on A's sortfeeds list, A will appear on B's sortfeeds
2951 * list.
2953 * If client A is on client B's sortfeeds list, client A must come after
2954 * client B in the execution order. The above 3 rules ensure that the
2955 * sortfeeds relation is always acyclic so that all ordering constraints
2956 * can actually be met.
2958 * Each client also has a "truefeeds" list which is the same as sortfeeds
2959 * except that feedback connections appear normally instead of reversed.
2960 * This is used to detect whether the graph has become acyclic.
2964 void
2965 jack_sort_graph (jack_engine_t *engine)
2967 /* called, obviously, must hold engine->client_lock */
2969 VERBOSE (engine, "++ jack_sort_graph");
2970 engine->clients = jack_slist_sort (engine->clients,
2971 (JCompareFunc) jack_client_sort);
2972 jack_compute_all_port_total_latencies (engine);
2973 jack_rechain_graph (engine);
2974 VERBOSE (engine, "-- jack_sort_graph");
2977 static int
2978 jack_client_sort (jack_client_internal_t *a, jack_client_internal_t *b)
2980 /* drivers are forced to the front, ie considered as sources
2981 rather than sinks for purposes of the sort */
2983 if (jack_client_feeds_transitive (a, b) ||
2984 (a->control->type == ClientDriver &&
2985 b->control->type != ClientDriver)) {
2986 return -1;
2987 } else if (jack_client_feeds_transitive (b, a) ||
2988 (b->control->type == ClientDriver &&
2989 a->control->type != ClientDriver)) {
2990 return 1;
2991 } else {
2992 return 0;
2996 /* transitive closure of the relation expressed by the sortfeeds lists. */
2997 static int
2998 jack_client_feeds_transitive (jack_client_internal_t *source,
2999 jack_client_internal_t *dest )
3001 jack_client_internal_t *med;
3002 JSList *node;
3004 if (jack_slist_find (source->sortfeeds, dest)) {
3005 return 1;
3008 for (node = source->sortfeeds; node; node = jack_slist_next (node)) {
3010 med = (jack_client_internal_t *) node->data;
3012 if (jack_client_feeds_transitive (med, dest)) {
3013 return 1;
3017 return 0;
3021 * Checks whether the graph has become acyclic and if so modifies client
3022 * sortfeeds lists to turn leftover feedback connections into normal ones.
3023 * This lowers latency, but at the expense of some data corruption.
3025 static void
3026 jack_check_acyclic (jack_engine_t *engine)
3028 JSList *srcnode, *dstnode, *portnode, *connnode;
3029 jack_client_internal_t *src, *dst;
3030 jack_port_internal_t *port;
3031 jack_connection_internal_t *conn;
3032 int stuck;
3033 int unsortedclients = 0;
3035 VERBOSE (engine, "checking for graph become acyclic");
3037 for (srcnode = engine->clients; srcnode;
3038 srcnode = jack_slist_next (srcnode)) {
3040 src = (jack_client_internal_t *) srcnode->data;
3041 src->tfedcount = src->fedcount;
3042 unsortedclients++;
3045 stuck = FALSE;
3047 /* find out whether a normal sort would have been possible */
3048 while (unsortedclients && !stuck) {
3050 stuck = TRUE;
3052 for (srcnode = engine->clients; srcnode;
3053 srcnode = jack_slist_next (srcnode)) {
3055 src = (jack_client_internal_t *) srcnode->data;
3057 if (!src->tfedcount) {
3059 stuck = FALSE;
3060 unsortedclients--;
3061 src->tfedcount = -1;
3063 for (dstnode = src->truefeeds; dstnode;
3064 dstnode = jack_slist_next (dstnode)) {
3066 dst = (jack_client_internal_t *)
3067 dstnode->data;
3068 dst->tfedcount--;
3074 if (stuck) {
3076 VERBOSE (engine, "graph is still cyclic" );
3077 } else {
3079 VERBOSE (engine, "graph has become acyclic");
3081 /* turn feedback connections around in sortfeeds */
3082 for (srcnode = engine->clients; srcnode;
3083 srcnode = jack_slist_next (srcnode)) {
3085 src = (jack_client_internal_t *) srcnode->data;
3087 for (portnode = src->ports; portnode;
3088 portnode = jack_slist_next (portnode)) {
3090 port = (jack_port_internal_t *) portnode->data;
3092 for (connnode = port->connections; connnode;
3093 connnode = jack_slist_next (connnode)) {
3095 conn = (jack_connection_internal_t*)
3096 connnode->data;
3098 if (conn->dir == -1 )
3100 /*&&
3101 conn->srcclient == src) */{
3103 VERBOSE (engine,
3104 "reversing connection from "
3105 "%s to %s",
3106 conn->srcclient->control->name,
3107 conn->dstclient->control->name);
3108 conn->dir = 1;
3109 conn->dstclient->sortfeeds =
3110 jack_slist_remove
3111 (conn->dstclient->sortfeeds,
3112 conn->srcclient);
3114 conn->srcclient->sortfeeds =
3115 jack_slist_prepend
3116 (conn->srcclient->sortfeeds,
3117 conn->dstclient );
3122 engine->feedbackcount = 0;
3127 * Dumps current engine configuration.
3129 void jack_dump_configuration(jack_engine_t *engine, int take_lock)
3131 JSList *clientnode, *portnode, *connectionnode;
3132 jack_client_internal_t *client;
3133 jack_client_control_t *ctl;
3134 jack_port_internal_t *port;
3135 jack_connection_internal_t* connection;
3136 int n, m, o;
3138 jack_info ("engine.c: <-- dump begins -->");
3140 if (take_lock) {
3141 jack_rdlock_graph (engine);
3144 for (n = 0, clientnode = engine->clients; clientnode;
3145 clientnode = jack_slist_next (clientnode)) {
3146 client = (jack_client_internal_t *) clientnode->data;
3147 ctl = client->control;
3149 jack_info ("client #%d: %s (type: %d, process? %s,"
3150 " start=%d wait=%d",
3151 ++n,
3152 ctl->name,
3153 ctl->type,
3154 ctl->process_cbset ? "yes" : "no",
3155 client->subgraph_start_fd,
3156 client->subgraph_wait_fd);
3158 for(m = 0, portnode = client->ports; portnode;
3159 portnode = jack_slist_next (portnode)) {
3160 port = (jack_port_internal_t *) portnode->data;
3162 jack_info("\t port #%d: %s", ++m,
3163 port->shared->name);
3165 for(o = 0, connectionnode = port->connections;
3166 connectionnode;
3167 connectionnode =
3168 jack_slist_next (connectionnode)) {
3169 connection = (jack_connection_internal_t *)
3170 connectionnode->data;
3172 jack_info("\t\t connection #%d: %s %s",
3173 ++o,
3174 (port->shared->flags
3175 & JackPortIsInput)? "<-": "->",
3176 (port->shared->flags & JackPortIsInput)?
3177 connection->source->shared->name:
3178 connection->destination->shared->name);
3183 if (take_lock) {
3184 jack_unlock_graph (engine);
3188 jack_info("engine.c: <-- dump ends -->");
3191 static int
3192 jack_port_do_connect (jack_engine_t *engine,
3193 const char *source_port,
3194 const char *destination_port)
3196 jack_connection_internal_t *connection;
3197 jack_port_internal_t *srcport, *dstport;
3198 jack_port_id_t src_id, dst_id;
3199 jack_client_internal_t *srcclient, *dstclient;
3200 JSList *it;
3202 if ((srcport = jack_get_port_by_name (engine, source_port)) == NULL) {
3203 jack_error ("unknown source port in attempted connection [%s]",
3204 source_port);
3205 return -1;
3208 if ((dstport = jack_get_port_by_name (engine, destination_port))
3209 == NULL) {
3210 jack_error ("unknown destination port in attempted connection"
3211 " [%s]", destination_port);
3212 return -1;
3215 if ((dstport->shared->flags & JackPortIsInput) == 0) {
3216 jack_error ("destination port in attempted connection of"
3217 " %s and %s is not an input port",
3218 source_port, destination_port);
3219 return -1;
3222 if ((srcport->shared->flags & JackPortIsOutput) == 0) {
3223 jack_error ("source port in attempted connection of %s and"
3224 " %s is not an output port",
3225 source_port, destination_port);
3226 return -1;
3229 if (srcport->shared->ptype_id != dstport->shared->ptype_id) {
3230 jack_error ("ports used in attemped connection are not of "
3231 "the same data type");
3232 return -1;
3235 if ((srcclient = jack_client_internal_by_id (engine,
3236 srcport->shared->client_id))
3237 == 0) {
3238 jack_error ("unknown client set as owner of port - "
3239 "cannot connect");
3240 return -1;
3243 if (!srcclient->control->active) {
3244 jack_error ("cannot connect ports owned by inactive clients;"
3245 " \"%s\" is not active", srcclient->control->name);
3246 return -1;
3249 if ((dstclient = jack_client_internal_by_id (engine,
3250 dstport->shared->client_id))
3251 == 0) {
3252 jack_error ("unknown client set as owner of port - cannot "
3253 "connect");
3254 return -1;
3257 if (!dstclient->control->active) {
3258 jack_error ("cannot connect ports owned by inactive clients;"
3259 " \"%s\" is not active", dstclient->control->name);
3260 return -1;
3263 for (it = srcport->connections; it; it = it->next) {
3264 if (((jack_connection_internal_t *)it->data)->destination
3265 == dstport) {
3266 return EEXIST;
3270 connection = (jack_connection_internal_t *)
3271 malloc (sizeof (jack_connection_internal_t));
3273 connection->source = srcport;
3274 connection->destination = dstport;
3275 connection->srcclient = srcclient;
3276 connection->dstclient = dstclient;
3278 src_id = srcport->shared->id;
3279 dst_id = dstport->shared->id;
3281 jack_lock_graph (engine);
3283 if (dstport->connections && !dstport->shared->has_mixdown) {
3284 jack_port_type_info_t *port_type =
3285 jack_port_type_info (engine, dstport);
3286 jack_error ("cannot make multiple connections to a port of"
3287 " type [%s]", port_type->type_name);
3288 free (connection);
3289 jack_unlock_graph (engine);
3290 return -1;
3291 } else {
3293 if (dstclient->control->type == ClientDriver)
3295 /* Ignore output connections to drivers for purposes
3296 of sorting. Drivers are executed first in the sort
3297 order anyway, and we don't want to treat graphs
3298 such as driver -> client -> driver as containing
3299 feedback */
3301 VERBOSE (engine,
3302 "connect %s and %s (output)",
3303 srcport->shared->name,
3304 dstport->shared->name);
3306 connection->dir = 1;
3309 else if (srcclient != dstclient) {
3311 srcclient->truefeeds = jack_slist_prepend
3312 (srcclient->truefeeds, dstclient);
3314 dstclient->fedcount++;
3316 if (jack_client_feeds_transitive (dstclient,
3317 srcclient ) ||
3318 (dstclient->control->type == ClientDriver &&
3319 srcclient->control->type != ClientDriver)) {
3321 /* dest is running before source so
3322 this is a feedback connection */
3324 VERBOSE (engine,
3325 "connect %s and %s (feedback)",
3326 srcport->shared->name,
3327 dstport->shared->name);
3329 dstclient->sortfeeds = jack_slist_prepend
3330 (dstclient->sortfeeds, srcclient);
3332 connection->dir = -1;
3333 engine->feedbackcount++;
3334 VERBOSE (engine,
3335 "feedback count up to %d",
3336 engine->feedbackcount);
3338 } else {
3340 /* this is not a feedback connection */
3342 VERBOSE (engine,
3343 "connect %s and %s (forward)",
3344 srcport->shared->name,
3345 dstport->shared->name);
3347 srcclient->sortfeeds = jack_slist_prepend
3348 (srcclient->sortfeeds, dstclient);
3350 connection->dir = 1;
3353 else
3355 /* this is a connection to self */
3357 VERBOSE (engine,
3358 "connect %s and %s (self)",
3359 srcport->shared->name,
3360 dstport->shared->name);
3362 connection->dir = 0;
3365 dstport->connections =
3366 jack_slist_prepend (dstport->connections, connection);
3367 srcport->connections =
3368 jack_slist_prepend (srcport->connections, connection);
3370 DEBUG ("actually sorted the graph...");
3372 jack_send_connection_notification (engine,
3373 srcport->shared->client_id,
3374 src_id, dst_id, TRUE);
3377 jack_send_connection_notification (engine,
3378 dstport->shared->client_id,
3379 dst_id, src_id, TRUE);
3381 /* send a port connection notification just once to everyone who cares excluding clients involved in the connection */
3383 jack_notify_all_port_interested_clients (engine, srcport->shared->client_id, dstport->shared->client_id, src_id, dst_id, 1);
3385 jack_sort_graph (engine);
3388 jack_unlock_graph (engine);
3390 return 0;
3394 jack_port_disconnect_internal (jack_engine_t *engine,
3395 jack_port_internal_t *srcport,
3396 jack_port_internal_t *dstport )
3399 JSList *node;
3400 jack_connection_internal_t *connect;
3401 int ret = -1;
3402 jack_port_id_t src_id, dst_id;
3403 int check_acyclic = engine->feedbackcount;
3405 /* call tree **** MUST HOLD **** engine->client_lock. */
3406 for (node = srcport->connections; node;
3407 node = jack_slist_next (node)) {
3409 connect = (jack_connection_internal_t *) node->data;
3411 if (connect->source == srcport &&
3412 connect->destination == dstport) {
3414 VERBOSE (engine, "DIS-connect %s and %s",
3415 srcport->shared->name,
3416 dstport->shared->name);
3418 srcport->connections =
3419 jack_slist_remove (srcport->connections,
3420 connect);
3421 dstport->connections =
3422 jack_slist_remove (dstport->connections,
3423 connect);
3425 src_id = srcport->shared->id;
3426 dst_id = dstport->shared->id;
3428 /* this is a bit harsh, but it basically says
3429 that if we actually do a disconnect, and
3430 its the last one, then make sure that any
3431 input monitoring is turned off on the
3432 srcport. this isn't ideal for all
3433 situations, but it works better for most of
3434 them.
3436 if (srcport->connections == NULL) {
3437 srcport->shared->monitor_requests = 0;
3440 jack_send_connection_notification (
3441 engine, srcport->shared->client_id, src_id,
3442 dst_id, FALSE);
3443 jack_send_connection_notification (
3444 engine, dstport->shared->client_id, dst_id,
3445 src_id, FALSE);
3447 /* send a port connection notification just once to everyone who cares excluding clients involved in the connection */
3449 jack_notify_all_port_interested_clients (engine, srcport->shared->client_id, dstport->shared->client_id, src_id, dst_id, 0);
3451 if (connect->dir) {
3453 jack_client_internal_t *src;
3454 jack_client_internal_t *dst;
3456 src = jack_client_internal_by_id
3457 (engine, srcport->shared->client_id);
3459 dst = jack_client_internal_by_id
3460 (engine, dstport->shared->client_id);
3462 src->truefeeds = jack_slist_remove
3463 (src->truefeeds, dst);
3465 dst->fedcount--;
3467 if (connect->dir == 1) {
3468 /* normal connection: remove dest from
3469 source's sortfeeds list */
3470 src->sortfeeds = jack_slist_remove
3471 (src->sortfeeds, dst);
3472 } else {
3473 /* feedback connection: remove source
3474 from dest's sortfeeds list */
3475 dst->sortfeeds = jack_slist_remove
3476 (dst->sortfeeds, src);
3477 engine->feedbackcount--;
3478 VERBOSE (engine,
3479 "feedback count down to %d",
3480 engine->feedbackcount);
3483 } /* else self-connection: do nothing */
3485 free (connect);
3486 ret = 0;
3487 break;
3491 if (check_acyclic) {
3492 jack_check_acyclic (engine);
3495 jack_sort_graph (engine);
3497 return ret;
3500 static int
3501 jack_port_do_disconnect_all (jack_engine_t *engine,
3502 jack_port_id_t port_id)
3504 if (port_id >= engine->control->port_max) {
3505 jack_error ("illegal port ID in attempted disconnection [%"
3506 PRIu32 "]", port_id);
3507 return -1;
3510 VERBOSE (engine, "clear connections for %s",
3511 engine->internal_ports[port_id].shared->name);
3513 jack_lock_graph (engine);
3514 jack_port_clear_connections (engine, &engine->internal_ports[port_id]);
3515 jack_sort_graph (engine);
3516 jack_unlock_graph (engine);
3518 return 0;
3521 static int
3522 jack_port_do_disconnect (jack_engine_t *engine,
3523 const char *source_port,
3524 const char *destination_port)
3526 jack_port_internal_t *srcport, *dstport;
3527 int ret = -1;
3529 if ((srcport = jack_get_port_by_name (engine, source_port)) == NULL) {
3530 jack_error ("unknown source port in attempted disconnection"
3531 " [%s]", source_port);
3532 return -1;
3535 if ((dstport = jack_get_port_by_name (engine, destination_port))
3536 == NULL) {
3537 jack_error ("unknown destination port in attempted"
3538 " disconnection [%s]", destination_port);
3539 return -1;
3542 jack_lock_graph (engine);
3544 ret = jack_port_disconnect_internal (engine, srcport, dstport);
3546 jack_unlock_graph (engine);
3548 return ret;
3551 int
3552 jack_get_fifo_fd (jack_engine_t *engine, unsigned int which_fifo)
3554 /* caller must hold client_lock */
3555 char path[PATH_MAX+1];
3556 struct stat statbuf;
3558 snprintf (path, sizeof (path), "%s-%d", engine->fifo_prefix,
3559 which_fifo);
3561 DEBUG ("%s", path);
3563 if (stat (path, &statbuf)) {
3564 if (errno == ENOENT) {
3566 if (mkfifo(path, 0666) < 0){
3567 jack_error ("cannot create inter-client FIFO"
3568 " [%s] (%s)\n", path,
3569 strerror (errno));
3570 return -1;
3573 } else {
3574 jack_error ("cannot check on FIFO %d\n", which_fifo);
3575 return -1;
3577 } else {
3578 if (!S_ISFIFO(statbuf.st_mode)) {
3579 jack_error ("FIFO %d (%s) already exists, but is not"
3580 " a FIFO!\n", which_fifo, path);
3581 return -1;
3585 if (which_fifo >= engine->fifo_size) {
3586 unsigned int i;
3588 engine->fifo = (int *)
3589 realloc (engine->fifo,
3590 sizeof (int) * (engine->fifo_size + 16));
3591 for (i = engine->fifo_size; i < engine->fifo_size + 16; i++) {
3592 engine->fifo[i] = -1;
3594 engine->fifo_size += 16;
3597 if (engine->fifo[which_fifo] < 0) {
3598 if ((engine->fifo[which_fifo] =
3599 open (path, O_RDWR|O_CREAT|O_NONBLOCK, 0666)) < 0) {
3600 jack_error ("cannot open fifo [%s] (%s)", path,
3601 strerror (errno));
3602 return -1;
3604 DEBUG ("opened engine->fifo[%d] == %d (%s)",
3605 which_fifo, engine->fifo[which_fifo], path);
3608 return engine->fifo[which_fifo];
3611 static void
3612 jack_clear_fifos (jack_engine_t *engine)
3614 /* caller must hold client_lock */
3616 unsigned int i;
3617 char buf[16];
3619 /* this just drains the existing FIFO's of any data left in
3620 them by aborted clients, etc. there is only ever going to
3621 be 0, 1 or 2 bytes in them, but we'll allow for up to 16.
3623 for (i = 0; i < engine->fifo_size; i++) {
3624 if (engine->fifo[i] >= 0) {
3625 int nread = read (engine->fifo[i], buf, sizeof (buf));
3627 if (nread < 0 && errno != EAGAIN) {
3628 jack_error ("clear fifo[%d] error: %s",
3629 i, strerror (errno));
3635 static int
3636 jack_use_driver (jack_engine_t *engine, jack_driver_t *driver)
3638 if (engine->driver) {
3639 engine->driver->detach (engine->driver, engine);
3640 engine->driver = 0;
3643 if (driver) {
3644 engine->driver = driver;
3646 if (driver->attach (driver, engine)) {
3647 engine->driver = 0;
3648 return -1;
3651 engine->rolling_interval =
3652 jack_rolling_interval (driver->period_usecs);
3655 return 0;
3659 /* PORT RELATED FUNCTIONS */
3662 static jack_port_id_t
3663 jack_get_free_port (jack_engine_t *engine)
3666 jack_port_id_t i;
3668 pthread_mutex_lock (&engine->port_lock);
3670 for (i = 0; i < engine->port_max; i++) {
3671 if (engine->control->ports[i].in_use == 0) {
3672 engine->control->ports[i].in_use = 1;
3673 break;
3677 pthread_mutex_unlock (&engine->port_lock);
3679 if (i == engine->port_max) {
3680 return (jack_port_id_t) -1;
3683 return i;
3686 void
3687 jack_port_release (jack_engine_t *engine, jack_port_internal_t *port)
3689 pthread_mutex_lock (&engine->port_lock);
3690 port->shared->in_use = 0;
3691 port->shared->alias1[0] = '\0';
3692 port->shared->alias2[0] = '\0';
3694 if (port->buffer_info) {
3695 jack_port_buffer_list_t *blist =
3696 jack_port_buffer_list (engine, port);
3697 pthread_mutex_lock (&blist->lock);
3698 blist->freelist =
3699 jack_slist_prepend (blist->freelist,
3700 port->buffer_info);
3701 port->buffer_info = NULL;
3702 pthread_mutex_unlock (&blist->lock);
3704 pthread_mutex_unlock (&engine->port_lock);
3707 jack_port_internal_t *
3708 jack_get_port_internal_by_name (jack_engine_t *engine, const char *name)
3710 jack_port_id_t id;
3712 pthread_mutex_lock (&engine->port_lock);
3714 for (id = 0; id < engine->port_max; id++) {
3715 if (jack_port_name_equals (&engine->control->ports[id], name)) {
3716 break;
3720 pthread_mutex_unlock (&engine->port_lock);
3722 if (id != engine->port_max) {
3723 return &engine->internal_ports[id];
3724 } else {
3725 return NULL;
3730 jack_port_do_register (jack_engine_t *engine, jack_request_t *req, int internal)
3732 jack_port_id_t port_id;
3733 jack_port_shared_t *shared;
3734 jack_port_internal_t *port;
3735 jack_client_internal_t *client;
3736 unsigned long i;
3737 char *backend_client_name;
3738 size_t len;
3740 for (i = 0; i < engine->control->n_port_types; ++i) {
3741 if (strcmp (req->x.port_info.type,
3742 engine->control->port_types[i].type_name) == 0) {
3743 break;
3747 if (i == engine->control->n_port_types) {
3748 jack_error ("cannot register a port of type \"%s\"",
3749 req->x.port_info.type);
3750 return -1;
3753 jack_lock_graph (engine);
3754 if ((client = jack_client_internal_by_id (engine,
3755 req->x.port_info.client_id))
3756 == NULL) {
3757 jack_error ("unknown client id in port registration request");
3758 jack_unlock_graph (engine);
3759 return -1;
3762 if ((port = jack_get_port_by_name(engine, req->x.port_info.name)) != NULL) {
3763 jack_error ("duplicate port name in port registration request");
3764 jack_unlock_graph (engine);
3765 return -1;
3768 if ((port_id = jack_get_free_port (engine)) == (jack_port_id_t) -1) {
3769 jack_error ("no ports available!");
3770 jack_unlock_graph (engine);
3771 return -1;
3774 shared = &engine->control->ports[port_id];
3776 if (!internal || !engine->driver)
3777 goto fallback;
3779 backend_client_name = (char *) engine->driver->internal_client->control->name;
3780 len = strlen (backend_client_name);
3782 if (strncmp (req->x.port_info.name, backend_client_name, len) != 0)
3783 goto fallback;
3785 /* use backend's original as an alias, use predefined names */
3787 if (strcmp(req->x.port_info.type, JACK_DEFAULT_AUDIO_TYPE) == 0) {
3788 if ((req->x.port_info.flags & (JackPortIsPhysical|JackPortIsInput)) == (JackPortIsPhysical|JackPortIsInput)) {
3789 snprintf (shared->name, sizeof (shared->name), JACK_BACKEND_ALIAS ":playback_%d", ++engine->audio_out_cnt);
3790 strcpy (shared->alias1, req->x.port_info.name);
3791 goto next;
3793 else if ((req->x.port_info.flags & (JackPortIsPhysical|JackPortIsOutput)) == (JackPortIsPhysical|JackPortIsOutput)) {
3794 snprintf (shared->name, sizeof (shared->name), JACK_BACKEND_ALIAS ":capture_%d", ++engine->audio_in_cnt);
3795 strcpy (shared->alias1, req->x.port_info.name);
3796 goto next;
3800 #if 0 // do not do this for MIDI
3802 else if (strcmp(req->x.port_info.type, JACK_DEFAULT_MIDI_TYPE) == 0) {
3803 if ((req->x.port_info.flags & (JackPortIsPhysical|JackPortIsInput)) == (JackPortIsPhysical|JackPortIsInput)) {
3804 snprintf (shared->name, sizeof (shared->name), JACK_BACKEND_ALIAS ":midi_playback_%d", ++engine->midi_out_cnt);
3805 strcpy (shared->alias1, req->x.port_info.name);
3806 goto next;
3808 else if ((req->x.port_info.flags & (JackPortIsPhysical|JackPortIsOutput)) == (JackPortIsPhysical|JackPortIsOutput)) {
3809 snprintf (shared->name, sizeof (shared->name), JACK_BACKEND_ALIAS ":midi_capture_%d", ++engine->midi_in_cnt);
3810 strcpy (shared->alias1, req->x.port_info.name);
3811 goto next;
3814 #endif
3816 fallback:
3817 strcpy (shared->name, req->x.port_info.name);
3819 next:
3820 shared->ptype_id = engine->control->port_types[i].ptype_id;
3821 shared->client_id = req->x.port_info.client_id;
3822 shared->flags = req->x.port_info.flags;
3823 shared->latency = 0;
3824 shared->monitor_requests = 0;
3826 port = &engine->internal_ports[port_id];
3828 port->shared = shared;
3829 port->connections = 0;
3830 port->buffer_info = NULL;
3832 if (jack_port_assign_buffer (engine, port)) {
3833 jack_error ("cannot assign buffer for port");
3834 jack_port_release (engine, &engine->internal_ports[port_id]);
3835 jack_unlock_graph (engine);
3836 return -1;
3839 client->ports = jack_slist_prepend (client->ports, port);
3840 jack_port_registration_notify (engine, port_id, TRUE);
3841 jack_unlock_graph (engine);
3843 VERBOSE (engine, "registered port %s, offset = %u",
3844 shared->name, (unsigned int)shared->offset);
3846 req->x.port_info.port_id = port_id;
3848 return 0;
3852 jack_port_do_unregister (jack_engine_t *engine, jack_request_t *req)
3854 jack_client_internal_t *client;
3855 jack_port_shared_t *shared;
3856 jack_port_internal_t *port;
3858 if (req->x.port_info.port_id < 0 ||
3859 req->x.port_info.port_id > engine->port_max) {
3860 jack_error ("invalid port ID %" PRIu32
3861 " in unregister request",
3862 req->x.port_info.port_id);
3863 return -1;
3866 shared = &engine->control->ports[req->x.port_info.port_id];
3868 if (shared->client_id != req->x.port_info.client_id) {
3869 jack_error ("Client %" PRIu32
3870 " is not allowed to remove port %s",
3871 req->x.port_info.client_id, shared->name);
3872 return -1;
3875 jack_lock_graph (engine);
3876 if ((client = jack_client_internal_by_id (engine, shared->client_id))
3877 == NULL) {
3878 jack_error ("unknown client id in port registration request");
3879 jack_unlock_graph (engine);
3880 return -1;
3883 port = &engine->internal_ports[req->x.port_info.port_id];
3885 jack_port_clear_connections (engine, port);
3886 jack_port_release (engine,
3887 &engine->internal_ports[req->x.port_info.port_id]);
3889 client->ports = jack_slist_remove (client->ports, port);
3890 jack_port_registration_notify (engine, req->x.port_info.port_id,
3891 FALSE);
3892 jack_unlock_graph (engine);
3894 return 0;
3898 jack_do_get_port_connections (jack_engine_t *engine, jack_request_t *req,
3899 int reply_fd)
3901 jack_port_internal_t *port;
3902 JSList *node;
3903 unsigned int i;
3904 int ret = -1;
3905 int internal = FALSE;
3907 jack_rdlock_graph (engine);
3909 port = &engine->internal_ports[req->x.port_info.port_id];
3911 DEBUG ("Getting connections for port '%s'.", port->shared->name);
3913 req->x.port_connections.nports = jack_slist_length (port->connections);
3914 req->status = 0;
3916 /* figure out if this is an internal or external client */
3918 for (node = engine->clients; node; node = jack_slist_next (node)) {
3920 if (((jack_client_internal_t *) node->data)->request_fd
3921 == reply_fd) {
3922 internal = jack_client_is_internal(
3923 (jack_client_internal_t *) node->data);
3924 break;
3928 if (!internal) {
3929 if (write (reply_fd, req, sizeof (*req))
3930 < (ssize_t) sizeof (req)) {
3931 jack_error ("cannot write GetPortConnections result "
3932 "to client via fd = %d (%s)",
3933 reply_fd, strerror (errno));
3934 goto out;
3936 } else {
3937 req->x.port_connections.ports = (const char**)
3938 malloc (sizeof (char *)
3939 * req->x.port_connections.nports);
3942 if (req->type == GetPortConnections) {
3944 for (i = 0, node = port->connections; node;
3945 node = jack_slist_next (node), ++i) {
3947 jack_port_id_t port_id;
3949 if (((jack_connection_internal_t *) node->data)->source
3950 == port) {
3951 port_id = ((jack_connection_internal_t *)
3952 node->data)->destination->shared->id;
3953 } else {
3954 port_id = ((jack_connection_internal_t *)
3955 node->data)->source->shared->id;
3958 if (internal) {
3960 /* internal client asking for
3961 * names. store in malloc'ed space,
3962 * client frees
3964 char **ports = (char **) req->x.port_connections.ports;
3966 ports[i] =
3967 engine->control->ports[port_id].name;
3969 } else {
3971 /* external client asking for
3972 * names. we write the port id's to
3973 * the reply fd.
3975 if (write (reply_fd, &port_id,
3976 sizeof (port_id))
3977 < (ssize_t) sizeof (port_id)) {
3978 jack_error ("cannot write port id "
3979 "to client");
3980 goto out;
3986 ret = 0;
3988 out:
3989 req->status = ret;
3990 jack_unlock_graph (engine);
3991 return ret;
3994 void
3995 jack_port_registration_notify (jack_engine_t *engine,
3996 jack_port_id_t port_id, int yn)
3998 jack_event_t event;
3999 jack_client_internal_t *client;
4000 JSList *node;
4002 event.type = (yn ? PortRegistered : PortUnregistered);
4003 event.x.port_id = port_id;
4005 for (node = engine->clients; node; node = jack_slist_next (node)) {
4007 client = (jack_client_internal_t *) node->data;
4009 if (!client->control->active) {
4010 continue;
4013 if (client->control->port_register_cbset) {
4014 if (jack_deliver_event (engine, client, &event)) {
4015 jack_error ("cannot send port registration"
4016 " notification to %s (%s)",
4017 client->control->name,
4018 strerror (errno));
4024 void
4025 jack_client_registration_notify (jack_engine_t *engine,
4026 const char* name, int yn)
4028 jack_event_t event;
4029 jack_client_internal_t *client;
4030 JSList *node;
4032 event.type = (yn ? ClientRegistered : ClientUnregistered);
4033 snprintf (event.x.name, sizeof (event.x.name), "%s", name);
4035 for (node = engine->clients; node; node = jack_slist_next (node)) {
4037 client = (jack_client_internal_t *) node->data;
4039 if (!client->control->active) {
4040 continue;
4043 if (strcmp ((char*) client->control->name, (char*) name) == 0) {
4044 /* do not notify client of its own registration */
4045 continue;
4048 if (client->control->client_register_cbset) {
4049 if (jack_deliver_event (engine, client, &event)) {
4050 jack_error ("cannot send client registration"
4051 " notification to %s (%s)",
4052 client->control->name,
4053 strerror (errno));
4060 jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port)
4062 jack_port_buffer_list_t *blist =
4063 jack_port_buffer_list (engine, port);
4064 jack_port_buffer_info_t *bi;
4066 if (port->shared->flags & JackPortIsInput) {
4067 port->shared->offset = 0;
4068 return 0;
4071 pthread_mutex_lock (&blist->lock);
4073 if (blist->freelist == NULL) {
4074 jack_port_type_info_t *port_type =
4075 jack_port_type_info (engine, port);
4076 jack_error ("all %s port buffers in use!",
4077 port_type->type_name);
4078 pthread_mutex_unlock (&blist->lock);
4079 return -1;
4082 bi = (jack_port_buffer_info_t *) blist->freelist->data;
4083 blist->freelist = jack_slist_remove (blist->freelist, bi);
4085 port->shared->offset = bi->offset;
4086 port->buffer_info = bi;
4088 pthread_mutex_unlock (&blist->lock);
4089 return 0;
4092 static jack_port_internal_t *
4093 jack_get_port_by_name (jack_engine_t *engine, const char *name)
4095 jack_port_id_t id;
4097 /* Note the potential race on "in_use". Other design
4098 elements prevent this from being a problem.
4101 for (id = 0; id < engine->port_max; id++) {
4102 if (engine->control->ports[id].in_use &&
4103 jack_port_name_equals (&engine->control->ports[id], name)) {
4104 return &engine->internal_ports[id];
4108 return NULL;
4111 static int
4112 jack_send_connection_notification (jack_engine_t *engine,
4113 jack_client_id_t client_id,
4114 jack_port_id_t self_id,
4115 jack_port_id_t other_id, int connected)
4118 jack_client_internal_t *client;
4119 jack_event_t event;
4121 if ((client = jack_client_internal_by_id (engine, client_id)) == NULL) {
4122 jack_error ("no such client %" PRIu32
4123 " during connection notification", client_id);
4124 return -1;
4127 if (client->control->active) {
4128 event.type = (connected ? PortConnected : PortDisconnected);
4129 event.x.self_id = self_id;
4130 event.y.other_id = other_id;
4132 if (jack_deliver_event (engine, client, &event)) {
4133 jack_error ("cannot send port connection notification"
4134 " to client %s (%s)",
4135 client->control->name, strerror (errno));
4136 return -1;
4140 return 0;