1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
|
/* -*- mode: c; c-file-style: "bsd"; -*- */
/*
Internal shared data and functions.
If you edit this file, you should carefully consider changing the
JACK_PROTOCOL_VERSION in configure.in.
Copyright (C) 2001-2003 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __jack_internal_h__
#define __jack_internal_h__
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <dlfcn.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/time.h>
/* Needed by <sysdeps/time.h> */
extern void jack_error(const char *fmt, ...);
extern void jack_info(const char *fmt, ...);
#include <jack/jack.h>
#include <jack/types.h>
#include <jack/transport.h>
#include <jack/session.h>
#include <jack/thread.h>
#include <jack/metadata.h>
#include "port.h"
extern jack_thread_creator_t jack_thread_creator;
typedef enum {
JACK_TIMER_SYSTEM_CLOCK,
JACK_TIMER_HPET,
} jack_timer_type_t;
void jack_init_time();
void jack_set_clock_source (jack_timer_type_t);
const char* jack_clock_source_name (jack_timer_type_t);
#include <sysdeps/time.h>
#include "atomicity.h"
#ifdef JACK_USE_MACH_THREADS
#include <sysdeps/mach_port.h>
#endif
#include "messagebuffer.h"
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif /* MAXPATHLEN */
#endif /* !PATH_MAX */
#ifdef DEBUG_ENABLED
/* grab thread id instead of PID on linux */
#if defined(__gnu_linux__)
#ifdef gettid /* glibc has a version */
#define GETTID() gettid ()
#else /* use our own version */
#include <sys/syscall.h>
#define GETTID() syscall (__NR_gettid)
#endif
#else
#define GETTID() getpid ()
#endif
#define DEBUG(format, args ...) \
MESSAGE ("jack:%5d:%" PRIu64 " %s:%s:%d: " format "", GETTID (), jack_get_microseconds (), __FILE__, __FUNCTION__, __LINE__, ## args)
#else
#if JACK_CPP_VARARGS_BROKEN
#define DEBUG(format ...)
#else
#define DEBUG(format, args ...)
#endif
#endif
/* Enable preemption checking for Linux Realtime Preemption kernels.
*
* This checks if any RT-safe code section does anything to cause CPU
* preemption. Examples are sleep() or other system calls that block.
* If a problem is detected, the kernel writes a syslog entry, and
* sends SIGUSR2 to the client.
*/
#ifdef DO_PREEMPTION_CHECKING
#define CHECK_PREEMPTION(engine, onoff) \
if ((engine)->real_time) gettimeofday (1, (onoff))
#else
#define CHECK_PREEMPTION(engine, onoff)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (1)
#endif
typedef struct _jack_engine jack_engine_t;
typedef struct _jack_request jack_request_t;
typedef void * dlhandle;
typedef enum {
TransportCommandNone = 0,
TransportCommandStart = 1,
TransportCommandStop = 2,
} transport_command_t;
typedef struct {
volatile uint32_t guard1;
volatile jack_nframes_t frames;
volatile jack_time_t current_wakeup;
volatile jack_time_t next_wakeup;
volatile float period_usecs;
volatile int32_t initialized;
volatile uint32_t guard2;
/* not accessed by clients */
int32_t reset_pending; /* xrun happened, deal with it */
float filter_omega; /* set once, never altered */
} POST_PACKED_STRUCTURE jack_frame_timer_t;
/* JACK engine shared memory data structure. */
typedef struct {
jack_transport_state_t transport_state;
volatile transport_command_t transport_cmd;
transport_command_t previous_cmd; /* previous transport_cmd */
jack_position_t current_time; /* position for current cycle */
jack_position_t pending_time; /* position for next cycle */
jack_position_t request_time; /* latest requested position */
jack_unique_t prev_request; /* previous request unique ID */
volatile _Atomic_word seq_number; /* unique ID sequence number */
int8_t new_pos; /* new position this cycle */
int8_t pending_pos; /* new position request pending */
jack_nframes_t pending_frame; /* pending frame number */
int32_t sync_clients; /* number of active_slowsync clients */
int32_t sync_remain; /* number of them with sync_poll */
jack_time_t sync_timeout;
jack_time_t sync_time_left;
jack_frame_timer_t frame_timer;
int32_t internal;
jack_timer_type_t clock_source;
pid_t engine_pid;
jack_nframes_t buffer_size;
int8_t real_time;
int8_t do_mlock;
int8_t do_munlock;
int32_t client_priority;
int32_t max_client_priority;
int32_t has_capabilities;
float cpu_load;
float xrun_delayed_usecs;
float max_delayed_usecs;
uint32_t port_max;
int32_t engine_ok;
jack_port_type_id_t n_port_types;
jack_port_type_info_t port_types[JACK_MAX_PORT_TYPES];
jack_port_shared_t ports[0];
} POST_PACKED_STRUCTURE jack_control_t;
typedef enum {
BufferSizeChange,
SampleRateChange,
AttachPortSegment,
PortConnected,
PortDisconnected,
GraphReordered,
PortRegistered,
PortUnregistered,
XRun,
StartFreewheel,
StopFreewheel,
ClientRegistered,
ClientUnregistered,
SaveSession,
LatencyCallback,
PropertyChange,
PortRename
} JackEventType;
const char* jack_event_type_name (JackEventType);
typedef struct {
JackEventType type;
union {
uint32_t n;
char name[JACK_PORT_NAME_SIZE];
jack_port_id_t port_id;
jack_port_id_t self_id;
jack_uuid_t uuid;
} x;
union {
uint32_t n;
jack_port_type_id_t ptid;
jack_port_id_t other_id;
uint32_t key_size; /* key data will follow the event structure */
} y;
union {
char other_name[JACK_PORT_NAME_SIZE];
jack_property_change_t property_change;
} z;
} POST_PACKED_STRUCTURE jack_event_t;
typedef enum {
ClientInternal, /* connect request just names .so */
ClientDriver, /* code is loaded along with driver */
ClientExternal /* client is in another process */
} ClientType;
typedef enum {
NotTriggered,
Triggered,
Running,
Finished
} jack_client_state_t;
/* JACK client shared memory data structure. */
typedef volatile struct {
jack_uuid_t uuid; /* w: engine r: engine and client */
volatile jack_client_state_t state; /* w: engine and client r: engine */
volatile char name[JACK_CLIENT_NAME_SIZE];
volatile char session_command[JACK_PORT_NAME_SIZE];
volatile jack_session_flags_t session_flags;
volatile ClientType type; /* w: engine r: engine and client */
volatile int8_t active; /* w: engine r: engine and client */
volatile int8_t dead; /* r/w: engine */
volatile int8_t timed_out; /* r/w: engine */
volatile int8_t is_timebase; /* w: engine, r: engine and client */
volatile int8_t timebase_new; /* w: engine and client, r: engine */
volatile int8_t is_slowsync; /* w: engine, r: engine and client */
volatile int8_t active_slowsync; /* w: engine, r: engine and client */
volatile int8_t sync_poll; /* w: engine and client, r: engine */
volatile int8_t sync_new; /* w: engine and client, r: engine */
volatile pid_t pid; /* w: client r: engine; client pid */
volatile pid_t pgrp; /* w: client r: engine; client pgrp */
volatile uint64_t signalled_at;
volatile uint64_t awake_at;
volatile uint64_t finished_at;
volatile int32_t last_status; /* w: client, r: engine and client */
/* indicators for whether callbacks have been set for this client.
We do not include ptrs to the callbacks here (or their arguments)
so that we can avoid 32/64 bit pointer size mismatches between
the jack server and a client. The pointers are in the client-
local structure which is part of the libjack compiled for
either 32 bit or 64 bit clients.
*/
volatile uint8_t process_cbset;
volatile uint8_t thread_init_cbset;
volatile uint8_t bufsize_cbset;
volatile uint8_t srate_cbset;
volatile uint8_t port_register_cbset;
volatile uint8_t port_connect_cbset;
volatile uint8_t graph_order_cbset;
volatile uint8_t xrun_cbset;
volatile uint8_t sync_cb_cbset;
volatile uint8_t timebase_cb_cbset;
volatile uint8_t freewheel_cb_cbset;
volatile uint8_t client_register_cbset;
volatile uint8_t thread_cb_cbset;
volatile uint8_t session_cbset;
volatile uint8_t latency_cbset;
volatile uint8_t property_cbset;
volatile uint8_t port_rename_cbset;
} POST_PACKED_STRUCTURE jack_client_control_t;
typedef struct {
uint32_t protocol_v; /* protocol version, must go first */
int32_t load;
ClientType type;
jack_options_t options;
jack_uuid_t uuid;
char name[JACK_CLIENT_NAME_SIZE];
char object_path[PATH_MAX + 1];
char object_data[1024];
} POST_PACKED_STRUCTURE jack_client_connect_request_t;
typedef struct {
jack_status_t status;
jack_shm_registry_index_t client_shm_index;
jack_shm_registry_index_t engine_shm_index;
char fifo_prefix[PATH_MAX + 1];
int32_t realtime;
int32_t realtime_priority;
char name[JACK_CLIENT_NAME_SIZE]; /* unique name, if assigned */
/* these are actually pointers, but they must
be the same size regardless of whether the
server and/or client are 64 bit or 32 bit.
force them to be 64 bit.
*/
uint64_t client_control;
uint64_t engine_control;
#ifdef JACK_USE_MACH_THREADS
/* specific resources for server/client real-time thread communication */
int32_t portnum;
#endif
} POST_PACKED_STRUCTURE jack_client_connect_result_t;
typedef struct {
jack_uuid_t client_id;
} POST_PACKED_STRUCTURE jack_client_connect_ack_request_t;
typedef struct {
int8_t status;
} POST_PACKED_STRUCTURE jack_client_connect_ack_result_t;
typedef enum {
RegisterPort = 1,
UnRegisterPort = 2,
ConnectPorts = 3,
DisconnectPorts = 4,
SetTimeBaseClient = 5,
ActivateClient = 6,
DeactivateClient = 7,
DisconnectPort = 8,
SetClientCapabilities = 9,
GetPortConnections = 10,
GetPortNConnections = 11,
ResetTimeBaseClient = 12,
SetSyncClient = 13,
ResetSyncClient = 14,
SetSyncTimeout = 15,
SetBufferSize = 16,
FreeWheel = 17,
StopFreeWheel = 18,
IntClientHandle = 19,
IntClientLoad = 20,
IntClientName = 21,
IntClientUnload = 22,
RecomputeTotalLatencies = 23,
RecomputeTotalLatency = 24,
SessionNotify = 25,
GetClientByUUID = 26,
GetUUIDByClientName = 27,
ReserveName = 30,
SessionReply = 31,
SessionHasCallback = 32,
PropertyChangeNotify = 33,
PortNameChanged = 34
} RequestType;
struct _jack_request {
//RequestType type;
uint32_t type;
union {
struct {
char name[JACK_PORT_NAME_SIZE];
char type[JACK_PORT_TYPE_SIZE];
uint32_t flags;
jack_shmsize_t buffer_size;
jack_port_id_t port_id;
jack_uuid_t client_id;
} POST_PACKED_STRUCTURE port_info;
struct {
char source_port[JACK_PORT_NAME_SIZE];
char destination_port[JACK_PORT_NAME_SIZE];
} POST_PACKED_STRUCTURE connect;
struct {
char path[JACK_PORT_NAME_SIZE];
jack_session_event_type_t type;
char target[JACK_CLIENT_NAME_SIZE];
} POST_PACKED_STRUCTURE session;
struct {
int32_t nports;
const char **ports; /* this is only exposed to internal clients, so there
is no 64/32 issue. external clients read the ports
one by one from the server, and allocate their
own "ports" array in their own address space.
we are lucky, because this is part of a union
whose other components are bigger than this one.
otherwise it would change structure size when
comparing the 64 and 32 bit versions.
*/
} POST_PACKED_STRUCTURE port_connections;
struct {
jack_uuid_t client_id;
int32_t conditional;
} POST_PACKED_STRUCTURE timebase;
struct {
char name[JACK_CLIENT_NAME_SIZE];
jack_uuid_t uuid;
} POST_PACKED_STRUCTURE reservename;
struct {
//jack_options_t options;
uint32_t options;
jack_uuid_t uuid;
char name[JACK_CLIENT_NAME_SIZE];
char path[PATH_MAX + 1];
char init[JACK_LOAD_INIT_LIMIT];
} POST_PACKED_STRUCTURE intclient;
struct {
jack_property_change_t change;
jack_uuid_t uuid;
size_t keylen;
const char* key; /* not delivered inline to server, see oop_client_deliver_request() */
} POST_PACKED_STRUCTURE property;
jack_uuid_t client_id;
jack_nframes_t nframes;
jack_time_t timeout;
pid_t cap_pid;
char name[JACK_CLIENT_NAME_SIZE];
} POST_PACKED_STRUCTURE x;
int32_t status;
} POST_PACKED_STRUCTURE;
/* Per-client structure allocated in the server's address space.
* It's here because its not part of the engine structure.
*/
typedef struct _jack_client_internal {
jack_client_control_t *control;
int request_fd;
int event_fd;
int subgraph_start_fd;
int subgraph_wait_fd;
JSList *ports; /* protected by engine->client_lock */
JSList *truefeeds; /* protected by engine->client_lock */
JSList *sortfeeds; /* protected by engine->client_lock */
int fedcount;
int tfedcount;
jack_shm_info_t control_shm;
unsigned long execution_order;
struct _jack_client_internal *next_client; /* not a linked list! */
dlhandle handle;
int (*initialize)(jack_client_t*, const char*); /* int. clients only */
void (*finish)(void *); /* internal clients only */
int error;
int session_reply_pending;
#ifdef JACK_USE_MACH_THREADS
/* specific resources for server/client real-time thread communication */
mach_port_t serverport;
trivial_message message;
int running;
int portnum;
#endif /* JACK_USE_MACH_THREADS */
jack_client_t *private_client;
} jack_client_internal_t;
typedef struct _jack_thread_arg {
jack_client_t* client;
void* (*work_function)(void*);
int priority;
int realtime;
void* arg;
pid_t cap_pid;
} jack_thread_arg_t;
extern int jack_client_handle_port_connection(jack_client_t *client,
jack_event_t *event);
extern jack_client_t *jack_driver_client_new(jack_engine_t *,
const char *client_name);
extern jack_client_t *jack_client_alloc_internal(jack_client_control_t*,
jack_engine_t*);
/* internal clients call this. it's defined in jack/engine.c */
void handle_internal_client_request(jack_control_t*, jack_request_t*);
extern const char *jack_get_tmpdir(void);
extern char *jack_user_dir(void);
extern char *jack_server_dir(const char *server_name, char *server_dir);
extern void *jack_zero_filled_buffer;
extern jack_port_functions_t jack_builtin_audio_functions;
extern jack_port_type_info_t jack_builtin_port_types[];
extern void jack_client_fix_port_buffers(jack_client_t *client);
extern void jack_transport_copy_position(jack_position_t *from,
jack_position_t *to);
extern void jack_call_sync_client(jack_client_t *client);
extern void jack_call_timebase_master(jack_client_t *client);
extern char *jack_default_server_name(void);
void silent_jack_error_callback(const char *desc);
/* needed for port management */
extern jack_port_t *jack_port_by_id_int(const jack_client_t *client,
jack_port_id_t id, int* free);
extern jack_port_t *jack_port_by_name_int(jack_client_t *client,
const char *port_name, int* free);
extern int jack_port_name_equals(jack_port_shared_t* port, const char* target);
/** Get the size (in bytes) of the data structure used to store
* MIDI events internally.
*/
extern size_t jack_midi_internal_event_size();
extern int jack_client_handle_latency_callback(jack_client_t *client, jack_event_t *event, int is_driver);
#ifdef __GNUC__
# define likely(x) __builtin_expect ((x), 1)
# define unlikely(x) __builtin_expect ((x), 0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
#endif
#ifdef VALGRIND_CLEAN
#include <string.h>
#define VALGRIND_MEMSET(ptr, val, size) memset ((ptr), (val), (size))
#else
#define VALGRIND_MEMSET(ptr, val, size)
#endif
#endif /* __jack_internal_h__ */
|