** Warning: Cannot open xref database.
1 /* -*- mode: c; c-file-style: "bsd"; -*- */
2 /*
3 Copyright (C) 2001-2003 Paul Davis
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 $Id: client.c,v 1.61 2003/12/10 06:52:17 joq Exp $
20 */
21
22 #if defined(__APPLE__) && defined(__POWERPC__)
23 #include "pThreadUtilities.h"
24 #include "ipc.h"
25 #include "fakepoll.h"
26 #else
27 #include <sys/poll.h>
28 #endif
29
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <pthread.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/ipc.h>
37 #include <sys/mman.h>
38
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdint.h>
42 #include <regex.h>
43
44 #include <config.h>
45
46 #include <jack/jack.h>
47 #include <jack/internal.h>
48 #include <jack/engine.h>
49 #include <jack/pool.h>
50 #include <jack/time.h>
51 #include <jack/jslist.h>
52 #include <jack/version.h>
53 #include <jack/shm.h>
54
55 #include "local.h"
56
57 #ifdef WITH_TIMESTAMPS
58 #include <jack/timestamps.h>
59 #endif /* WITH_TIMESTAMPS */
60
61 #ifdef DEFAULT_TMP_DIR
62 char *jack_server_dir = DEFAULT_TMP_DIR;
63 #else
64 char *jack_server_dir = "/tmp";
65 #endif
66
67 void
68 jack_set_server_dir (const char *path)
69 {
70 fprintf (stderr, "jack_set_server_dir() is deprecated.\n Please contact the program's author\n");
71 jack_server_dir = strdup (path);
72 }
73
74 static pthread_mutex_t client_lock;
75 static pthread_cond_t client_ready;
76 void *jack_zero_filled_buffer = NULL;
77
78 #define event_fd pollfd[0].fd
79 #define graph_wait_fd pollfd[1].fd
80
81 typedef struct {
82 int status;
83 struct _jack_client *client;
84 const char *client_name;
85 } client_info;
86
87 void
88 jack_error (const char *fmt, ...)
89 {
90 va_list ap;
91 char buffer[300];
92
93 va_start (ap, fmt);
94 vsnprintf (buffer, sizeof(buffer), fmt, ap);
95 jack_error_callback (buffer);
96 va_end (ap);
97 }
98
99 void default_jack_error_callback (const char *desc)
100 {
101 fprintf(stderr, "%s\n", desc);
102 }
103
104 void silent_jack_error_callback (const char *desc)
105 {
106 }
107
108 void (*jack_error_callback)(const char *desc) = &default_jack_error_callback;
109
110 static int
111 oop_client_deliver_request (void *ptr, jack_request_t *req)
112 {
113 jack_client_t *client = (jack_client_t*) ptr;
114
115 if (write (client->request_fd, req, sizeof (*req)) != sizeof (*req)) {
116 jack_error ("cannot send request type %d to server", req->type);
117 req->status = -1;
118 }
119 if (read (client->request_fd, req, sizeof (*req)) != sizeof (*req)) {
120 jack_error ("cannot read result for request type %d from server (%s)", req->type, strerror (errno));
121 req->status = -1;
122 }
123
124 return req->status;
125 }
126
127 int
128 jack_client_deliver_request (const jack_client_t *client, jack_request_t *req)
129 {
130 /* indirect through the function pointer that was set
131 either by jack_client_new() (external) or handle_new_client()
132 in the server.
133 */
134
135 return client->control->deliver_request (client->control->deliver_arg, req);
136 }
137
138 jack_client_t *
139 jack_client_alloc ()
140 {
141 jack_client_t *client;
142
143 client = (jack_client_t *) malloc (sizeof (jack_client_t));
144 client->pollfd = (struct pollfd *) malloc (sizeof (struct pollfd) * 2);
145 client->pollmax = 2;
146 client->request_fd = -1;
147 client->event_fd = -1;
148 client->graph_wait_fd = -1;
149 client->graph_next_fd = -1;
150 client->ports = NULL;
151 client->engine = NULL;
152 client->control = NULL;
153 client->thread_ok = FALSE;
154 client->first_active = TRUE;
155 client->on_shutdown = NULL;
156 client->n_port_types = 0;
157 client->port_segment = NULL;
158
159 return client;
160 }
161
162 jack_client_t *
163 jack_client_alloc_internal (jack_client_control_t *cc, jack_engine_t* engine)
164 {
165 jack_client_t* client;
166
167 client = jack_client_alloc ();
168
169 client->control = cc;
170 client->engine = engine->control;
171
172 client->n_port_types = client->engine->n_port_types;
173 client->port_segment = &engine->port_segment[0];
174
175 return client;
176 }
177
178 static void
179 jack_client_free (jack_client_t *client)
180 {
181 if (client->pollfd) {
182 free (client->pollfd);
183 }
184
185 free (client);
186 }
187
188 void
189 jack_client_invalidate_port_buffers (jack_client_t *client)
190 {
191 JSList *node;
192 jack_port_t *port;
193
194 /* This releases all local memory owned by input ports
195 and sets the buffer pointer to NULL. This will cause
196 jack_port_get_buffer() to reallocate space for the
197 buffer on the next call (if there is one).
198 */
199
200 for (node = client->ports; node; node = jack_slist_next (node)) {
201 port = (jack_port_t *) node->data;
202
203 if (port->shared->flags & JackPortIsInput) {
204 if (port->mix_buffer) {
205 jack_pool_release (port->mix_buffer);
206 port->mix_buffer = NULL;
207 }
208 }
209 }
210 }
211
212 int
213 jack_client_handle_port_connection (jack_client_t *client, jack_event_t *event)
214
215 {
216 jack_port_t *control_port;
217 jack_port_t *other;
218 JSList *node;
219
220 switch (event->type) {
221 case PortConnected:
222 other = jack_port_new (client, event->y.other_id, client->engine);
223 control_port = jack_port_by_id (client, event->x.self_id);
224 pthread_mutex_lock (&control_port->connection_lock);
225 control_port->connections = jack_slist_prepend (control_port->connections, (void*)other);
226 pthread_mutex_unlock (&control_port->connection_lock);
227 break;
228
229 case PortDisconnected:
230 control_port = jack_port_by_id (client, event->x.self_id);
231
232 pthread_mutex_lock (&control_port->connection_lock);
233
234 for (node = control_port->connections; node; node = jack_slist_next (node)) {
235
236 other = (jack_port_t *) node->data;
237
238 if (other->shared->id == event->y.other_id) {
239 control_port->connections = jack_slist_remove_link (control_port->connections, node);
240 jack_slist_free_1 (node);
241 free (other);
242 break;
243 }
244 }
245
246 pthread_mutex_unlock (&control_port->connection_lock);
247 break;
248
249 default:
250 /* impossible */
251 break;
252 }
253
254 return 0;
255 }
256
257 static int
258 jack_handle_reorder (jack_client_t *client, jack_event_t *event)
259 {
260 char path[PATH_MAX+1];
261
262 if (client->graph_wait_fd >= 0) {
263 DEBUG ("closing graph_wait_fd==%d", client->graph_wait_fd);
264 close (client->graph_wait_fd);
265 client->graph_wait_fd = -1;
266 }
267
268 if (client->graph_next_fd >= 0) {
269 DEBUG ("closing graph_next_fd==%d", client->graph_next_fd);
270 close (client->graph_next_fd);
271 client->graph_next_fd = -1;
272 }
273
274 sprintf (path, "%s-%" PRIu32, client->fifo_prefix, event->x.n);
275
276 if ((client->graph_wait_fd = open (path, O_RDONLY|O_NONBLOCK)) < 0) {
277 jack_error ("cannot open specified fifo [%s] for reading (%s)", path, strerror (errno));
278 return -1;
279 }
280
281
282 DEBUG ("opened new graph_wait_fd %d (%s)", client->graph_wait_fd, path);
283
284 sprintf (path, "%s-%" PRIu32, client->fifo_prefix, event->x.n+1);
285
286 if ((client->graph_next_fd = open (path, O_WRONLY|O_NONBLOCK)) < 0) {
287 jack_error ("cannot open specified fifo [%s] for writing (%s)", path, strerror (errno));
288 return -1;
289 }
290
291 DEBUG ("opened new graph_next_fd %d (%s)", client->graph_next_fd, path);
292
293 /* If the client registered its own callback for graph order events,
294 execute it now.
295 */
296
297 if (client->control->graph_order) {
298 client->control->graph_order (client->control->graph_order_arg);
299 }
300
301 return 0;
302 }
303
304 static int
305 server_connect (int which)
306 {
307 int fd;
308 struct sockaddr_un addr;
309
310 if ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) {
311 jack_error ("cannot create client socket (%s)", strerror (errno));
312 return -1;
313 }
314
315 addr.sun_family = AF_UNIX;
316 snprintf (addr.sun_path, sizeof (addr.sun_path) - 1, "%s/jack_%d", jack_server_dir, which);
317
318 if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
319 jack_error ("cannot connect to jack server", strerror (errno));
320 close (fd);
321 return -1;
322 }
323
324 return fd;
325 }
326
327 static int
328 server_event_connect (jack_client_t *client)
329 {
330 int fd;
331 struct sockaddr_un addr;
332 jack_client_connect_ack_request_t req;
333 jack_client_connect_ack_result_t res;
334
335 if ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) {
336 jack_error ("cannot create client event socket (%s)", strerror (errno));
337 return -1;
338 }
339
340 addr.sun_family = AF_UNIX;
341 snprintf (addr.sun_path, sizeof (addr.sun_path) - 1, "%s/jack_ack_0", jack_server_dir);
342
343 if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
344 jack_error ("cannot connect to jack server for events", strerror (errno));
345 close (fd);
346 return -1;
347 }
348
349 req.client_id = client->control->id;
350
351 if (write (fd, &req, sizeof (req)) != sizeof (req)) {
352 jack_error ("cannot write event connect request to server (%s)", strerror (errno));
353 close (fd);
354 return -1;
355 }
356
357 if (read (fd, &res, sizeof (res)) != sizeof (res)) {
358 jack_error ("cannot read event connect result from server (%s)", strerror (errno));
359 close (fd);
360 return -1;
361 }
362
363 if (res.status != 0) {
364 close (fd);
365 return -1;
366 }
367
368 return fd;
369 }
370
371 static int
372 jack_request_client (ClientType type, const char* client_name, const char* so_name,
373 const char* so_data, jack_client_connect_result_t *res, int *req_fd)
374 {
375 jack_client_connect_request_t req;
376
377 *req_fd = -1;
378
379 memset (&req, 0, sizeof (req));
380
381 if (strlen (client_name) > sizeof (req.name) - 1) {
382 jack_error ("\"%s\" is too long to be used as a JACK client name.\n"
383 "Please use %lu characters or less.",
384 client_name, sizeof (req.name) - 1);
385 return -1;
386 }
387
388 if (strlen (so_name) > sizeof (req.object_path) - 1) {
389 jack_error ("\"%s\" is too long to be used as a JACK shared object name.\n"
390 "Please use %lu characters or less.",
391 so_name, sizeof (req.object_path) - 1);
392 return -1;
393 }
394
395 if (strlen (so_data) > sizeof (req.object_data) - 1) {
396 jack_error ("\"%s\" is too long to be used as a JACK shared object data string.\n"
397 "Please use %lu characters or less.",
398 so_data, sizeof (req.object_data) - 1);
399 return -1;
400 }
401
402 if ((*req_fd = server_connect (0)) < 0) {
403 jack_error ("cannot connect to default JACK server");
404 goto fail;
405 }
406
407 req.load = TRUE;
408 req.type = type;
409 snprintf (req.name, sizeof (req.name), "%s", client_name);
410 snprintf (req.object_path, sizeof (req.object_path), "%s", so_name);
411 snprintf (req.object_data, sizeof (req.object_data), "%s", so_data);
412
413 if (write (*req_fd, &req, sizeof (req)) != sizeof (req)) {
414 jack_error ("cannot send request to jack server (%s)", strerror (errno));
415 goto fail;
416 }
417
418 if (read (*req_fd, res, sizeof (*res)) != sizeof (*res)) {
419
420 if (errno == 0) {
421 /* server shut the socket */
422 jack_error ("could not attach as client (duplicate client name?)");
423 goto fail;
424 }
425
426 jack_error ("cannot read response from jack server (%s)", strerror (errno));
427 goto fail;
428 }
429
430 if (res->status) {
431 jack_error ("could not attach as client (duplicate client name?)");
432 goto fail;
433 }
434
435 if (res->protocol_v != jack_protocol_version){
436 jack_error ("application linked against too wrong of a version of libjack.");
437 goto fail;
438 }
439
440 switch (type) {
441 case ClientDriver:
442 case ClientInternal:
443 close (*req_fd);
444 *req_fd = -1;
445 break;
446
447 default:
448 break;
449 }
450
451 return 0;
452
453 fail:
454 if (*req_fd >= 0) {
455 close (*req_fd);
456 *req_fd = -1;
457 }
458 return -1;
459 }
460
461 int
462 jack_attach_port_segment (jack_client_t *client, jack_port_type_id_t ptid)
463 {
464 /* Lookup, attach and register the port/buffer segments in use
465 * right now.
466 */
467
468 if (client->control->type != ClientExternal) {
469 jack_error("Only external clients need attach port segments");
470 abort();
471 }
472
473 /* make sure we have space to store the port
474 segment information.
475 */
476
477 if (ptid >= client->n_port_types) {
478
479 client->port_segment = (jack_shm_info_t*)
480 realloc (client->port_segment,
481 sizeof (jack_shm_info_t) * (ptid+1));
482
483 memset (&client->port_segment[client->n_port_types],
484 0,
485 sizeof (jack_shm_info_t) *
486 (ptid - client->n_port_types));
487
488 client->n_port_types = ptid + 1;
489
490 } else {
491
492 /* release any previous segment */
493
494 jack_release_shm (&client->port_segment[ptid]);
495 }
496
497 /* get the index into the shm registry */
498
499 client->port_segment[ptid].index =
500 client->engine->port_types[ptid].shm_registry_index;
501
502 /* attach the relevant segment */
503
504 if (jack_attach_shm (&client->port_segment[ptid])) {
505 jack_error ("cannot attach port segment shared memory"
506 " (%s)", strerror (errno));
507 return -1;
508 }
509
510 /* The first chunk of the audio port segment will be set by
511 * the engine to be a zero-filled buffer. This hasn't been
512 * done yet, but it will happen before the process cycle
513 * (re)starts.
514 */
515
516 if (ptid == JACK_AUDIO_PORT_TYPE) {
517 jack_zero_filled_buffer =
518 jack_shm_addr (&client->port_segment[ptid]);
519 }
520
521 return 0;
522 }
523
524 jack_client_t *
525 jack_client_new (const char *client_name)
526 {
527 int req_fd = -1;
528 int ev_fd = -1;
529 jack_client_connect_result_t res;
530 jack_client_t *client;
531 jack_port_type_id_t ptid;
532
533 /* external clients need this initialized; internal clients
534 will use the setup in the server's address space.
535 */
536 jack_init_time ();
537 jack_initialize_shm ();
538
539 if (jack_request_client (ClientExternal, client_name, "", "",
540 &res, &req_fd)) {
541 return NULL;
542 }
543
544 client = jack_client_alloc ();
545
546 strcpy (client->fifo_prefix, res.fifo_prefix);
547 client->request_fd = req_fd;
548
549 client->pollfd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
550 client->pollfd[1].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
551
552 /* attach the engine control/info block */
553 client->engine_shm = res.engine_shm;
554 if (jack_attach_shm (&client->engine_shm)) {
555 jack_error ("cannot attached engine control shared memory"
556 " segment");
557 goto fail;
558 }
559
560 client->engine = (jack_control_t *) jack_shm_addr (&client->engine_shm);
561
562 /* now attach the client control block */
563 client->control_shm = res.client_shm;
564 if (jack_attach_shm (&client->control_shm)) {
565 jack_error ("cannot attached client control shared memory"
566 " segment");
567 goto fail;
568 }
569
570 client->control = (jack_client_control_t *) jack_shm_addr (&client->control_shm);
571
572 /* nobody else needs to access this shared memory any more, so
573 destroy it. because we have our own attachment to it, it won't
574 vanish till we exit (and release it).
575 */
576 jack_destroy_shm (&client->control_shm);
577
578 client->n_port_types = client->engine->n_port_types;
579 client->port_segment = (jack_shm_info_t *) malloc (sizeof (jack_shm_info_t) *
580 client->n_port_types);
581
582 for (ptid = 0; ptid < client->n_port_types; ++ptid) {
583 client->port_segment[ptid].index =
584 client->engine->port_types[ptid].shm_registry_index;
585 jack_attach_port_segment (client, ptid);
586 }
587
588 /* set up the client so that it does the right thing for an
589 * external client
590 */
591 client->control->deliver_request = oop_client_deliver_request;
592 client->control->deliver_arg = client;
593
594 if ((ev_fd = server_event_connect (client)) < 0) {
595 jack_error ("cannot connect to server for event stream (%s)",
596 strerror (errno));
597 goto fail;
598 }
599
600 client->event_fd = ev_fd;
601
602 #if defined(__APPLE__) && defined(__POWERPC__)
603 /* specific resources for server/client real-time thread
604 * communication */
605 client->clienttask = mach_task_self();
606
607 if (task_get_bootstrap_port(client->clienttask, &client->bp)){
608 jack_error ("Can't find bootstrap port");
609 goto fail;
610 }
611
612 if (allocate_mach_clientport(client, res.portnum) < 0) {
613 jack_error("Can't allocate mach port");
614 goto fail;
615 };
616 #endif
617 return client;
618
619 fail:
620 if (client->engine) {
621 jack_release_shm (&client->engine_shm);
622 client->engine = 0;
623 }
624 if (client->control) {
625 jack_release_shm (&client->control_shm);
626 client->control = 0;
627 }
628 if (req_fd >= 0) {
629 close (req_fd);
630 }
631 if (ev_fd >= 0) {
632 close (ev_fd);
633 }
634
635 return 0;
636 }
637
638 int
639 jack_internal_client_new (const char *client_name, const char *so_name, const char *so_data)
640 {
641 jack_client_connect_result_t res;
642 int req_fd;
643
644 return jack_request_client (ClientInternal, client_name, so_name, so_data, &res, &req_fd);
645 }
646
647 void
648 jack_internal_client_close (const char *client_name)
649 {
650 jack_client_connect_request_t req;
651 int fd;
652
653 req.load = FALSE;
654 snprintf (req.name, sizeof (req.name), "%s", client_name);
655
656 if ((fd = server_connect (0)) < 0) {
657 jack_error ("cannot connect to default JACK server.");
658 return;
659 }
660
661 if (write (fd, &req, sizeof (req)) != sizeof(req)) {
662 jack_error ("cannot deliver ClientUnload request to JACK server.");
663 }
664
665 /* no response to this request */
666
667 close (fd);
668 return;
669 }
670
671 int
672 jack_drop_real_time_scheduling (pthread_t thread)
673 {
674 struct sched_param rtparam;
675 int x;
676
677 memset (&rtparam, 0, sizeof (rtparam));
678 rtparam.sched_priority = 0;
679
680 if ((x = pthread_setschedparam (thread, SCHED_OTHER, &rtparam)) != 0) {
681 jack_error ("cannot switch to normal scheduling priority(%s)\n", strerror (errno));
682 return -1;
683 }
684 return 0;
685 }
686
687 int
688 jack_acquire_real_time_scheduling (pthread_t thread, int priority)
689 {
690 struct sched_param rtparam;
691 int x;
692
693 memset (&rtparam, 0, sizeof (rtparam));
694 rtparam.sched_priority = priority;
695
696 if ((x = pthread_setschedparam (thread, SCHED_FIFO, &rtparam)) != 0) {
697 jack_error ("cannot use real-time scheduling (FIFO/%d) "
698 "(%d: %s)", rtparam.sched_priority, x,
699 strerror (x));
700 return -1;
701 }
702 return 0;
703 }
704
705 int
706 jack_set_freewheel (jack_client_t* client, int onoff)
707 {
708 jack_request_t request;
709 request.type = onoff ? FreeWheel : StopFreeWheel;
710 return jack_client_deliver_request (client, &request);
711 }
712
713 void
714 jack_start_freewheel (jack_client_t* client)
715 {
716 jack_client_control_t *control = client->control;
717
718 if (client->engine->real_time) {
719 jack_drop_real_time_scheduling (client->thread);
720 }
721
722 if (control->freewheel_cb) {
723 control->freewheel_cb (1, control->freewheel_arg);
724 }
725 }
726
727 void
728 jack_stop_freewheel (jack_client_t* client)
729 {
730 jack_client_control_t *control = client->control;
731
732 if (control->freewheel_cb) {
733 control->freewheel_cb (0, control->freewheel_arg);
734 }
735
736 if (client->engine->real_time) {
737 jack_acquire_real_time_scheduling (client->thread,
738 client->engine->client_priority);
739 }
740 }
741
742 static void *
743 jack_client_thread (void *arg)
744 {
745 jack_client_t *client = (jack_client_t *) arg;
746 jack_client_control_t *control = client->control;
747 jack_event_t event;
748 char status = 0;
749 char c;
750 int err = 0;
751
752 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
753
754 pthread_mutex_lock (&client_lock);
755 client->thread_ok = TRUE;
756 client->thread_id = pthread_self();
757 pthread_cond_signal (&client_ready);
758 pthread_mutex_unlock (&client_lock);
759
760 client->control->pid = getpid();
761 client->control->pgrp = getpgrp();
762
763 DEBUG ("client thread is now running");
764
765 while (err == 0) {
766 if (client->engine->engine_ok == 0) {
767 jack_error ("engine unexpectedly shutdown; "
768 "thread exiting\n");
769 if (client->on_shutdown) {
770 client->on_shutdown (client->on_shutdown_arg);
771 }
772 pthread_exit (0);
773
774 }
775
776 DEBUG ("client polling on event_fd and graph_wait_fd...");
777
778 if (poll (client->pollfd, client->pollmax, 1000) < 0) {
779 if (errno == EINTR) {
780 fprintf (stderr, "poll interrupted\n");
781 continue;
782 }
783 jack_error ("poll failed in client (%s)",
784 strerror (errno));
785 status = -1;
786 break;
787 }
788
789 /* get an accurate timestamp on waking from poll for a
790 * process() cycle.
791 */
792
793 if (client->pollfd[1].revents & POLLIN) {
794 control->awake_at = jack_get_microseconds();
795 }
796
797 DEBUG ("pfd[0].revents = 0x%x pfd[1].revents = 0x%x",
798 client->pollfd[0].revents,
799 client->pollfd[1].revents);
800
801 pthread_testcancel();
802
803 if ((client->pollfd[0].revents & ~POLLIN) ||
804 client->control->dead) {
805 goto zombie;
806 }
807
808 if (client->pollfd[0].revents & POLLIN) {
809
810 DEBUG ("client receives an event, "
811 "now reading on event fd");
812
813 /* server has sent us an event. process the
814 * event and reply */
815
816 if (read (client->event_fd, &event, sizeof (event))
817 != sizeof (event)) {
818 jack_error ("cannot read server event (%s)",
819 strerror (errno));
820 err++;
821 break;
822 }
823
824 status = 0;
825
826 switch (event.type) {
827 case PortRegistered:
828 if (control->port_register) {
829 control->port_register
830 (event.x.port_id, TRUE,
831 control->port_register_arg);
832 }
833 break;
834
835 case PortUnregistered:
836 if (control->port_register) {
837 control->port_register
838 (event.x.port_id, FALSE,
839 control->port_register_arg);
840 }
841 break;
842
843 case GraphReordered:
844 status = jack_handle_reorder (client, &event);
845 break;
846
847 case PortConnected:
848 case PortDisconnected:
849 status = jack_client_handle_port_connection
850 (client, &event);
851 break;
852
853 case BufferSizeChange:
854 jack_client_invalidate_port_buffers (client);
855
856 if (control->bufsize) {
857 status = control->bufsize
858 (control->nframes,
859 control->bufsize_arg);
860 }
861 break;
862
863 case SampleRateChange:
864 if (control->srate) {
865 status = control->srate
866 (control->nframes,
867 control->srate_arg);
868 }
869 break;
870
871 case XRun:
872 if (control->xrun) {
873 status = control->xrun
874 (control->xrun_arg);
875 }
876 break;
877
878 case AttachPortSegment:
879 jack_attach_port_segment (client, event.y.ptid);
880 break;
881
882 case StartFreewheel:
883 jack_start_freewheel (client);
884 break;
885
886 case StopFreewheel:
887 jack_stop_freewheel (client);
888 break;
889 }
890
891 DEBUG ("client has dealt with the event, writing "
892 "response on event fd");
893
894 if (write (client->event_fd, &status, sizeof (status))
895 != sizeof (status)) {
896 jack_error ("cannot send event response to "
897 "engine (%s)", strerror (errno));
898 err++;
899 break;
900 }
901 }
902
903 if (client->pollfd[1].revents & ~POLLIN) {
904 goto zombie;
905 }
906
907 if (client->pollfd[1].revents & POLLIN) {
908
909 #ifdef WITH_TIMESTAMPS
910 jack_reset_timestamps ();
911 #endif
912
913 DEBUG ("client %d signalled at %" PRIu64
914 ", awake for process at %" PRIu64
915 " (delay = %" PRIu64
916 " usecs) (wakeup on graph_wait_fd==%d)",
917 getpid(),
918 control->signalled_at,
919 control->awake_at,
920 control->awake_at - control->signalled_at,
921 client->pollfd[1].fd);
922
923 control->state = Running;
924
925 if (control->sync_cb)
926 jack_call_sync_client (client);
927
928 if (control->process) {
929 if (control->process (control->nframes,
930 control->process_arg)
931 == 0) {
932 control->state = Finished;
933 }
934 } else {
935 control->state = Finished;
936 }
937
938 if (control->timebase_cb)
939 jack_call_timebase_master (client);
940
941 control->finished_at = jack_get_microseconds();
942
943 #ifdef WITH_TIMESTAMPS
944 jack_timestamp ("finished");
945 #endif
946 /* pass the execution token along */
947
948 DEBUG ("client finished processing at %" PRIu64
949 " (elapsed = %" PRIu64
950 " usecs), writing on graph_next_fd==%d",
951 control->finished_at,
952 control->finished_at - control->awake_at,
953 client->graph_next_fd);
954
955 if (write (client->graph_next_fd, &c, sizeof (c))
956 != sizeof (c)) {
957 jack_error ("cannot continue execution of the "
958 "processing graph (%s)",
959 strerror(errno));
960 err++;
961 break;
962 }
963
964 DEBUG ("client sent message to next stage by %" PRIu64
965 ", client reading on graph_wait_fd==%d",
966 jack_get_microseconds(), client->graph_wait_fd);
967
968 #ifdef WITH_TIMESTAMPS
969 jack_timestamp ("read pending byte from wait");
970 #endif
971 DEBUG("reading cleanup byte from pipe\n");
972
973 if ((read (client->graph_wait_fd, &c, sizeof (c))
974 != sizeof (c))) {
975 DEBUG ("WARNING: READ FAILED!");
976 #if 0
977 jack_error ("cannot complete execution of the "
978 "processing graph (%s)",
979 strerror(errno));
980 err++;
981 break;
982 #endif
983 }
984
985 /* check if we were killed during the process
986 * cycle (or whatever) */
987 if (client->control->dead) {
988 goto zombie;
989 }
990
991 DEBUG("process cycle fully complete\n");
992
993 #ifdef WITH_TIMESTAMPS
994 jack_timestamp ("read done");
995 jack_dump_timestamps (stdout);
996 #endif
997
998 }
999 }
1000
1001 return (void *) ((intptr_t)err);
1002
1003 zombie:
1004 if (client->on_shutdown) {
1005 jack_error ("zombified - calling shutdown handler");
1006 client->on_shutdown (client->on_shutdown_arg);
1007 } else {
1008 jack_error ("zombified - exiting from JACK");
1009 jack_client_close (client);
1010 /* Need a fix : possibly make client crash if
1011 * zombified without shutdown handler
1012 */
1013 }
1014
1015 pthread_exit (0);
1016 /*NOTREACHED*/
1017 return 0;
1018 }
1019
1020
1021 #if defined(__APPLE__) && defined(__POWERPC__)
1022 /* real-time thread : separated from the normal client thread, it will
1023 * communicate with the server using fast mach RPC mechanism */
1024
1025 static void *
1026 jack_client_process_thread (void *arg)
1027 {
1028 jack_client_t *client = (jack_client_t *) arg;
1029 jack_client_control_t *control = client->control;
1030 int err = 0;
1031
1032 client->control->pid = getpid();
1033 DEBUG ("client process thread is now running");
1034
1035 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
1036
1037 while (err == 0) {
1038
1039 if (jack_client_suspend(client) < 0) {
1040 pthread_exit (0);
1041 }
1042
1043 control->awake_at = jack_get_microseconds();
1044
1045 DEBUG ("client resumed");
1046
1047 control->state = Running;
1048
1049 if (control->process) {
1050 if (control->process (control->nframes,
1051 control->process_arg) == 0) {
1052 control->state = Finished;
1053 }
1054 } else {
1055 control->state = Finished;
1056 }
1057
1058 control->finished_at = jack_get_microseconds();
1059
1060 #ifdef WITH_TIMESTAMPS
1061 jack_timestamp ("finished");
1062 #endif
1063 DEBUG ("client finished processing at %Lu (elapsed = %f usecs)",
1064 control->finished_at, ((float)(control->finished_at - control->awake_at)));
1065
1066 /* check if we were killed during the process cycle (or whatever) */
1067
1068 if (client->control->dead) {
1069 jack_error ("jack_client_process_thread : client->control->dead");
1070 goto zombie;
1071 }
1072
1073 DEBUG("process cycle fully complete\n");
1074
1075 }
1076
1077 return (void *) ((intptr_t)err);
1078
1079 zombie:
1080
1081 jack_error ("jack_client_process_thread : zombified");
1082
1083 if (client->on_shutdown) {
1084 jack_error ("zombified - calling shutdown handler");
1085 client->on_shutdown (client->on_shutdown_arg);
1086 } else {
1087 jack_error ("zombified - exiting from JACK");
1088 jack_client_close (client); /* Need a fix : possibly make client crash if zombified without shutdown handler */
1089 }
1090
1091 pthread_exit (0);
1092 /*NOTREACHED*/
1093 return 0;
1094 }
1095 #endif
1096
1097 static int
1098 jack_start_thread (jack_client_t *client)
1099
1100 {
1101 pthread_attr_t *attributes = 0;
1102 #ifdef USE_CAPABILITIES
1103 int policy = SCHED_OTHER;
1104 struct sched_param client_param, temp_param;
1105 #endif
1106
1107 if (client->engine->real_time) {
1108
1109 /* Get the client thread to run as an RT-FIFO
1110 scheduled thread of appropriate priority.
1111 */
1112
1113 struct sched_param rt_param;
1114
1115 attributes = (pthread_attr_t *)
1116 malloc (sizeof (pthread_attr_t));
1117
1118 pthread_attr_init (attributes);
1119
1120 if (pthread_attr_setschedpolicy (attributes, SCHED_FIFO)) {
1121 jack_error ("cannot set FIFO scheduling class for RT "
1122 "thread");
1123 return -1;
1124 }
1125
1126 if (pthread_attr_setscope (attributes, PTHREAD_SCOPE_SYSTEM)) {
1127 jack_error ("Cannot set scheduling scope for RT "
1128 "thread");
1129 return -1;
1130 }
1131
1132 memset (&rt_param, 0, sizeof (rt_param));
1133 rt_param.sched_priority = client->engine->client_priority;
1134
1135 if (pthread_attr_setschedparam (attributes, &rt_param)) {
1136 jack_error ("Cannot set scheduling priority for RT "
1137 "thread (%s)", strerror (errno));
1138 return -1;
1139 }
1140
1141 #if defined(__APPLE__) && defined(__POWERPC__)
1142 // To be implemented
1143 #else
1144 if (mlockall (MCL_CURRENT | MCL_FUTURE) != 0) {
1145 jack_error ("cannot lock down memory for RT thread (%s)",
1146 strerror (errno));
1147 #ifdef ENSURE_MLOCK
1148 return -1;
1149 #endif /* ENSURE_MLOCK */
1150 }
1151 #endif
1152
1153 }
1154
1155 if (pthread_create (&client->thread, attributes,
1156 jack_client_thread, client)) {
1157 #ifdef USE_CAPABILITIES
1158 if (client->engine->real_time) {
1159 /* we are probably dealing with a broken glibc so try
1160 to work around the bug, see below for more details
1161 */
1162 goto capabilities_workaround;
1163 }
1164 #endif
1165 return -1;
1166 }
1167
1168 #if defined(__APPLE__) && defined(__POWERPC__)
1169 /* a spcial real-time thread to call the "process"
1170 * callback. It will communicate with the server using fast
1171 * mach RPC mechanism */
1172 if (pthread_create (&client->process_thread, attributes,
1173 jack_client_process_thread, client)) {
1174 jack_error("pthread_create failed for process_thread \n");
1175 return -1;
1176 }
1177 if (client->engine->real_time){
1178 /* time constraint thread */
1179 setThreadToPriority(client->process_thread, 96, true, 10000000);
1180 }else{
1181 /* fixed priority thread */
1182 setThreadToPriority(client->process_thread, 63, true, 10000000);
1183 }
1184 #endif
1185
1186 return 0;
1187
1188 #ifdef USE_CAPABILITIES
1189
1190 /* we get here only with engine running realtime and capabilities */
1191
1192 capabilities_workaround:
1193
1194 /* the version of glibc I've played with has a bug that makes
1195 that code fail when running under a non-root user but with the
1196 proper realtime capabilities (in short, pthread_attr_setschedpolicy
1197 does not check for capabilities, only for the uid being
1198 zero). Newer versions apparently have this fixed. This
1199 workaround temporarily switches the client thread to the
1200 proper scheduler and priority, then starts the realtime
1201 thread so that it can inherit them and finally switches the
1202 client thread back to what it was before. Sigh. For ardour
1203 I have to check again and switch the thread explicitly to
1204 realtime, don't know why or how to debug - nando
1205 */
1206
1207 /* get current scheduler and parameters of the client process */
1208 if ((policy = sched_getscheduler (0)) < 0) {
1209 jack_error ("Cannot get current client scheduler: %s",
1210 strerror(errno));
1211 return -1;
1212 }
1213 memset (&client_param, 0, sizeof (client_param));
1214 if (sched_getparam (0, &client_param)) {
1215 jack_error ("Cannot get current client scheduler "
1216 "parameters: %s", strerror(errno));
1217 return -1;
1218 }
1219
1220 /* temporarily change the client process to SCHED_FIFO so that
1221 the realtime thread can inherit the scheduler and priority
1222 */
1223 memset (&temp_param, 0, sizeof (temp_param));
1224 temp_param.sched_priority = client->engine->client_priority;
1225 if (sched_setscheduler(0, SCHED_FIFO, &temp_param)) {
1226 jack_error ("Cannot temporarily set client to RT scheduler:"
1227 " %s", strerror(errno));
1228 return -1;
1229 }
1230
1231 /* prepare the attributes for the realtime thread */
1232 attributes = (pthread_attr_t *) malloc (sizeof (pthread_attr_t));
1233 pthread_attr_init (attributes);
1234 if (pthread_attr_setscope (attributes, PTHREAD_SCOPE_SYSTEM)) {
1235 sched_setscheduler (0, policy, &client_param);
1236 jack_error ("Cannot set scheduling scope for RT thread");
1237 return -1;
1238 }
1239 if (pthread_attr_setinheritsched (attributes, PTHREAD_INHERIT_SCHED)) {
1240 sched_setscheduler (0, policy, &client_param);
1241 jack_error ("Cannot set scheduler inherit policy for RT "
1242 "thread");
1243 return -1;
1244 }
1245
1246 /* create the RT thread */
1247 if (pthread_create (&client->thread, attributes,
1248 jack_client_thread, client)) {
1249 sched_setscheduler (0, policy, &client_param);
1250 return -1;
1251 }
1252
1253 /* return the client process to the scheduler it was in before */
1254 if (sched_setscheduler (0, policy, &client_param)) {
1255 jack_error ("Cannot reset original client scheduler: %s",
1256 strerror(errno));
1257 return -1;
1258 }
1259
1260 /* check again... inheritance of policy and priority works in
1261 jack_simple_client but not in ardour! So I check again and
1262 force the policy if it is not set correctly. This does not
1263 really really work either, the manager thread of the
1264 linuxthreads implementation is left running with
1265 SCHED_OTHER, that is presumably very bad.
1266 */
1267 memset (&client_param, 0, sizeof (client_param));
1268 if (pthread_getschedparam(client->thread, &policy,
1269 &client_param) == 0) {
1270 if (policy != SCHED_FIFO) {
1271 memset (&client_param, 0, sizeof (client_param));
1272 client_param.sched_priority =
1273 client->engine->client_priority;
1274 if (pthread_setschedparam (client->thread, SCHED_FIFO,
1275 &client_param)) {
1276 jack_error ("Cannot set (again) FIFO scheduling"
1277 " class for RT thread\n");
1278 return -1;
1279 }
1280 }
1281 }
1282 return 0;
1283 #endif
1284 }
1285
1286 int
1287 jack_activate (jack_client_t *client)
1288 {
1289 jack_request_t req;
1290
1291 /* we need to scribble on our stack to ensure that its memory
1292 * pages are actually mapped (more important for mlockall(2)
1293 * usage in jack_start_thread())
1294 */
1295
1296 #if defined(__APPLE__) && defined(__POWERPC__)
1297 /* a bigger stack makes the application crash... */
1298 #define BIG_ENOUGH_STACK 10000
1299 #else
1300 #define BIG_ENOUGH_STACK 1048576
1301 #endif
1302
1303 char buf[BIG_ENOUGH_STACK];
1304 int i;
1305
1306 for (i = 0; i < BIG_ENOUGH_STACK; i++) {
1307 buf[i] = (char) (i & 0xff);
1308 }
1309
1310 #undef BIG_ENOUGH_STACK
1311
1312 if (client->control->type == ClientInternal ||
1313 client->control->type == ClientDriver) {
1314 goto startit;
1315 }
1316
1317 /* get the pid of the client process to pass it to engine */
1318
1319 client->control->pid = getpid ();
1320
1321 #ifdef USE_CAPABILITIES
1322
1323 if (client->engine->has_capabilities != 0 &&
1324 client->control->pid != 0 && client->engine->real_time != 0) {
1325
1326 /* we need to ask the engine for realtime capabilities
1327 before trying to start the realtime thread
1328 */
1329
1330 req.type = SetClientCapabilities;
1331 req.x.client_id = client->control->id;
1332
1333 jack_client_deliver_request (client, &req);
1334
1335 if (req.status) {
1336
1337 /* what to do? engine is running realtime, it
1338 is using capabilities and has them
1339 (otherwise we would not get an error
1340 return) but for some reason it could not
1341 give the client the required capabilities,
1342 so for now downgrade the client so that it
1343 still runs, albeit non-realtime - nando
1344 */
1345
1346 jack_error ("could not receive realtime capabilities, "
1347 "client will run non-realtime");
1348 /* XXX wrong, this is a property of the engine
1349 client->engine->real_time = 0;
1350 */
1351 }
1352 }
1353 #endif
1354
1355 if (client->first_active) {
1356
1357 pthread_mutex_init (&client_lock, NULL);
1358 pthread_cond_init (&client_ready, NULL);
1359
1360 pthread_mutex_lock (&client_lock);
1361
1362 if (jack_start_thread (client)) {
1363 pthread_mutex_unlock (&client_lock);
1364 return -1;
1365 }
1366
1367 pthread_cond_wait (&client_ready, &client_lock);
1368 pthread_mutex_unlock (&client_lock);
1369
1370 if (!client->thread_ok) {
1371 jack_error ("could not start client thread");
1372 return -1;
1373 }
1374
1375 client->first_active = FALSE;
1376 }
1377
1378 startit:
1379
1380 req.type = ActivateClient;
1381 req.x.client_id = client->control->id;
1382
1383 return jack_client_deliver_request (client, &req);
1384 }
1385
1386 int
1387 jack_deactivate (jack_client_t *client)
1388
1389 {
1390 jack_request_t req;
1391
1392 req.type = DeactivateClient;
1393 req.x.client_id = client->control->id;
1394
1395 return jack_client_deliver_request (client, &req);
1396 }
1397
1398 int
1399 jack_client_close (jack_client_t *client)
1400 {
1401 JSList *node;
1402 void *status;
1403
1404 if (client->control->active) {
1405 jack_deactivate (client);
1406 }
1407
1408 if (client->control->type == ClientExternal) {
1409
1410 /* stop the thread that communicates with the jack
1411 * server, only if it was actually running
1412 */
1413
1414 if (client->thread_ok){
1415 pthread_cancel (client->thread);
1416 pthread_join (client->thread, &status);
1417 }
1418
1419 if (client->control) {
1420 jack_release_shm (&client->control_shm);
1421 client->control = NULL;
1422 }
1423 if (client->engine) {
1424 jack_release_shm (&client->engine_shm);
1425 client->engine = NULL;
1426 }
1427
1428 if (client->port_segment) {
1429 jack_port_type_id_t ptid;
1430 for (ptid = 0; ptid < client->n_port_types; ++ptid) {
1431 jack_release_shm (&client->port_segment[ptid]);
1432 }
1433 free (client->port_segment);
1434 client->port_segment = NULL;
1435 }
1436
1437 if (client->graph_wait_fd) {
1438 close (client->graph_wait_fd);
1439 }
1440
1441 if (client->graph_next_fd) {
1442 close (client->graph_next_fd);
1443 }
1444
1445 close (client->event_fd);
1446 close (client->request_fd);
1447 }
1448
1449 for (node = client->ports; node; node = jack_slist_next (node)) {
1450 free (node->data);
1451 }
1452 jack_slist_free (client->ports);
1453 jack_client_free (client);
1454
1455 return 0;
1456 }
1457
1458 int
1459 jack_is_realtime (jack_client_t *client)
1460 {
1461 return client->engine->real_time;
1462 }
1463
1464 jack_nframes_t
1465 jack_get_buffer_size (jack_client_t *client)
1466 {
1467 return client->engine->buffer_size;
1468 }
1469
1470 int
1471 jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes)
1472 {
1473 #ifdef DO_BUFFER_RESIZE
1474 jack_request_t req;
1475
1476 req.type = SetBufferSize;
1477 req.x.nframes = nframes;
1478
1479 return jack_client_deliver_request (client, &req);
1480 #else
1481 return ENOSYS;
1482
1483 #endif /* DO_BUFFER_RESIZE */
1484 }
1485
1486 int
1487 jack_connect (jack_client_t *client, const char *source_port,
1488 const char *destination_port)
1489 {
1490 jack_request_t req;
1491
1492 req.type = ConnectPorts;
1493
1494 snprintf (req.x.connect.source_port,
1495 sizeof (req.x.connect.source_port), "%s", source_port);
1496 snprintf (req.x.connect.destination_port,
1497 sizeof (req.x.connect.destination_port),
1498 "%s", destination_port);
1499
1500 return jack_client_deliver_request (client, &req);
1501 }
1502
1503 int
1504 jack_port_disconnect (jack_client_t *client, jack_port_t *port)
1505 {
1506 jack_request_t req;
1507
1508 pthread_mutex_lock (&port->connection_lock);
1509
1510 if (port->connections == NULL) {
1511 pthread_mutex_unlock (&port->connection_lock);
1512 return 0;
1513 }
1514
1515 pthread_mutex_unlock (&port->connection_lock);
1516
1517 req.type = DisconnectPort;
1518 req.x.port_info.port_id = port->shared->id;
1519
1520 return jack_client_deliver_request (client, &req);
1521 }
1522
1523 int
1524 jack_disconnect (jack_client_t *client, const char *source_port,
1525 const char *destination_port)
1526 {
1527 jack_request_t req;
1528
1529 req.type = DisconnectPorts;
1530
1531 snprintf (req.x.connect.source_port,
1532 sizeof (req.x.connect.source_port), "%s", source_port);
1533 snprintf (req.x.connect.destination_port,
1534 sizeof (req.x.connect.destination_port),
1535 "%s", destination_port);
1536
1537 return jack_client_deliver_request (client, &req);
1538 }
1539
1540 void
1541 jack_set_error_function (void (*func) (const char *))
1542 {
1543 jack_error_callback = func;
1544 }
1545
1546
1547 int
1548 jack_set_graph_order_callback (jack_client_t *client,
1549 JackGraphOrderCallback callback, void *arg)
1550 {
1551 if (client->control->active) {
1552 jack_error ("You cannot set callbacks on an active client.");
1553 return -1;
1554 }
1555 client->control->graph_order = callback;
1556 client->control->graph_order_arg = arg;
1557 return 0;
1558 }
1559
1560 int jack_set_xrun_callback (jack_client_t *client,
1561 JackXRunCallback callback, void *arg)
1562 {
1563 if (client->control->active) {
1564 jack_error ("You cannot set callbacks on an active client.");
1565 return -1;
1566 }
1567
1568 client->control->xrun = callback;
1569 client->control->xrun_arg = arg;
1570 return 0;
1571 }
1572
1573 int
1574 jack_set_process_callback (jack_client_t *client,
1575 JackProcessCallback callback, void *arg)
1576
1577 {
1578 if (client->control->active) {
1579 jack_error ("You cannot set callbacks on an active client.");
1580 return -1;
1581 }
1582 client->control->process_arg = arg;
1583 client->control->process = callback;
1584 return 0;
1585 }
1586
1587 int
1588 jack_set_freewheel_callback (jack_client_t *client,
1589 JackFreewheelCallback callback, void *arg)
1590 {
1591 if (client->control->active) {
1592 jack_error ("You cannot set callbacks on an active client.");
1593 return -1;
1594 }
1595 client->control->freewheel_arg = arg;
1596 client->control->freewheel_cb = callback;
1597 return 0;
1598 }
1599
1600 int
1601 jack_set_buffer_size_callback (jack_client_t *client,
1602 JackBufferSizeCallback callback, void *arg)
1603 {
1604 client->control->bufsize_arg = arg;
1605 client->control->bufsize = callback;
1606 return 0;
1607 }
1608
1609 int
1610 jack_set_port_registration_callback(jack_client_t *client,
1611 JackPortRegistrationCallback callback,
1612 void *arg)
1613 {
1614 if (client->control->active) {
1615 jack_error ("You cannot set callbacks on an active client.");
1616 return -1;
1617 }
1618 client->control->port_register_arg = arg;
1619 client->control->port_register = callback;
1620 return 0;
1621 }
1622
1623 int
1624 jack_get_process_start_fd (jack_client_t *client)
1625 {
1626 /* once this has been called, the client thread
1627 does not sleep on the graph wait fd.
1628 */
1629
1630 client->pollmax = 1;
1631 return client->graph_wait_fd;
1632
1633 }
1634
1635 int
1636 jack_get_process_done_fd (jack_client_t *client)
1637 {
1638 return client->graph_next_fd;
1639 }
1640
1641
1642 void
1643 jack_on_shutdown (jack_client_t *client, void (*function)(void *arg), void *arg)
1644 {
1645 client->on_shutdown = function;
1646 client->on_shutdown_arg = arg;
1647 }
1648
1649 const char **
1650 jack_get_ports (jack_client_t *client,
1651 const char *port_name_pattern,
1652 const char *type_name_pattern,
1653 unsigned long flags)
1654 {
1655 jack_control_t *engine;
1656 const char **matching_ports;
1657 unsigned long match_cnt;
1658 jack_port_shared_t *psp;
1659 unsigned long i;
1660 regex_t port_regex;
1661 regex_t type_regex;
1662 int matching;
1663
1664 engine = client->engine;
1665
1666 if (port_name_pattern && port_name_pattern[0]) {
1667 regcomp (&port_regex, port_name_pattern,
1668 REG_EXTENDED|REG_NOSUB);
1669 }
1670 if (type_name_pattern && type_name_pattern[0]) {
1671 regcomp (&type_regex, type_name_pattern,
1672 REG_EXTENDED|REG_NOSUB);
1673 }
1674
1675 psp = engine->ports;
1676 match_cnt = 0;
1677
1678 matching_ports = (const char **)
1679 malloc (sizeof (char *) * engine->port_max);
1680
1681 for (i = 0; i < engine->port_max; i++) {
1682 matching = 1;
1683
1684 if (!psp[i].in_use) {
1685 continue;
1686 }
1687
1688 if (flags) {
1689 if ((psp[i].flags & flags) != flags) {
1690 matching = 0;
1691 }
1692 }
1693
1694 if (matching && port_name_pattern && port_name_pattern[0]) {
1695 if (regexec (&port_regex, psp[i].name, 0, NULL, 0)) {
1696 matching = 0;
1697 }
1698 }
1699
1700 if (matching && type_name_pattern && type_name_pattern[0]) {
1701 jack_port_type_id_t ptid = psp[i].ptype_id;
1702 if (regexec (&type_regex,
1703 engine->port_types[ptid].type_name,
1704 0, NULL, 0)) {
1705 matching = 0;
1706 }
1707 }
1708
1709 if (matching) {
1710 matching_ports[match_cnt++] = psp[i].name;
1711 }
1712 }
1713
1714 matching_ports[match_cnt] = 0;
1715
1716 if (match_cnt == 0) {
1717 free (matching_ports);
1718 matching_ports = 0;
1719 }
1720
1721 return matching_ports;
1722 }
1723
1724 float
1725 jack_cpu_load (jack_client_t *client)
1726 {
1727 return client->engine->cpu_load;
1728 }
1729
1730 pthread_t
1731 jack_client_thread_id (jack_client_t *client)
1732 {
1733 return client->thread_id;
1734 }
1735
1736 #if defined(__APPLE__) && defined(__POWERPC__)
1737
1738 double __jack_time_ratio;
1739
1740 void jack_init_time ()
1741 {
1742 mach_timebase_info_data_t info;
1743 mach_timebase_info(&info);
1744 __jack_time_ratio = ((float)info.numer/info.denom) / 1000;
1745 }
1746 #else
1747
1748 jack_time_t
1749 jack_get_mhz (void)
1750 {
1751 FILE *f = fopen("/proc/cpuinfo", "r");
1752 if (f == 0)
1753 {
1754 perror("can't open /proc/cpuinfo\n");
1755 exit(1);
1756 }
1757
1758 for ( ; ; )
1759 {
1760 jack_time_t mhz;
1761 int ret;
1762 char buf[1000];
1763
1764 if (fgets(buf, sizeof(buf), f) == NULL)
1765 {
1766 fprintf(stderr, "cannot locate cpu MHz in /proc/cpuinfo\n");
1767 exit(1);
1768 }
1769
1770 #if defined(__powerpc__)
1771 ret = sscanf(buf, "clock\t: %" SCNu64 "MHz", &mhz);
1772 #elif defined( __i386__ ) || defined (__hppa__) || defined (__ia64__) || \
1773 defined(__x86_64__)
1774 ret = sscanf(buf, "cpu MHz : %" SCNu64, &mhz);
1775 #elif defined( __sparc__ )
1776 ret = sscanf(buf, "Cpu0Bogo : %" SCNu64, &mhz);
1777 #elif defined( __mc68000__ )
1778 ret = sscanf(buf, "Clocking: %" SCNu64, &mhz);
1779 #elif defined( __s390__ )
1780 ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz);
1781 #else /* MIPS, ARM, alpha */
1782 ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz);
1783 #endif
1784
1785 if (ret == 1)
1786 {
1787 fclose(f);
1788 return (jack_time_t)mhz;
1789 }
1790 }
1791 }
1792
1793 jack_time_t __jack_cpu_mhz;
1794
1795 void jack_init_time ()
1796 {
1797 __jack_cpu_mhz = jack_get_mhz ();
1798 }
1799
1800 #endif
1801
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.