~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
JACK/libjack/client.c


** 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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.