diff --git a/drivers/alsa/alsa_driver.c b/drivers/alsa/alsa_driver.c index 9022874..4b40071 100644 --- a/drivers/alsa/alsa_driver.c +++ b/drivers/alsa/alsa_driver.c @@ -532,12 +532,13 @@ alsa_driver_configure_stream (alsa_driver_t *driver, char *device_name, return -1; } jack_info ("ALSA: use %d periods for %s", *nperiodsp, stream_name); - +#if 0 if (!jack_power_of_two(driver->frames_per_cycle)) { jack_error("JACK: frames must be a power of two " "(64, 512, 1024, ...)\n"); return -1; } +#endif if ((err = snd_pcm_hw_params_set_buffer_size (handle, hw_params, *nperiodsp * diff --git a/jack/internal.h b/jack/internal.h index be83539..0b327a6 100644 --- a/jack/internal.h +++ b/jack/internal.h @@ -34,6 +34,21 @@ #include #include +#ifndef POST_PACKED_STRUCTURE +#ifdef __GNUC__ +/* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. +*/ +#define POST_PACKED_STRUCTURE __attribute__((__packed__)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + /* Needed by */ extern void jack_error (const char *fmt, ...); @@ -136,7 +151,7 @@ typedef struct { int32_t reset_pending; /* xrun happened, deal with it */ float filter_coefficient; /* set once, never altered */ -} jack_frame_timer_t; +} POST_PACKED_STRUCTURE jack_frame_timer_t; /* JACK engine shared memory data structure. */ typedef struct { @@ -175,7 +190,7 @@ typedef struct { jack_port_type_info_t port_types[JACK_MAX_PORT_TYPES]; jack_port_shared_t ports[0]; -} jack_control_t; +} POST_PACKED_STRUCTURE jack_control_t; typedef enum { BufferSizeChange, @@ -206,7 +221,7 @@ typedef struct { jack_port_type_id_t ptid; jack_port_id_t other_id; } y; -} jack_event_t; +} POST_PACKED_STRUCTURE jack_event_t; typedef enum { ClientInternal, /* connect request just names .so */ @@ -245,48 +260,28 @@ typedef volatile struct { volatile uint64_t finished_at; volatile int32_t last_status; /* w: client, r: engine and client */ - /* JOQ: all these pointers are trouble for 32/64 compatibility, - * they should move to non-shared memory. + /* 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. */ - - /* callbacks - */ - JackProcessCallback process; - void *process_arg; - JackThreadInitCallback thread_init; - void *thread_init_arg; - JackBufferSizeCallback bufsize; - void *bufsize_arg; - JackSampleRateCallback srate; - void *srate_arg; - JackPortRegistrationCallback port_register; - void *port_register_arg; - JackPortConnectCallback port_connect; - void *port_connect_arg; - JackGraphOrderCallback graph_order; - void *graph_order_arg; - JackXRunCallback xrun; - void *xrun_arg; - JackSyncCallback sync_cb; - void *sync_arg; - JackTimebaseCallback timebase_cb; - void *timebase_arg; - JackFreewheelCallback freewheel_cb; - void *freewheel_arg; - JackClientRegistrationCallback client_register; - void *client_register_arg; - JackThreadCallback thread_cb; - void *thread_cb_arg; - - /* external clients: set by libjack - * internal clients: set by engine */ - int (*deliver_request)(void*, jack_request_t*); /* JOQ: 64/32 bug! */ - void *deliver_arg; - - /* for engine use only */ - void *private_client; - -} jack_client_control_t; + 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; + +} POST_PACKED_STRUCTURE jack_client_control_t; typedef struct { @@ -299,14 +294,14 @@ typedef struct { char object_path[PATH_MAX+1]; char object_data[1024]; -} jack_client_connect_request_t; +} POST_PACKED_STRUCTURE jack_client_connect_request_t; typedef struct { jack_status_t status; - jack_shm_info_t client_shm; - jack_shm_info_t engine_shm; + jack_shm_registry_index_t client_shm_index; + jack_shm_registry_index_t engine_shm_index; char fifo_prefix[PATH_MAX+1]; @@ -315,24 +310,29 @@ typedef struct { char name[JACK_CLIENT_NAME_SIZE]; /* unique name, if assigned */ - /* these two are valid only for internal clients */ - jack_client_control_t *client_control; - jack_control_t *engine_control; + /* these two are valid only for internal clients, and thus + are exempt from the requirement that we not export + pointers back to clients. an internal client must + necessarily match the host, so 32/64 bit issues + do not apply to these pointers. + */ + jack_client_control_t* client_control; + jack_control_t* engine_control; #ifdef JACK_USE_MACH_THREADS /* specific resources for server/client real-time thread communication */ int32_t portnum; #endif -} jack_client_connect_result_t; +} POST_PACKED_STRUCTURE jack_client_connect_result_t; typedef struct { jack_client_id_t client_id; -} jack_client_connect_ack_request_t; +} POST_PACKED_STRUCTURE jack_client_connect_ack_request_t; typedef struct { int8_t status; -} jack_client_connect_ack_result_t; +} POST_PACKED_STRUCTURE jack_client_connect_ack_result_t; typedef enum { RegisterPort = 1, @@ -363,7 +363,8 @@ typedef enum { struct _jack_request { - RequestType type; + //RequestType type; + uint32_t type; union { struct { char name[JACK_PORT_NAME_SIZE]; @@ -372,33 +373,35 @@ struct _jack_request { jack_shmsize_t buffer_size; jack_port_id_t port_id; jack_client_id_t client_id; - } port_info; + } POST_PACKED_STRUCTURE port_info; struct { char source_port[JACK_PORT_NAME_SIZE]; char destination_port[JACK_PORT_NAME_SIZE]; - } connect; + } POST_PACKED_STRUCTURE connect; struct { int32_t nports; - const char **ports; /* JOQ: 32/64 problem? */ - } port_connections; + //const char **ports; /* JOQ: 32/64 problem? */ + uint64_t ports; + } POST_PACKED_STRUCTURE port_connections; struct { jack_client_id_t client_id; int32_t conditional; - } timebase; + } POST_PACKED_STRUCTURE timebase; struct { - jack_options_t options; + //jack_options_t options; + uint32_t options; jack_client_id_t id; char name[JACK_CLIENT_NAME_SIZE]; char path[PATH_MAX+1]; char init[JACK_LOAD_INIT_LIMIT]; - } intclient; + } POST_PACKED_STRUCTURE intclient; jack_client_id_t client_id; jack_nframes_t nframes; jack_time_t timeout; pid_t cap_pid; - } x; + } 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. @@ -432,7 +435,42 @@ typedef struct _jack_client_internal { int running; int portnum; #endif /* JACK_USE_MACH_THREADS */ - + +#if 0 + /* callbacks + */ + JackProcessCallback process; + void *process_arg; + JackThreadInitCallback thread_init; + void *thread_init_arg; + JackBufferSizeCallback bufsize; + void *bufsize_arg; + JackSampleRateCallback srate; + void *srate_arg; + JackPortRegistrationCallback port_register; + void *port_register_arg; + JackPortConnectCallback port_connect; + void *port_connect_arg; + JackGraphOrderCallback graph_order; + void *graph_order_arg; + JackXRunCallback xrun; + void *xrun_arg; + JackSyncCallback sync_cb; + void *sync_arg; + JackTimebaseCallback timebase_cb; + void *timebase_arg; + JackFreewheelCallback freewheel_cb; + void *freewheel_arg; + JackClientRegistrationCallback client_register; + void *client_register_arg; + JackThreadCallback thread_cb; + void *thread_cb_arg; +#endif + /* external clients: set by libjack + * internal clients: set by engine */ + //int (*deliver_request)(void*, jack_request_t*); /* JOQ: 64/32 bug! */ + //void *deliver_arg; + jack_client_t *private_client; } jack_client_internal_t; typedef struct _jack_thread_arg { diff --git a/jack/transport.h b/jack/transport.h index b5787d6..de9a9cd 100644 --- a/jack/transport.h +++ b/jack/transport.h @@ -27,6 +27,22 @@ extern "C" { #include +#ifndef POST_PACKED_STRUCTURE +#ifdef __GNUC__ +/* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. +*/ +#define POST_PACKED_STRUCTURE __attribute__((__packed__)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + + /** * Transport states. */ @@ -127,7 +143,7 @@ typedef struct { /* When (unique_1 == unique_2) the contents are consistent. */ jack_unique_t unique_2; /**< unique ID */ -} jack_position_t; +} POST_PACKED_STRUCTURE jack_position_t; /** * Called by the timebase master to release itself from that diff --git a/jackd/clientengine.c b/jackd/clientengine.c index 34a8526..4597c89 100644 --- a/jackd/clientengine.c +++ b/jackd/clientengine.c @@ -38,6 +38,8 @@ #include "clientengine.h" #include "transengine.h" +#include "libjack/local.h" + static void jack_client_disconnect_ports (jack_engine_t *engine, jack_client_internal_t *client) @@ -318,7 +320,7 @@ jack_client_unload (jack_client_internal_t *client) { if (client->handle) { if (client->finish) { - client->finish (client->control->process_arg); + client->finish (client->private_client->process_arg); } dlclose (client->handle); } @@ -516,25 +518,38 @@ jack_setup_client_control (jack_engine_t *engine, int fd, client->subgraph_start_fd = -1; client->subgraph_wait_fd = -1; - client->control->process = NULL; - client->control->process_arg = NULL; - client->control->bufsize = NULL; - client->control->bufsize_arg = NULL; - client->control->srate = NULL; - client->control->srate_arg = NULL; - client->control->xrun = NULL; - client->control->xrun_arg = NULL; - client->control->port_register = NULL; - client->control->port_register_arg = NULL; - client->control->port_connect = NULL; - client->control->port_connect_arg = NULL; - client->control->graph_order = NULL; - client->control->graph_order_arg = NULL; - client->control->client_register = NULL; - client->control->client_register_arg = NULL; - client->control->thread_cb = NULL; - client->control->thread_cb_arg = NULL; - + client->control->process_cbset = FALSE; + client->control->bufsize_cbset = FALSE; + client->control->srate_cbset = FALSE; + client->control->xrun_cbset = FALSE; + client->control->port_register_cbset = FALSE; + client->control->port_connect_cbset = FALSE; + client->control->graph_order_cbset = FALSE; + client->control->client_register_cbset = FALSE; + client->control->thread_cb_cbset = FALSE; + +#if 0 + if (type != ClientExternal) { + client->process = NULL; + client->process_arg = NULL; + client->bufsize = NULL; + client->bufsize_arg = NULL; + client->srate = NULL; + client->srate_arg = NULL; + client->xrun = NULL; + client->xrun_arg = NULL; + client->port_register = NULL; + client->port_register_arg = NULL; + client->port_connect = NULL; + client->port_connect_arg = NULL; + client->graph_order = NULL; + client->graph_order_arg = NULL; + client->client_register = NULL; + client->client_register_arg = NULL; + client->thread_cb = NULL; + client->thread_cb_arg = NULL; + } +#endif jack_transport_client_new (client); #ifdef JACK_USE_MACH_THREADS @@ -586,12 +601,22 @@ setup_client (jack_engine_t *engine, ClientType type, char *name, if (jack_client_is_internal(client)) { + // XXX: do i need to lock the graph here ? + // i moved this one up in the init process, lets see what happens. + + /* Internal clients need to make regular JACK API + * calls, which need a jack_client_t structure. + * Create one here. + */ + client->private_client = + jack_client_alloc_internal (client->control, engine); + /* Set up the pointers necessary for the request * system to work. The client is in the same address * space */ - client->control->deliver_request = internal_client_request; - client->control->deliver_arg = engine; + client->private_client->deliver_request = internal_client_request; + client->private_client->deliver_arg = engine; } /* add new client to the clients list */ @@ -601,12 +626,6 @@ setup_client (jack_engine_t *engine, ClientType type, char *name, if (jack_client_is_internal(client)) { - /* Internal clients need to make regular JACK API - * calls, which need a jack_client_t structure. - * Create one here. - */ - client->control->private_client = - jack_client_alloc_internal (client->control, engine); jack_unlock_graph (engine); @@ -616,7 +635,7 @@ setup_client (jack_engine_t *engine, ClientType type, char *name, if (client->control->type == ClientInternal) { pthread_mutex_unlock (&engine->request_lock); - if (client->initialize (client->control->private_client, + if (client->initialize (client->private_client, object_data)) { /* failed: clean up client data */ @@ -735,8 +754,8 @@ jack_client_create (jack_engine_t *engine, int client_fd) res.status |= JackFailure; /* just making sure */ return -1; } - res.client_shm = client->control_shm; - res.engine_shm = engine->control_shm; + res.client_shm_index = client->control_shm.index; + res.engine_shm_index = engine->control_shm.index; res.realtime = engine->control->real_time; res.realtime_priority = engine->rtpriority - 1; strncpy (res.name, req.name, sizeof(res.name)); @@ -880,7 +899,7 @@ jack_client_delete (jack_engine_t *engine, jack_client_internal_t *client) if (jack_client_is_internal (client)) { jack_client_unload (client); - free (client->control->private_client); + free (client->private_client); free ((void *) client->control); } else { diff --git a/jackd/engine.c b/jackd/engine.c index 7ba1474..97ed8fe 100644 --- a/jackd/engine.c +++ b/jackd/engine.c @@ -61,6 +61,8 @@ #include "clientengine.h" #include "transengine.h" +#include "libjack/local.h" + typedef struct { jack_port_internal_t *source; @@ -581,17 +583,17 @@ jack_process_internal(jack_engine_t *engine, JSList *node, /* XXX how to time out an internal client? */ - if (ctl->sync_cb) - jack_call_sync_client (ctl->private_client); + if (ctl->sync_cb_cbset) + jack_call_sync_client (client->private_client); - if (ctl->process) - if (ctl->process (nframes, ctl->process_arg)) { + if (ctl->process_cbset) + if (client->private_client->process (nframes, client->private_client->process_arg)) { jack_error ("internal client %s failed", ctl->name); engine->process_errors++; } - if (ctl->timebase_cb) - jack_call_timebase_master (ctl->private_client); + if (ctl->timebase_cb_cbset) + jack_call_timebase_master (client->private_client); ctl->state = Finished; @@ -1071,7 +1073,7 @@ jack_engine_load_driver (jack_engine_t *engine, return -1; } - if ((driver = info->initialize (client->control->private_client, + if ((driver = info->initialize (client->private_client, driver_params)) == NULL) { free (info); return -1; @@ -1401,6 +1403,8 @@ handle_external_client_request (jack_engine_t *engine, int fd) } else { jack_error ("cannot read request from client (%d/%d/%s)", r, sizeof(req), strerror (errno)); + // XXX: shouldnt we mark this client as error now ? + return -1; } } @@ -2410,7 +2414,7 @@ jack_notify_all_port_interested_clients (jack_engine_t *engine, jack_client_id_t for (node = engine->clients; node; node = jack_slist_next (node)) { jack_client_internal_t* client = (jack_client_internal_t*) node->data; - if (src_client != client && dst_client != client && client->control->port_connect != NULL) { + if (src_client != client && dst_client != client && client->control->port_connect_cbset != FALSE) { /* one of the ports belong to this client or it has a port connect callback */ jack_deliver_event (engine, client, &event); @@ -2447,39 +2451,39 @@ jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client, case PortConnected: case PortDisconnected: jack_client_handle_port_connection - (client->control->private_client, event); + (client->private_client, event); break; case BufferSizeChange: jack_client_invalidate_port_buffers - (client->control->private_client); + (client->private_client); - if (client->control->bufsize) { - client->control->bufsize + if (client->control->bufsize_cbset) { + client->private_client->bufsize (event->x.n, - client->control->bufsize_arg); + client->private_client->bufsize_arg); } break; case SampleRateChange: - if (client->control->srate) { - client->control->srate + if (client->control->srate_cbset) { + client->private_client->srate (event->x.n, - client->control->srate_arg); + client->private_client->srate_arg); } break; case GraphReordered: - if (client->control->graph_order) { - client->control->graph_order - (client->control->graph_order_arg); + if (client->control->graph_order_cbset) { + client->private_client->graph_order + (client->private_client->graph_order_arg); } break; case XRun: - if (client->control->xrun) { - client->control->xrun - (client->control->xrun_arg); + if (client->control->xrun_cbset) { + client->private_client->xrun + (client->private_client->xrun_arg); } break; @@ -3134,7 +3138,7 @@ void jack_dump_configuration(jack_engine_t *engine, int take_lock) ++n, ctl->name, ctl->type, - ctl->process ? "yes" : "no", + ctl->process_cbset ? "yes" : "no", client->subgraph_start_fd, client->subgraph_wait_fd); @@ -3940,7 +3944,9 @@ jack_do_get_port_connections (jack_engine_t *engine, jack_request_t *req, * names. store in malloc'ed space, * client frees */ - req->x.port_connections.ports[i] = + char **ports = req->x.port_connections.ports; + + ports[i] = engine->control->ports[port_id].name; } else { @@ -3987,7 +3993,7 @@ jack_port_registration_notify (jack_engine_t *engine, continue; } - if (client->control->port_register) { + if (client->control->port_register_cbset) { if (jack_deliver_event (engine, client, &event)) { jack_error ("cannot send port registration" " notification to %s (%s)", @@ -4022,7 +4028,7 @@ jack_client_registration_notify (jack_engine_t *engine, continue; } - if (client->control->client_register) { + if (client->control->client_register_cbset) { if (jack_deliver_event (engine, client, &event)) { jack_error ("cannot send client registration" " notification to %s (%s)", diff --git a/jackd/transengine.c b/jackd/transengine.c index 29224b7..aea1d0a 100644 --- a/jackd/transengine.c +++ b/jackd/transengine.c @@ -321,10 +321,18 @@ jack_transport_client_new (jack_client_internal_t *client) client->control->active_slowsync = 0; client->control->sync_poll = 0; client->control->sync_new = 0; - client->control->sync_cb = NULL; - client->control->sync_arg = NULL; - client->control->timebase_cb = NULL; - client->control->timebase_arg = NULL; + + client->control->sync_cb_cbset = FALSE; + client->control->timebase_cb_cbset = FALSE; + +#if 0 + if (client->control->type != ClientExternal) { + client->sync_cb = NULL; + client->sync_arg = NULL; + client->timebase_cb = NULL; + client->timebase_arg = NULL; + } +#endif } /* on ResetSyncClient request */ diff --git a/libjack/client.c b/libjack/client.c index 84f387f..a1e8216 100644 --- a/libjack/client.c +++ b/libjack/client.c @@ -273,7 +273,7 @@ jack_client_deliver_request (const jack_client_t *client, jack_request_t *req) * the server. */ - return client->control->deliver_request (client->control->deliver_arg, + return client->deliver_request (client->deliver_arg, req); } @@ -454,10 +454,10 @@ jack_client_handle_port_connection (jack_client_t *client, jack_event_t *event) } } - if (client->control->port_connect) { - client->control->port_connect (event->x.self_id, event->y.other_id, + if (client->control->port_connect_cbset) { + client->port_connect (event->x.self_id, event->y.other_id, (event->type == PortConnected ? 1 : 0), - client->control->port_connect_arg); + client->port_connect_arg); } return 0; @@ -530,8 +530,8 @@ jack_handle_reorder (jack_client_t *client, jack_event_t *event) execute it now. */ - if (client->control->graph_order) { - client->control->graph_order (client->control->graph_order_arg); + if (client->control->graph_order_cbset) { + client->graph_order (client->graph_order_arg); } return 0; @@ -1013,7 +1013,7 @@ jack_client_open_aux (const char *client_name, } /* attach the engine control/info block */ - client->engine_shm = res.engine_shm; + client->engine_shm.index = res.engine_shm_index; if (jack_attach_shm (&client->engine_shm)) { jack_error ("cannot attached engine control shared memory" " segment"); @@ -1026,7 +1026,7 @@ jack_client_open_aux (const char *client_name, jack_set_clock_source (client->engine->clock_source); /* now attach the client control block */ - client->control_shm = res.client_shm; + client->control_shm.index = res.client_shm_index; if (jack_attach_shm (&client->control_shm)) { jack_error ("cannot attached client control shared memory" " segment"); @@ -1056,8 +1056,8 @@ jack_client_open_aux (const char *client_name, /* set up the client so that it does the right thing for an * external client */ - client->control->deliver_request = oop_client_deliver_request; - client->control->deliver_arg = client; + client->deliver_request = oop_client_deliver_request; + client->deliver_arg = client; if ((ev_fd = server_event_connect (client, va.server_name)) < 0) { goto fail; @@ -1255,8 +1255,8 @@ jack_start_freewheel (jack_client_t* client) #endif } - if (control->freewheel_cb) { - control->freewheel_cb (1, control->freewheel_arg); + if (control->freewheel_cb_cbset) { + client->freewheel_cb (1, client->freewheel_arg); } } @@ -1275,8 +1275,8 @@ jack_stop_freewheel (jack_client_t* client) #endif } - if (control->freewheel_cb) { - control->freewheel_cb (0, control->freewheel_arg); + if (control->freewheel_cb_cbset) { + client->freewheel_cb (0, client->freewheel_arg); } } @@ -1334,34 +1334,34 @@ jack_client_process_events (jack_client_t* client) port->type_info = &client->engine->port_types[port->shared->ptype_id]; } } - if (control->port_register) { - control->port_register + if (control->port_register_cbset) { + client->port_register (event.x.port_id, TRUE, - control->port_register_arg); + client->port_register_arg); } break; case PortUnregistered: - if (control->port_register) { - control->port_register + if (control->port_register_cbset) { + client->port_register (event.x.port_id, FALSE, - control->port_register_arg); + client->port_register_arg); } break; case ClientRegistered: - if (control->client_register) { - control->client_register + if (control->client_register_cbset) { + client->client_register (event.x.name, TRUE, - control->client_register_arg); + client->client_register_arg); } break; case ClientUnregistered: - if (control->client_register) { - control->client_register + if (control->client_register_cbset) { + client->client_register (event.x.name, FALSE, - control->client_register_arg); + client->client_register_arg); } break; @@ -1377,25 +1377,25 @@ jack_client_process_events (jack_client_t* client) case BufferSizeChange: jack_client_invalidate_port_buffers (client); - if (control->bufsize) { - status = control->bufsize + if (control->bufsize_cbset) { + status = client->bufsize (control->nframes, - control->bufsize_arg); + client->bufsize_arg); } break; case SampleRateChange: - if (control->srate) { - status = control->srate + if (control->srate_cbset) { + status = client->srate (control->nframes, - control->srate_arg); + client->srate_arg); } break; case XRun: - if (control->xrun) { - status = control->xrun - (control->xrun_arg); + if (control->xrun_cbset) { + status = client->xrun + (client->xrun_arg); } break; @@ -1583,7 +1583,7 @@ jack_thread_wait (jack_client_t* client, int status) /* housekeeping/cleanup after data processing */ - if (status == 0 && client->control->timebase_cb) { + if (status == 0 && client->control->timebase_cb_cbset) { jack_call_timebase_master (client); } @@ -1621,7 +1621,7 @@ jack_thread_wait (jack_client_t* client, int status) /* begin preemption checking */ CHECK_PREEMPTION (client->engine, TRUE); - if (client->control->sync_cb) + if (client->control->sync_cb_cbset) jack_call_sync_client (client); return client->control->nframes; @@ -1644,7 +1644,7 @@ jack_nframes_t jack_cycle_wait (jack_client_t* client) /* begin preemption checking */ CHECK_PREEMPTION (client->engine, TRUE); - if (client->control->sync_cb) + if (client->control->sync_cb_cbset) jack_call_sync_client (client); return client->control->nframes; @@ -1658,7 +1658,7 @@ void jack_cycle_signal(jack_client_t* client, int status) /* housekeeping/cleanup after data processing */ - if (status == 0 && client->control->timebase_cb) { + if (status == 0 && client->control->timebase_cb_cbset) { jack_call_timebase_master (client); } @@ -1701,9 +1701,9 @@ jack_client_thread_aux (void *arg) DEBUG ("client thread is now running"); - if (control->thread_init) { + if (control->thread_init_cbset) { DEBUG ("calling client thread init callback"); - control->thread_init (control->thread_init_arg); + client->thread_init (client->thread_init_arg); } /* wait for first wakeup from server */ @@ -1712,14 +1712,14 @@ jack_client_thread_aux (void *arg) /* now run till we're done */ - if (control->process) { + if (control->process_cbset) { /* run process callback, then wait... ad-infinitum */ while (1) { DEBUG("client calls process()"); - int status = (control->process (control->nframes, - control->process_arg) == + int status = (client->process (control->nframes, + client->process_arg) == control->nframes); control->state = Finished; DEBUG("client leaves process(), re-enters wait"); @@ -1745,7 +1745,7 @@ jack_client_thread (void *arg) jack_client_t *client = (jack_client_t *) arg; jack_client_control_t *control = client->control; - if (client->control->thread_cb) { + if (client->control->thread_cb_cbset) { pthread_mutex_lock (&client_lock); client->thread_ok = TRUE; @@ -1756,7 +1756,7 @@ jack_client_thread (void *arg) control->pid = getpid(); control->pgrp = getpgrp(); - client->control->thread_cb(client->control->thread_cb_arg); + client->thread_cb(client->thread_cb_arg); jack_client_thread_suicide(client); } else { jack_client_thread_aux(arg); @@ -2232,8 +2232,9 @@ jack_set_graph_order_callback (jack_client_t *client, jack_error ("You cannot set callbacks on an active client."); return -1; } - client->control->graph_order = callback; - client->control->graph_order_arg = arg; + client->graph_order = callback; + client->graph_order_arg = arg; + client->control->graph_order_cbset = (callback != NULL); return 0; } @@ -2245,8 +2246,9 @@ int jack_set_xrun_callback (jack_client_t *client, return -1; } - client->control->xrun = callback; - client->control->xrun_arg = arg; + client->xrun = callback; + client->xrun_arg = arg; + client->control->xrun_cbset = (callback != NULL); return 0; } @@ -2260,13 +2262,14 @@ jack_set_process_callback (jack_client_t *client, return -1; } - if (client->control->thread_cb) { + if (client->control->thread_cb_cbset) { jack_error ("A thread callback has already been setup, both models cannot be used at the same time!"); return -1; } - client->control->process_arg = arg; - client->control->process = callback; + client->process_arg = arg; + client->process = callback; + client->control->process_cbset = (callback != NULL); return 0; } @@ -2279,8 +2282,9 @@ jack_set_thread_init_callback (jack_client_t *client, jack_error ("You cannot set callbacks on an active client."); return -1; } - client->control->thread_init_arg = arg; - client->control->thread_init = callback; + client->thread_init_arg = arg; + client->thread_init = callback; + client->control->thread_init_cbset = (callback != NULL); return 0; } @@ -2292,8 +2296,9 @@ jack_set_freewheel_callback (jack_client_t *client, jack_error ("You cannot set callbacks on an active client."); return -1; } - client->control->freewheel_arg = arg; - client->control->freewheel_cb = callback; + client->freewheel_arg = arg; + client->freewheel_cb = callback; + client->control->freewheel_cb_cbset = (callback != NULL); return 0; } @@ -2301,8 +2306,9 @@ int jack_set_buffer_size_callback (jack_client_t *client, JackBufferSizeCallback callback, void *arg) { - client->control->bufsize_arg = arg; - client->control->bufsize = callback; + client->bufsize_arg = arg; + client->bufsize = callback; + client->control->bufsize_cbset = (callback != NULL); return 0; } @@ -2315,8 +2321,9 @@ jack_set_port_registration_callback(jack_client_t *client, jack_error ("You cannot set callbacks on an active client."); return -1; } - client->control->port_register_arg = arg; - client->control->port_register = callback; + client->port_register_arg = arg; + client->port_register = callback; + client->control->port_register_cbset = (callback != NULL); return 0; } @@ -2329,8 +2336,9 @@ jack_set_port_connect_callback(jack_client_t *client, jack_error ("You cannot set callbacks on an active client."); return -1; } - client->control->port_connect_arg = arg; - client->control->port_connect = callback; + client->port_connect_arg = arg; + client->port_connect = callback; + client->control->port_connect_cbset = (callback != NULL); return 0; } @@ -2343,8 +2351,9 @@ jack_set_client_registration_callback(jack_client_t *client, jack_error ("You cannot set callbacks on an active client."); return -1; } - client->control->client_register_arg = arg; - client->control->client_register = callback; + client->client_register_arg = arg; + client->client_register = callback; + client->control->client_register_cbset = (callback != NULL); return 0; } @@ -2356,13 +2365,14 @@ jack_set_process_thread(jack_client_t* client, JackThreadCallback callback, void return -1; } - if (client->control->process) { + if (client->control->process_cbset) { jack_error ("A process callback has already been setup, both models cannot be used at the same time!"); return -1; } - client->control->thread_cb_arg = arg; - client->control->thread_cb = callback; + client->thread_cb_arg = arg; + client->thread_cb = callback; + client->control->thread_cb_cbset = (callback != NULL); return 0; } diff --git a/libjack/local.h b/libjack/local.h index bcd8fb5..7ee4bbb 100644 --- a/libjack/local.h +++ b/libjack/local.h @@ -42,6 +42,40 @@ struct _jack_client { char rt_thread_ok : 1; #endif + /* callbacks + */ + JackProcessCallback process; + void *process_arg; + JackThreadInitCallback thread_init; + void *thread_init_arg; + JackBufferSizeCallback bufsize; + void *bufsize_arg; + JackSampleRateCallback srate; + void *srate_arg; + JackPortRegistrationCallback port_register; + void *port_register_arg; + JackPortConnectCallback port_connect; + void *port_connect_arg; + JackGraphOrderCallback graph_order; + void *graph_order_arg; + JackXRunCallback xrun; + void *xrun_arg; + JackSyncCallback sync_cb; + void *sync_arg; + JackTimebaseCallback timebase_cb; + void *timebase_arg; + JackFreewheelCallback freewheel_cb; + void *freewheel_arg; + JackClientRegistrationCallback client_register; + void *client_register_arg; + JackThreadCallback thread_cb; + void *thread_cb_arg; + + /* external clients: set by libjack + * internal clients: set by engine */ + int (*deliver_request)(void*, jack_request_t*); /* JOQ: 64/32 bug! */ + void *deliver_arg; + }; extern int jack_client_deliver_request (const jack_client_t *client, diff --git a/libjack/transclient.c b/libjack/transclient.c index 2e50536..f66811f 100644 --- a/libjack/transclient.c +++ b/libjack/transclient.c @@ -135,9 +135,9 @@ jack_call_sync_client (jack_client_t *client) if ((ectl->new_pos || control->sync_poll || control->sync_new) && control->active_slowsync) { - if (control->sync_cb (ectl->transport_state, + if (client->sync_cb (ectl->transport_state, &ectl->current_time, - control->sync_arg)) { + client->sync_arg)) { if (control->sync_poll) { control->sync_poll = 0; @@ -169,18 +169,19 @@ jack_call_timebase_master (jack_client_t *client) if ((ectl->transport_state == JackTransportRolling) || new_pos) { - control->timebase_cb (ectl->transport_state, + client->timebase_cb (ectl->transport_state, control->nframes, &ectl->pending_time, new_pos, - control->timebase_arg); + client->timebase_arg); } } else { /* another master took over, so resign */ - control->timebase_cb = NULL; - control->timebase_arg = NULL; + client->timebase_cb = NULL; + client->timebase_arg = NULL; + control->timebase_cb_cbset = FALSE; } } @@ -309,8 +310,9 @@ jack_set_sample_rate_callback (jack_client_t *client, jack_error ("You cannot set callbacks on an active client."); return -1; } - client->control->srate_arg = arg; - client->control->srate = callback; + client->srate_arg = arg; + client->srate = callback; + client->control->srate_cbset = (callback != NULL); /* Now invoke it */ @@ -331,9 +333,11 @@ jack_release_timebase (jack_client_t *client) rc = jack_client_deliver_request (client, &req); if (rc == 0) { - ctl->timebase_cb = NULL; - ctl->timebase_arg = NULL; + client->timebase_cb = NULL; + client->timebase_arg = NULL; + ctl->timebase_cb_cbset = NULL; } + return rc; } @@ -353,8 +357,9 @@ jack_set_sync_callback (jack_client_t *client, rc = jack_client_deliver_request (client, &req); if (rc == 0) { - ctl->sync_cb = sync_callback; - ctl->sync_arg = arg; + client->sync_cb = sync_callback; + client->sync_arg = arg; + ctl->sync_cb_cbset = TRUE; } return rc; } @@ -384,8 +389,9 @@ jack_set_timebase_callback (jack_client_t *client, int conditional, rc = jack_client_deliver_request (client, &req); if (rc == 0) { - ctl->timebase_arg = arg; - ctl->timebase_cb = timebase_cb; + client->timebase_arg = arg; + client->timebase_cb = timebase_cb; + ctl->timebase_cb_cbset = TRUE; } return rc; }