diff --git a/ChangeLog b/ChangeLog index 4b05b3e7..fbb75e3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -27,16 +27,75 @@ Mario Lang Arnold Krille Jan Engelhardt Adrian Knoth -David Garcia Garzon +David Garcia Garzon +Valerio Pilo --------------------------- Jackdmp changes log --------------------------- +2011-03-11 Stephane Letz + + * Correct JackNetMaster::SetBufferSize. + +2011-03-10 Stephane Letz + + * Latency callback must always be activated. + * Correct TopologicalSort. + * Add jack_midi_dump client. + * Synchronize netjack1 with JACK1 version. + * Synchronize jack_connect/jack_disconnect with JACK1 version. + +2011-03-09 Stephane Letz + + * jack_client_has_session_callback implementation. + * Fix jdelay for new latency API. + * Check requested buffer size and limit to 1..8192 - avoids wierd behaviour caused by jack_bufsize foobar. + * jack_port_type_get_buffer_size implementation. + * Stop using alloca and allocate buffer on the heap for alsa_io. + * Rename jdelay to jack_iodelay as per Fons' request. + * Call buffer size callback in activate (actually this is done on client side in the RT thread Init method). + * JackEngine::ComputeTotalLatencies in progress. + +2011-03-08 Stephane Letz + + * Use of latency range in all backends. + * ComputeTotalLatencies now a client/server call. + * Add latent test client for latency API. + * Also print playback and capture latency in jack_lsp. + +2011-03-04 Stephane Letz + + * Revert r4119 (RT notification in the server). JackAudioDriver::ProcessSync now skip backend write in case of graph process failure. + * Fix incorrect error codes in alsa/usx2y.c and alsa/JackAlsaDriver.cpp. + * Synchronize public headers with JACK1. Update OSX project. + * New latency API implementation (in progress). + +2011-02-09 Stephane Letz + + * Remove JackPortIsActive flag. + +2011-02-07 Stephane Letz + + * Valerio Pilo second CAS for ARMv7 patch. + +2011-02-03 Stephane Letz + + * Valerio Pilo CAS for ARMv7 patch. + +2011-01-11 Stephane Letz + + * Adrian Knoth jack_lsp patch. + +2010-11-17 Stephane Letz + + * ALSA backend : suspend/resume handling (jack1 r4075). + * Correct dummy driver. + 2010-11-05 Stephane Letz * In jackdmp.cpp, jackctl_setup_signals moved before jackctl_server_start. - * Correct symbols export in backends. + * Correct symbols export in backends on OSX. 2010-11-03 Stephane Letz diff --git a/common/JackAPI.cpp b/common/JackAPI.cpp index fe60ebe2..550133cb 100644 --- a/common/JackAPI.cpp +++ b/common/JackAPI.cpp @@ -41,7 +41,7 @@ extern "C" { #endif - typedef void (*print_function)(const char *); + typedef void (*print_function)(const char*); typedef void *(*thread_routine)(void*); EXPORT @@ -53,198 +53,219 @@ extern "C" int *proto_ptr); EXPORT - const char * + const char* jack_get_version_string(); - jack_client_t * jack_client_new_aux (const char *client_name, + jack_client_t * jack_client_new_aux(const char* client_name, jack_options_t options, jack_status_t *status); - EXPORT jack_client_t * jack_client_open (const char *client_name, + EXPORT jack_client_t * jack_client_open(const char* client_name, jack_options_t options, jack_status_t *status, ...); - EXPORT jack_client_t * jack_client_new (const char *client_name); - EXPORT int jack_client_name_size (void); - EXPORT char* jack_get_client_name (jack_client_t *client); - EXPORT int jack_internal_client_new (const char *client_name, - const char *load_name, - const char *load_init); - EXPORT void jack_internal_client_close (const char *client_name); - EXPORT int jack_is_realtime (jack_client_t *client); - EXPORT void jack_on_shutdown (jack_client_t *client, + EXPORT jack_client_t * jack_client_new(const char* client_name); + EXPORT int jack_client_name_size(void); + EXPORT char* jack_get_client_name(jack_client_t *client); + EXPORT int jack_internal_client_new(const char* client_name, + const char* load_name, + const char* load_init); + EXPORT void jack_internal_client_close(const char* client_name); + EXPORT int jack_is_realtime(jack_client_t *client); + EXPORT void jack_on_shutdown(jack_client_t *client, JackShutdownCallback shutdown_callback, void *arg); - EXPORT void jack_on_info_shutdown (jack_client_t *client, + EXPORT void jack_on_info_shutdown(jack_client_t *client, JackInfoShutdownCallback shutdown_callback, void *arg); - EXPORT int jack_set_process_callback (jack_client_t *client, + EXPORT int jack_set_process_callback(jack_client_t *client, JackProcessCallback process_callback, void *arg); EXPORT jack_nframes_t jack_thread_wait(jack_client_t *client, int status); // new - EXPORT jack_nframes_t jack_cycle_wait (jack_client_t*); - EXPORT void jack_cycle_signal (jack_client_t*, int status); + EXPORT jack_nframes_t jack_cycle_wait(jack_client_t*); + EXPORT void jack_cycle_signal(jack_client_t*, int status); EXPORT int jack_set_process_thread(jack_client_t* client, JackThreadCallback fun, void *arg); - EXPORT int jack_set_thread_init_callback (jack_client_t *client, + EXPORT int jack_set_thread_init_callback(jack_client_t *client, JackThreadInitCallback thread_init_callback, void *arg); - EXPORT int jack_set_freewheel_callback (jack_client_t *client, + EXPORT int jack_set_freewheel_callback(jack_client_t *client, JackFreewheelCallback freewheel_callback, void *arg); EXPORT int jack_set_freewheel(jack_client_t* client, int onoff); - EXPORT int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes); - EXPORT int jack_set_buffer_size_callback (jack_client_t *client, + EXPORT int jack_set_buffer_size(jack_client_t *client, jack_nframes_t nframes); + EXPORT int jack_set_buffer_size_callback(jack_client_t *client, JackBufferSizeCallback bufsize_callback, void *arg); - EXPORT int jack_set_sample_rate_callback (jack_client_t *client, + EXPORT int jack_set_sample_rate_callback(jack_client_t *client, JackSampleRateCallback srate_callback, void *arg); - EXPORT int jack_set_client_registration_callback (jack_client_t *, + EXPORT int jack_set_client_registration_callback(jack_client_t *, JackClientRegistrationCallback registration_callback, void *arg); - EXPORT int jack_set_port_registration_callback (jack_client_t *, + EXPORT int jack_set_port_registration_callback(jack_client_t *, JackPortRegistrationCallback registration_callback, void *arg); - EXPORT int jack_set_port_connect_callback (jack_client_t *, + EXPORT int jack_set_port_connect_callback(jack_client_t *, JackPortConnectCallback connect_callback, void *arg); - EXPORT int jack_set_port_rename_callback (jack_client_t *, + EXPORT int jack_set_port_rename_callback(jack_client_t *, JackPortRenameCallback rename_callback, void *arg); - EXPORT int jack_set_graph_order_callback (jack_client_t *, + EXPORT int jack_set_graph_order_callback(jack_client_t *, JackGraphOrderCallback graph_callback, void *); - EXPORT int jack_set_xrun_callback (jack_client_t *, + EXPORT int jack_set_xrun_callback(jack_client_t *, JackXRunCallback xrun_callback, void *arg); - EXPORT int jack_activate (jack_client_t *client); - EXPORT int jack_deactivate (jack_client_t *client); - EXPORT jack_port_t * jack_port_register (jack_client_t *client, - const char *port_name, - const char *port_type, + EXPORT int jack_set_latency_callback(jack_client_t *client, + JackLatencyCallback callback, void *arg); + + EXPORT int jack_activate(jack_client_t *client); + EXPORT int jack_deactivate(jack_client_t *client); + EXPORT jack_port_t * jack_port_register(jack_client_t *client, + const char* port_name, + const char* port_type, unsigned long flags, unsigned long buffer_size); - EXPORT int jack_port_unregister (jack_client_t *, jack_port_t *); - EXPORT void * jack_port_get_buffer (jack_port_t *, jack_nframes_t); - EXPORT const char * jack_port_name (const jack_port_t *port); - EXPORT const char * jack_port_short_name (const jack_port_t *port); - EXPORT int jack_port_flags (const jack_port_t *port); - EXPORT const char * jack_port_type (const jack_port_t *port); - EXPORT jack_port_type_id_t jack_port_type_id (const jack_port_t *port); - EXPORT int jack_port_is_mine (const jack_client_t *, const jack_port_t *port); - EXPORT int jack_port_connected (const jack_port_t *port); - EXPORT int jack_port_connected_to (const jack_port_t *port, - const char *port_name); - EXPORT const char ** jack_port_get_connections (const jack_port_t *port); - EXPORT const char ** jack_port_get_all_connections (const jack_client_t *client, + EXPORT int jack_port_unregister(jack_client_t *, jack_port_t *); + EXPORT void * jack_port_get_buffer(jack_port_t *, jack_nframes_t); + EXPORT const char* jack_port_name(const jack_port_t *port); + EXPORT const char* jack_port_short_name(const jack_port_t *port); + EXPORT int jack_port_flags(const jack_port_t *port); + EXPORT const char* jack_port_type(const jack_port_t *port); + EXPORT jack_port_type_id_t jack_port_type_id(const jack_port_t *port); + EXPORT int jack_port_is_mine(const jack_client_t *, const jack_port_t *port); + EXPORT int jack_port_connected(const jack_port_t *port); + EXPORT int jack_port_connected_to(const jack_port_t *port, + const char* port_name); + EXPORT const char* * jack_port_get_connections(const jack_port_t *port); + EXPORT const char* * jack_port_get_all_connections(const jack_client_t *client, const jack_port_t *port); - EXPORT int jack_port_tie (jack_port_t *src, jack_port_t *dst); - EXPORT int jack_port_untie (jack_port_t *port); - EXPORT jack_nframes_t jack_port_get_latency (jack_port_t *port); - EXPORT jack_nframes_t jack_port_get_total_latency (jack_client_t *, + EXPORT int jack_port_tie(jack_port_t *src, jack_port_t *dst); + EXPORT int jack_port_untie(jack_port_t *port); + + // Old latency API + EXPORT jack_nframes_t jack_port_get_latency(jack_port_t *port); + EXPORT jack_nframes_t jack_port_get_total_latency(jack_client_t *, jack_port_t *port); - EXPORT void jack_port_set_latency (jack_port_t *, jack_nframes_t); - EXPORT int jack_recompute_total_latency (jack_client_t*, jack_port_t* port); - EXPORT int jack_recompute_total_latencies (jack_client_t*); - EXPORT int jack_port_set_name (jack_port_t *port, const char *port_name); - EXPORT int jack_port_set_alias (jack_port_t *port, const char *alias); - EXPORT int jack_port_unset_alias (jack_port_t *port, const char *alias); - EXPORT int jack_port_get_aliases (const jack_port_t *port, char* const aliases[2]); - EXPORT int jack_port_request_monitor (jack_port_t *port, int onoff); - EXPORT int jack_port_request_monitor_by_name (jack_client_t *client, - const char *port_name, int onoff); - EXPORT int jack_port_ensure_monitor (jack_port_t *port, int onoff); - EXPORT int jack_port_monitoring_input (jack_port_t *port); - EXPORT int jack_connect (jack_client_t *, - const char *source_port, - const char *destination_port); - EXPORT int jack_disconnect (jack_client_t *, - const char *source_port, - const char *destination_port); - EXPORT int jack_port_disconnect (jack_client_t *, jack_port_t *); + EXPORT void jack_port_set_latency(jack_port_t *, jack_nframes_t); + EXPORT int jack_recompute_total_latency(jack_client_t*, jack_port_t* port); + + // New latency API + EXPORT void jack_port_get_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range); + EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range); + EXPORT int jack_recompute_total_latencies(jack_client_t*); + + EXPORT int jack_port_set_name(jack_port_t *port, const char* port_name); + EXPORT int jack_port_set_alias(jack_port_t *port, const char* alias); + EXPORT int jack_port_unset_alias(jack_port_t *port, const char* alias); + EXPORT int jack_port_get_aliases(const jack_port_t *port, char* const aliases[2]); + EXPORT int jack_port_request_monitor(jack_port_t *port, int onoff); + EXPORT int jack_port_request_monitor_by_name(jack_client_t *client, + const char* port_name, int onoff); + EXPORT int jack_port_ensure_monitor(jack_port_t *port, int onoff); + EXPORT int jack_port_monitoring_input(jack_port_t *port); + EXPORT int jack_connect(jack_client_t *, + const char* source_port, + const char* destination_port); + EXPORT int jack_disconnect(jack_client_t *, + const char* source_port, + const char* destination_port); + EXPORT int jack_port_disconnect(jack_client_t *, jack_port_t *); EXPORT int jack_port_name_size(void); EXPORT int jack_port_type_size(void); - EXPORT jack_nframes_t jack_get_sample_rate (jack_client_t *); - EXPORT jack_nframes_t jack_get_buffer_size (jack_client_t *); - EXPORT const char ** jack_get_ports (jack_client_t *, - const char *port_name_pattern, - const char *type_name_pattern, + EXPORT size_t jack_port_type_get_buffer_size(jack_client_t *client, const char* port_type); + EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t *); + EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t *); + EXPORT const char* * jack_get_ports(jack_client_t *, + const char* port_name_pattern, + const char* type_name_pattern, unsigned long flags); - EXPORT jack_port_t * jack_port_by_name (jack_client_t *, const char *port_name); - EXPORT jack_port_t * jack_port_by_id (jack_client_t *client, + EXPORT jack_port_t * jack_port_by_name(jack_client_t *, const char* port_name); + EXPORT jack_port_t * jack_port_by_id(jack_client_t *client, jack_port_id_t port_id); - EXPORT int jack_engine_takeover_timebase (jack_client_t *); - EXPORT jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *); + EXPORT int jack_engine_takeover_timebase(jack_client_t *); + EXPORT jack_nframes_t jack_frames_since_cycle_start(const jack_client_t *); EXPORT jack_time_t jack_get_time(); EXPORT jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t time); EXPORT jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t frames); - EXPORT jack_nframes_t jack_frame_time (const jack_client_t *); - EXPORT jack_nframes_t jack_last_frame_time (const jack_client_t *client); - EXPORT float jack_cpu_load (jack_client_t *client); - EXPORT pthread_t jack_client_thread_id (jack_client_t *); - EXPORT void jack_set_error_function (print_function); - EXPORT void jack_set_info_function (print_function); - - EXPORT float jack_get_max_delayed_usecs (jack_client_t *client); - EXPORT float jack_get_xrun_delayed_usecs (jack_client_t *client); - EXPORT void jack_reset_max_delayed_usecs (jack_client_t *client); - - EXPORT int jack_release_timebase (jack_client_t *client); - EXPORT int jack_set_sync_callback (jack_client_t *client, + EXPORT jack_nframes_t jack_frame_time(const jack_client_t *); + EXPORT jack_nframes_t jack_last_frame_time(const jack_client_t *client); + EXPORT float jack_cpu_load(jack_client_t *client); + EXPORT jack_native_thread_t jack_client_thread_id(jack_client_t *); + EXPORT void jack_set_error_function(print_function); + EXPORT void jack_set_info_function(print_function); + + EXPORT float jack_get_max_delayed_usecs(jack_client_t *client); + EXPORT float jack_get_xrun_delayed_usecs(jack_client_t *client); + EXPORT void jack_reset_max_delayed_usecs(jack_client_t *client); + + EXPORT int jack_release_timebase(jack_client_t *client); + EXPORT int jack_set_sync_callback(jack_client_t *client, JackSyncCallback sync_callback, void *arg); - EXPORT int jack_set_sync_timeout (jack_client_t *client, + EXPORT int jack_set_sync_timeout(jack_client_t *client, jack_time_t timeout); - EXPORT int jack_set_timebase_callback (jack_client_t *client, + EXPORT int jack_set_timebase_callback(jack_client_t *client, int conditional, JackTimebaseCallback timebase_callback, void *arg); - EXPORT int jack_transport_locate (jack_client_t *client, + EXPORT int jack_transport_locate(jack_client_t *client, jack_nframes_t frame); - EXPORT jack_transport_state_t jack_transport_query (const jack_client_t *client, + EXPORT jack_transport_state_t jack_transport_query(const jack_client_t *client, jack_position_t *pos); - EXPORT jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client); - EXPORT int jack_transport_reposition (jack_client_t *client, + EXPORT jack_nframes_t jack_get_current_transport_frame(const jack_client_t *client); + EXPORT int jack_transport_reposition(jack_client_t *client, jack_position_t *pos); - EXPORT void jack_transport_start (jack_client_t *client); - EXPORT void jack_transport_stop (jack_client_t *client); - EXPORT void jack_get_transport_info (jack_client_t *client, + EXPORT void jack_transport_start(jack_client_t *client); + EXPORT void jack_transport_stop(jack_client_t *client); + EXPORT void jack_get_transport_info(jack_client_t *client, jack_transport_info_t *tinfo); - EXPORT void jack_set_transport_info (jack_client_t *client, + EXPORT void jack_set_transport_info(jack_client_t *client, jack_transport_info_t *tinfo); - EXPORT int jack_client_real_time_priority (jack_client_t*); - EXPORT int jack_client_max_real_time_priority (jack_client_t*); - EXPORT int jack_acquire_real_time_scheduling (pthread_t thread, int priority); - EXPORT int jack_client_create_thread (jack_client_t* client, - pthread_t *thread, + EXPORT int jack_client_real_time_priority(jack_client_t*); + EXPORT int jack_client_max_real_time_priority(jack_client_t*); + EXPORT int jack_acquire_real_time_scheduling(jack_native_thread_t thread, int priority); + EXPORT int jack_client_create_thread(jack_client_t* client, + jack_native_thread_t *thread, int priority, int realtime, // boolean thread_routine routine, void *arg); - EXPORT int jack_drop_real_time_scheduling (pthread_t thread); + EXPORT int jack_drop_real_time_scheduling(jack_native_thread_t thread); - EXPORT int jack_client_stop_thread (jack_client_t* client, pthread_t thread); - EXPORT int jack_client_kill_thread (jack_client_t* client, pthread_t thread); + EXPORT int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread); + EXPORT int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread); #ifndef WIN32 - EXPORT void jack_set_thread_creator (jack_thread_creator_t jtc); + EXPORT void jack_set_thread_creator(jack_thread_creator_t jtc); #endif - EXPORT char * jack_get_internal_client_name (jack_client_t *client, + EXPORT char * jack_get_internal_client_name(jack_client_t *client, jack_intclient_t intclient); - EXPORT jack_intclient_t jack_internal_client_handle (jack_client_t *client, - const char *client_name, + EXPORT jack_intclient_t jack_internal_client_handle(jack_client_t *client, + const char* client_name, jack_status_t *status); - EXPORT jack_intclient_t jack_internal_client_load (jack_client_t *client, - const char *client_name, + EXPORT jack_intclient_t jack_internal_client_load(jack_client_t *client, + const char* client_name, jack_options_t options, jack_status_t *status, ...); - EXPORT jack_intclient_t jack_internal_client_load_aux (jack_client_t *client, - const char *client_name, + EXPORT jack_intclient_t jack_internal_client_load_aux(jack_client_t *client, + const char* client_name, jack_options_t options, jack_status_t *status, va_list ap); - EXPORT jack_status_t jack_internal_client_unload (jack_client_t *client, + EXPORT jack_status_t jack_internal_client_unload(jack_client_t *client, jack_intclient_t intclient); EXPORT void jack_free(void* ptr); + EXPORT int jack_set_session_callback(jack_client_t* ext_client, JackSessionCallback session_callback, void* arg); + EXPORT jack_session_command_t *jack_session_notify(jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path); + EXPORT int jack_session_reply(jack_client_t* ext_client, jack_session_event_t *event); + EXPORT void jack_session_event_free(jack_session_event_t* ev); + EXPORT char* jack_get_uuid_for_client_name(jack_client_t* ext_client, const char* client_name); + EXPORT char* jack_get_client_name_by_uuid(jack_client_t* ext_client, const char* client_uuid); + EXPORT int jack_reserve_client_name(jack_client_t* ext_client, const char* name, const char* uuid); + EXPORT void jack_session_commands_free(jack_session_command_t *cmds); + EXPORT int jack_client_has_session_callback(jack_client_t *client, const char* client_name); + #ifdef __cplusplus } #endif @@ -256,7 +277,7 @@ static inline bool CheckPort(jack_port_id_t port_index) static inline bool CheckBufferSize(jack_nframes_t buffer_size) { - return (buffer_size <= BUFFER_SIZE_MAX); + return (buffer_size >= 1 && buffer_size <= BUFFER_SIZE_MAX); } static inline void WaitGraphChange() @@ -278,12 +299,12 @@ static inline void WaitGraphChange() } } -EXPORT void jack_set_error_function (print_function func) +EXPORT void jack_set_error_function(print_function func) { jack_error_callback = (func == NULL) ? &default_jack_error_callback : func; } -EXPORT void jack_set_info_function (print_function func) +EXPORT void jack_set_info_function(print_function func) { jack_info_callback = (func == NULL) ? &default_jack_info_callback : func; } @@ -526,6 +547,40 @@ EXPORT void jack_port_set_latency(jack_port_t* port, jack_nframes_t frames) } } +EXPORT void jack_port_get_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) +{ +#ifdef __CLIENTDEBUG__ + JackGlobals::CheckContext("jack_port_get_latency_range"); +#endif + uintptr_t port_aux = (uintptr_t)port; + jack_port_id_t myport = (jack_port_id_t)port_aux; + if (!CheckPort(myport)) { + jack_error("jack_port_get_latency_range called with an incorrect port %ld", myport); + } else { + WaitGraphChange(); + JackGraphManager* manager = GetGraphManager(); + if (manager) + manager->GetPort(myport)->GetLatencyRange(mode, range); + } +} + +EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) +{ +#ifdef __CLIENTDEBUG__ + JackGlobals::CheckContext("jack_port_set_latency_range"); +#endif + uintptr_t port_aux = (uintptr_t)port; + jack_port_id_t myport = (jack_port_id_t)port_aux; + if (!CheckPort(myport)) { + jack_error("jack_port_set_latency_range called with an incorrect port %ld", myport); + } else { + WaitGraphChange(); + JackGraphManager* manager = GetGraphManager(); + if (manager) + manager->GetPort(myport)->SetLatencyRange(mode, range); + } +} + EXPORT int jack_recompute_total_latency(jack_client_t* ext_client, jack_port_t* port) { #ifdef __CLIENTDEBUG__ @@ -536,10 +591,10 @@ EXPORT int jack_recompute_total_latency(jack_client_t* ext_client, jack_port_t* uintptr_t port_aux = (uintptr_t)port; jack_port_id_t myport = (jack_port_id_t)port_aux; if (client == NULL) { - jack_error("jack_recompute_total_latencies called with a NULL client"); + jack_error("jack_recompute_total_latency called with a NULL client"); return -1; } else if (!CheckPort(myport)) { - jack_error("jack_recompute_total_latencies called with a NULL port"); + jack_error("jack_recompute_total_latency called with a NULL port"); return -1; } else { WaitGraphChange(); @@ -559,9 +614,7 @@ EXPORT int jack_recompute_total_latencies(jack_client_t* ext_client) jack_error("jack_recompute_total_latencies called with a NULL client"); return -1; } else { - WaitGraphChange(); - JackGraphManager* manager = GetGraphManager(); - return (manager ? manager->ComputeTotalLatencies() : -1); + return client->ComputeTotalLatencies(); } } @@ -988,6 +1041,20 @@ EXPORT int jack_set_xrun_callback(jack_client_t* ext_client, JackXRunCallback xr } } +EXPORT int jack_set_latency_callback(jack_client_t* ext_client, JackLatencyCallback latency_callback, void *arg) +{ +#ifdef __CLIENTDEBUG__ + JackGlobals::CheckContext("jack_set_latency_callback"); +#endif + JackClient* client = (JackClient*)ext_client; + if (client == NULL) { + jack_error("jack_set_latency_callback called with a NULL client"); + return -1; + } else { + return client->SetLatencyCallback(latency_callback, arg); + } +} + EXPORT int jack_set_thread_init_callback(jack_client_t* ext_client, JackThreadInitCallback init_callback, void *arg) { #ifdef __CLIENTDEBUG__ @@ -1396,7 +1463,7 @@ EXPORT float jack_cpu_load(jack_client_t* ext_client) } } -EXPORT pthread_t jack_client_thread_id(jack_client_t* ext_client) +EXPORT jack_native_thread_t jack_client_thread_id(jack_client_t* ext_client) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_client_thread_id"); @@ -1404,7 +1471,7 @@ EXPORT pthread_t jack_client_thread_id(jack_client_t* ext_client) JackClient* client = (JackClient*)ext_client; if (client == NULL) { jack_error("jack_client_thread_id called with a NULL client"); - return (pthread_t)NULL; + return (jack_native_thread_t)NULL; } else { return client->GetThreadID(); } @@ -1439,6 +1506,26 @@ EXPORT int jack_port_type_size(void) return JACK_PORT_TYPE_SIZE; } +EXPORT size_t jack_port_type_get_buffer_size(jack_client_t* ext_client, const char* port_type) +{ +#ifdef __CLIENTDEBUG__ + JackGlobals::CheckContext("jack_port_type_get_buffer_size"); +#endif + JackClient* client = (JackClient*)ext_client; + if (client == NULL) { + jack_error("jack_port_type_get_buffer_size called with a NULL client"); + return 0; + } else { + jack_port_type_id_t port_id = GetPortTypeId(port_type); + if (port_id == PORT_TYPES_MAX) { + jack_error("jack_port_type_get_buffer_size called with an unknown port type = %s", port_type); + return 0; + } else { + return GetPortType(port_id)->size(); + } + } +} + // transport.h EXPORT int jack_release_timebase(jack_client_t* ext_client) { @@ -1595,7 +1682,7 @@ EXPORT void jack_set_transport_info(jack_client_t* ext_client, jack_transport_in { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_set_transport_info"); -#endif +#endif jack_error("jack_set_transport_info: deprecated"); if (tinfo) memset(tinfo, 0, sizeof(jack_transport_info_t)); @@ -1677,14 +1764,14 @@ EXPORT int jack_client_max_real_time_priority(jack_client_t* ext_client) } } -EXPORT int jack_acquire_real_time_scheduling(pthread_t thread, int priority) +EXPORT int jack_acquire_real_time_scheduling(jack_native_thread_t thread, int priority) { JackEngineControl* control = GetEngineControl(); return (control ? JackThread::AcquireRealTimeImp(thread, priority, GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint) : -1); } EXPORT int jack_client_create_thread(jack_client_t* client, - pthread_t *thread, + jack_native_thread_t *thread, int priority, int realtime, /* boolean */ thread_routine routine, @@ -1692,28 +1779,28 @@ EXPORT int jack_client_create_thread(jack_client_t* client, { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_client_create_thread"); -#endif +#endif return JackThread::StartImp(thread, priority, realtime, routine, arg); } -EXPORT int jack_drop_real_time_scheduling(pthread_t thread) +EXPORT int jack_drop_real_time_scheduling(jack_native_thread_t thread) { return JackThread::DropRealTimeImp(thread); } -EXPORT int jack_client_stop_thread(jack_client_t* client, pthread_t thread) +EXPORT int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_client_stop_thread"); -#endif +#endif return JackThread::StopImp(thread); } -EXPORT int jack_client_kill_thread(jack_client_t* client, pthread_t thread) +EXPORT int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_client_kill_thread"); -#endif +#endif return JackThread::KillImp(thread); } @@ -1725,15 +1812,15 @@ EXPORT void jack_set_thread_creator (jack_thread_creator_t jtc) #endif // intclient.h -EXPORT int jack_internal_client_new (const char *client_name, - const char *load_name, - const char *load_init) +EXPORT int jack_internal_client_new (const char* client_name, + const char* load_name, + const char* load_init) { jack_error("jack_internal_client_new: deprecated"); return -1; } -EXPORT void jack_internal_client_close (const char *client_name) +EXPORT void jack_internal_client_close (const char* client_name) { jack_error("jack_internal_client_close: deprecated"); } @@ -1803,7 +1890,7 @@ EXPORT jack_intclient_t jack_internal_client_load_aux(jack_client_t* ext_client, } } -EXPORT jack_intclient_t jack_internal_client_load(jack_client_t *client, const char *client_name, jack_options_t options, jack_status_t *status, ...) +EXPORT jack_intclient_t jack_internal_client_load(jack_client_t *client, const char* client_name, jack_options_t options, jack_status_t *status, ...) { va_list ap; va_start(ap, status); @@ -1847,7 +1934,7 @@ jack_get_version( } EXPORT -const char * +const char* jack_get_version_string() { return VERSION; @@ -1876,7 +1963,7 @@ EXPORT int jack_set_session_callback(jack_client_t* ext_client, JackSessionCallb } } -EXPORT jack_session_command_t *jack_session_notify(jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char *path) +EXPORT jack_session_command_t *jack_session_notify(jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_session_notify"); @@ -1891,7 +1978,7 @@ EXPORT jack_session_command_t *jack_session_notify(jack_client_t* ext_client, co } } -EXPORT int jack_session_reply(jack_client_t *ext_client, jack_session_event_t *event) +EXPORT int jack_session_reply(jack_client_t* ext_client, jack_session_event_t *event) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_session_reply"); @@ -1919,7 +2006,7 @@ EXPORT void jack_session_event_free(jack_session_event_t* ev) } } -EXPORT char *jack_get_uuid_for_client_name( jack_client_t *ext_client, const char *client_name ) +EXPORT char *jack_get_uuid_for_client_name(jack_client_t* ext_client, const char* client_name) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_get_uuid_for_client_name"); @@ -1934,7 +2021,7 @@ EXPORT char *jack_get_uuid_for_client_name( jack_client_t *ext_client, const cha } } -EXPORT char *jack_get_client_name_by_uuid( jack_client_t *ext_client, const char *client_uuid ) +EXPORT char *jack_get_client_name_by_uuid(jack_client_t* ext_client, const char* client_uuid) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_get_client_name_by_uuid"); @@ -1945,11 +2032,11 @@ EXPORT char *jack_get_client_name_by_uuid( jack_client_t *ext_client, const char jack_error("jack_get_client_name_by_uuid called with a NULL client"); return NULL; } else { - return client->GetClientNameForUUID(client_uuid); + return client->GetClientNameByUUID(client_uuid); } } -EXPORT int jack_reserve_client_name( jack_client_t *ext_client, const char *name, const char *uuid ) +EXPORT int jack_reserve_client_name(jack_client_t* ext_client, const char* client_name, const char* uuid) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_reserve_client_name"); @@ -1960,17 +2047,17 @@ EXPORT int jack_reserve_client_name( jack_client_t *ext_client, const char *name jack_error("jack_reserve_client_name called with a NULL client"); return -1; } else { - return client->ReserveClientName(name, uuid); + return client->ReserveClientName(client_name, uuid); } } -EXPORT void jack_session_commands_free( jack_session_command_t *cmds ) +EXPORT void jack_session_commands_free(jack_session_command_t *cmds) { if (!cmds) return; - int i=0; - while(1) { + int i = 0; + while (1) { if (cmds[i].client_name) free ((char *)cmds[i].client_name); if (cmds[i].command) @@ -1985,3 +2072,18 @@ EXPORT void jack_session_commands_free( jack_session_command_t *cmds ) free(cmds); } + +EXPORT int jack_client_has_session_callback(jack_client_t* ext_client, const char* client_name) +{ +#ifdef __CLIENTDEBUG__ + JackGlobals::CheckContext("jack_client_has_session_callback"); +#endif + JackClient* client = (JackClient*)ext_client; + jack_log("jack_client_has_session_callback ext_client %x client %x ", ext_client, client); + if (client == NULL) { + jack_error("jack_client_has_session_callback called with a NULL client"); + return -1; + } else { + return client->ClientHasSessionCallback(client_name); + } +} diff --git a/common/JackAudioDriver.cpp b/common/JackAudioDriver.cpp index 9748b46a..1e02f213 100644 --- a/common/JackAudioDriver.cpp +++ b/common/JackAudioDriver.cpp @@ -101,6 +101,7 @@ int JackAudioDriver::Attach() jack_port_id_t port_index; char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + jack_latency_range_t range; int i; jack_log("JackAudioDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); @@ -114,7 +115,8 @@ int JackAudioDriver::Attach() } port = fGraphManager->GetPort(port_index); port->SetAlias(alias); - port->SetLatency(fEngineControl->fBufferSize + fCaptureLatency); + range.min = range.max = fEngineControl->fBufferSize + fCaptureLatency; + port->SetLatencyRange(JackCaptureLatency, &range); fCapturePortList[i] = port_index; jack_log("JackAudioDriver::Attach fCapturePortList[i] port_index = %ld", port_index); } @@ -129,7 +131,8 @@ int JackAudioDriver::Attach() port = fGraphManager->GetPort(port_index); port->SetAlias(alias); // Add more latency if "async" mode is used... - port->SetLatency(fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + fPlaybackLatency); + range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + fPlaybackLatency; + port->SetLatencyRange(JackPlaybackLatency, &range); fPlaybackPortList[i] = port_index; jack_log("JackAudioDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); @@ -143,7 +146,8 @@ int JackAudioDriver::Attach() } else { port = fGraphManager->GetPort(port_index); port->SetAlias(alias); - port->SetLatency(fEngineControl->fBufferSize); + range.min = range.max = fEngineControl->fBufferSize; + port->SetLatencyRange(JackCaptureLatency, &range); fMonitorPortList[i] = port_index; } } @@ -188,13 +192,13 @@ int JackAudioDriver::ProcessNull() { // Keep begin cycle time JackDriver::CycleTakeBeginTime(); - + if (fEngineControl->fSyncMode) { ProcessGraphSync(); } else { ProcessGraphAsync(); } - + // Keep end cycle time JackDriver::CycleTakeEndTime(); WaitUntilNextCycle(); @@ -214,23 +218,24 @@ synchronize to the end of client graph execution. int JackAudioDriver::ProcessAsync() { // Read input buffers for the current cycle - if (Read() < 0) { + if (Read() < 0) { jack_error("JackAudioDriver::ProcessAsync: read error, stopping..."); - return -1; + return -1; } // Write output buffers from the previous cycle if (Write() < 0) { jack_error("JackAudioDriver::ProcessAsync: write error, stopping..."); - return -1; + return -1; } + // Process graph if (fIsMaster) { ProcessGraphAsync(); } else { fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); } - + // Keep end cycle time JackDriver::CycleTakeEndTime(); return 0; @@ -238,29 +243,38 @@ int JackAudioDriver::ProcessAsync() /* The driver SYNC mode: the server does synchronize to the end of client graph execution, -output buffers computed at the *current cycle* are used. +if graph process succeed, output buffers computed at the *current cycle* are used. */ int JackAudioDriver::ProcessSync() { // Read input buffers for the current cycle - if (Read() < 0) { + if (Read() < 0) { jack_error("JackAudioDriver::ProcessSync: read error, stopping..."); - return -1; + return -1; } + // Process graph if (fIsMaster) { - ProcessGraphSync(); + if (ProcessGraphSync() < 0) { + jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); + goto end; + } } else { - fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); + if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) { + jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); + goto end; + } } - + // Write output buffers from the current cycle if (Write() < 0) { jack_error("JackAudioDriver::ProcessSync: write error, stopping..."); - return -1; + return -1; } - + +end: + // Keep end cycle time JackDriver::CycleTakeEndTime(); return 0; @@ -269,25 +283,34 @@ int JackAudioDriver::ProcessSync() void JackAudioDriver::ProcessGraphAsync() { // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle - if (!fEngine->Process(fBeginDateUst, fEndDateUst)) + if (!fEngine->Process(fBeginDateUst, fEndDateUst)) jack_error("JackAudioDriver::ProcessGraphAsync: Process error"); fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); if (ProcessSlaves() < 0) jack_error("JackAudioDriver::ProcessGraphAsync: ProcessSlaves error"); } -void JackAudioDriver::ProcessGraphSync() +int JackAudioDriver::ProcessGraphSync() { + int res = 0; + // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle - if (fEngine->Process(fBeginDateUst, fEndDateUst)) { + if (fEngine->Process(fBeginDateUst, fEndDateUst)) { fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); - if (ProcessSlaves() < 0) + if (ProcessSlaves() < 0) { jack_error("JackAudioDriver::ProcessGraphSync: ProcessSlaves error, engine may now behave abnormally!!"); - if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) + res = -1; + } + if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) { jack_error("JackAudioDriver::ProcessGraphSync: SuspendRefNum error, engine may now behave abnormally!!"); + res = -1; + } } else { // Graph not finished: do not activate it jack_error("JackAudioDriver::ProcessGraphSync: Process error"); + res = -1; } + + return res; } void JackAudioDriver::WaitUntilNextCycle() @@ -316,4 +339,37 @@ jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index) return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize); } +int JackAudioDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) +{ + switch (notify) { + + case kLatencyCallback: + HandleLatencyCallback(value1); + break; + + default: + JackDriver::ClientNotify(refnum, name, notify, sync, message, value1, value2); + break; + } + + return 0; +} + +void JackAudioDriver::HandleLatencyCallback(int status) +{ + jack_latency_callback_mode_t mode = (status == 0) ? JackCaptureLatency : JackPlaybackLatency; + + for (int i = 0; i < fCaptureChannels; i++) { + if (mode == JackPlaybackLatency) { + fGraphManager->RecalculateLatency(fCapturePortList[i], mode); + } + } + + for (int i = 0; i < fPlaybackChannels; i++) { + if (mode == JackCaptureLatency) { + fGraphManager->RecalculateLatency(fPlaybackPortList[i], mode); + } + } +} + } // end of namespace diff --git a/common/JackAudioDriver.h b/common/JackAudioDriver.h index 6fb64e64..3127f4c1 100644 --- a/common/JackAudioDriver.h +++ b/common/JackAudioDriver.h @@ -36,12 +36,12 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver protected: void ProcessGraphAsync(); - void ProcessGraphSync(); + int ProcessGraphSync(); void WaitUntilNextCycle(); virtual int ProcessAsync(); virtual int ProcessSync(); - + int fCaptureChannels; int fPlaybackChannels; @@ -57,6 +57,8 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver jack_default_audio_sample_t* GetOutputBuffer(int port_index); jack_default_audio_sample_t* GetMonitorBuffer(int port_index); + void HandleLatencyCallback(int status); + public: JackAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); @@ -73,7 +75,7 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency); - + virtual int Open(bool capturing, bool playing, int inchannels, @@ -83,18 +85,20 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency); - + virtual int Process(); virtual int ProcessNull(); virtual int Attach(); virtual int Detach(); - + virtual int Write(); virtual int SetBufferSize(jack_nframes_t buffer_size); virtual int SetSampleRate(jack_nframes_t sample_rate); + virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); + }; } // end of namespace diff --git a/common/JackAudioPort.cpp b/common/JackAudioPort.cpp index 20cf1e8c..c006b1cf 100644 --- a/common/JackAudioPort.cpp +++ b/common/JackAudioPort.cpp @@ -18,7 +18,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "JackGlobals.h" +#include "JackEngineControl.h" #include "JackPortType.h" + #include #if defined (__APPLE__) @@ -46,7 +49,7 @@ static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_ frames = frames % 4; while (frames_group > 0) { -#if defined (__SSE__) && !defined (__sun__) +#if defined (__SSE__) && !defined (__sun__) __m128 vec = _mm_add_ps(_mm_load_ps(mixbuffer), _mm_load_ps(buffer)); _mm_store_ps(mixbuffer, vec); @@ -97,7 +100,7 @@ static void AudioBufferMixdown(void* mixbuffer, void** src_buffers, int src_coun void* buffer; // Copy first buffer -#if defined (__SSE__) && !defined (__sun__) +#if defined (__SSE__) && !defined (__sun__) jack_nframes_t frames_group = nframes / 4; jack_nframes_t remaining_frames = nframes % 4; @@ -127,12 +130,18 @@ static void AudioBufferMixdown(void* mixbuffer, void** src_buffers, int src_coun } } +static size_t AudioBufferSize() +{ + return GetEngineControl()->fBufferSize * sizeof(float); +} + const JackPortType gAudioPortType = - { - JACK_DEFAULT_AUDIO_TYPE, - AudioBufferInit, - AudioBufferMixdown - }; +{ + JACK_DEFAULT_AUDIO_TYPE, + AudioBufferSize, + AudioBufferInit, + AudioBufferMixdown +}; } // namespace Jack diff --git a/common/JackChannel.h b/common/JackChannel.h index 40cfd264..c9ee89e5 100644 --- a/common/JackChannel.h +++ b/common/JackChannel.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __JackChannel__ #define __JackChannel__ -#include "types.h" #include "session.h" namespace Jack @@ -108,43 +107,39 @@ class JackClientChannelInterface {} virtual void SetFreewheel(int onoff, int* result) {} + virtual void ComputeTotalLatencies(int* result) + {} virtual void ReleaseTimebase(int refnum, int* result) {} - virtual void SetTimebaseCallback(int refnum, int conditional, int* result) {} virtual void GetInternalClientName(int refnum, int int_ref, char* name_res, int* result) {} - virtual void InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result) {} - virtual void InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, int* result) {} - virtual void InternalClientUnload(int refnum, int int_ref, int* status, int* result) {} - - virtual void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, jack_session_command_t **result) - {} - virtual void SessionReply(int refnum, int *result) + virtual void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result) {} - - virtual void GetUUIDForClientName(int refnum, const char *client_name, char *uuid_res, int *result) + virtual void SessionReply(int refnum, int* result) {} - - virtual void GetClientNameForUUID(int refnum, const char *uuid, char *name_res, int *result) + virtual void GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) {} - - virtual void ReserveClientName(int refnum, const char *client_name, const char *uuid, int *result) + virtual void GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) + {} + virtual void ReserveClientName(int refnum, const char* client_name, const char *uuid, int* result) + {} + virtual void ClientHasSessionCallback(const char* client_name, int* result) {} virtual bool IsChannelThread() - { - return false; + { + return false; } }; diff --git a/common/JackClient.cpp b/common/JackClient.cpp index 3a59140e..ae244688 100644 --- a/common/JackClient.cpp +++ b/common/JackClient.cpp @@ -13,12 +13,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "JackClient.h" +#include "JackSystemDeps.h" #include "JackGraphManager.h" #include "JackClientControl.h" #include "JackEngineControl.h" @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "driver_interface.h" #include "JackLibGlobals.h" + #include #include #include @@ -60,6 +61,9 @@ JackClient::JackClient(JackSynchro* table):fThread(this) fTimebase = NULL; fSync = NULL; fThreadFun = NULL; + fSession = NULL; + fLatency = NULL; + fProcessArg = NULL; fGraphOrderArg = NULL; fXrunArg = NULL; @@ -75,6 +79,8 @@ JackClient::JackClient(JackSynchro* table):fThread(this) fSyncArg = NULL; fTimebaseArg = NULL; fThreadFunArg = NULL; + fSessionArg = NULL; + fLatencyArg = NULL; } JackClient::~JackClient() @@ -84,17 +90,17 @@ int JackClient::Close() { jack_log("JackClient::Close ref = %ld", GetClientControl()->fRefNum); int result = 0; - + Deactivate(); fChannel->Stop(); // Channels is stopped first to avoid receiving notifications while closing - + // Request close only if server is still running if (JackGlobals::fServerRunning) { fChannel->ClientClose(GetClientControl()->fRefNum, &result); } else { - jack_log("JackClient::Close server is shutdown"); + jack_log("JackClient::Close server is shutdown"); } - + fChannel->Close(); fSynchroTable[GetClientControl()->fRefNum].Disconnect(); JackGlobals::fClientTable[GetClientControl()->fRefNum] = NULL; @@ -106,7 +112,7 @@ bool JackClient::IsActive() return (GetClientControl()) ? GetClientControl()->fActive : false; } -pthread_t JackClient::GetThreadID() +jack_native_thread_t JackClient::GetThreadID() { return fThread.GetThreadID(); } @@ -156,7 +162,7 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, case kActivateClient: jack_log("JackClient::kActivateClient name = %s ref = %ld ", name, refnum); - Init(); + InitAux(); break; } @@ -188,7 +194,7 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, res = fBufferSize(value1, fBufferSizeArg); } break; - + case kSampleRateCallback: jack_log("JackClient::kSampleRateCallback sample_rate = %ld", value1); if (fSampleRate) { @@ -219,7 +225,9 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, fFreewheel(0, fFreewheelArg); } if (GetEngineControl()->fRealTime) { - fThread.AcquireRealTime(); + if (fThread.AcquireRealTime() < 0) { + jack_error("JackClient::AcquireRealTime error"); + } } break; @@ -250,7 +258,7 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, fPortConnect(value1, value2, 0, fPortConnectArg); } break; - + case kPortRenameCallback: jack_log("JackClient::kPortRenameCallback port = %ld", value1); if (fPortRename) { @@ -264,7 +272,7 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, res = fXrun(fXrunArg); } break; - + case kShutDownCallback: jack_log("JackClient::kShutDownCallback"); if (fInfoShutdown) { @@ -289,15 +297,109 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, res = (fImmediateSessionReply) ? 1 : 2; } break; + + case kLatencyCallback: + res = HandleLatencyCallback(value1); + break; } } return res; } +int JackClient::HandleLatencyCallback(int status) +{ + jack_latency_callback_mode_t mode = (status == 0) ? JackCaptureLatency : JackPlaybackLatency; + jack_latency_range_t latency = { UINT32_MAX, 0 }; + + /* first setup all latency values of the ports. + * this is based on the connections of the ports. + */ + list::iterator it; + + for (it = fPortList.begin(); it != fPortList.end(); it++) { + JackPort* port = GetGraphManager()->GetPort(*it); + if ((port->GetFlags() & JackPortIsOutput) && (mode == JackPlaybackLatency)) { + GetGraphManager()->RecalculateLatency(*it, mode); + } + if ((port->GetFlags() & JackPortIsInput) && (mode == JackCaptureLatency)) { + GetGraphManager()->RecalculateLatency(*it, mode); + } + } + + if (!fLatency) { + /* + * default action is to assume all ports depend on each other. + * then always take the maximum latency. + */ + + if (mode == JackPlaybackLatency) { + /* iterate over all OutputPorts, to find maximum playback latency + */ + for (it = fPortList.begin(); it != fPortList.end(); it++) { + JackPort* port = GetGraphManager()->GetPort(*it); + if (port->GetFlags() & JackPortIsOutput) { + jack_latency_range_t other_latency; + port->GetLatencyRange(mode, &other_latency); + if (other_latency.max > latency.max) + latency.max = other_latency.max; + if (other_latency.min < latency.min) + latency.min = other_latency.min; + } + } + + if (latency.min == UINT32_MAX) + latency.min = 0; + + /* now set the found latency on all input ports + */ + for (it = fPortList.begin(); it != fPortList.end(); it++) { + JackPort* port = GetGraphManager()->GetPort(*it); + if (port->GetFlags() & JackPortIsInput) { + port->SetLatencyRange(mode, &latency); + } + } + } + if (mode == JackCaptureLatency) { + /* iterate over all InputPorts, to find maximum playback latency + */ + for (it = fPortList.begin(); it != fPortList.end(); it++) { + JackPort* port = GetGraphManager()->GetPort(*it); + if (port->GetFlags() & JackPortIsInput) { + jack_latency_range_t other_latency; + port->GetLatencyRange(mode, &other_latency); + if (other_latency.max > latency.max) + latency.max = other_latency.max; + if (other_latency.min < latency.min) + latency.min = other_latency.min; + } + } + + if (latency.min == UINT32_MAX) + latency.min = 0; + + /* now set the found latency on all output ports + */ + for (it = fPortList.begin(); it != fPortList.end(); it++) { + JackPort* port = GetGraphManager()->GetPort(*it); + if (port->GetFlags() & JackPortIsOutput) { + port->SetLatencyRange(mode, &latency); + } + } + } + return 0; + } + + /* we have a latency callback setup by the client, + * lets use it... + */ + fLatency(mode, fLatencyArg); + return 0; +} + /*! \brief We need to start thread before activating in the server, otherwise the FW driver - connected to the client may not be activated. +connected to the client may not be activated. */ int JackClient::Activate() { @@ -310,13 +412,13 @@ int JackClient::Activate() if (StartThread() < 0) return -1; } - + /* - Insertion of client in the graph will cause a kGraphOrderCallback notification + Insertion of client in the graph will cause a kGraphOrderCallback notification to be delivered by the server, the client wants to receive it. */ GetClientControl()->fActive = true; - + // Transport related callback become "active" GetClientControl()->fTransportSync = true; GetClientControl()->fTransportTimebase = true; @@ -337,18 +439,18 @@ int JackClient::Deactivate() return 0; GetClientControl()->fActive = false; - + // Transport related callback become "unactive" GetClientControl()->fTransportSync = false; GetClientControl()->fTransportTimebase = false; - + // We need to wait for the new engine cycle before stopping the RT thread, but this is done by ClientDeactivate int result = -1; fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); jack_log("JackClient::Deactivate res = %ld", result); - + // RT thread is stopped only when needed... - if (IsRealTime()) + if (IsRealTime()) fThread.Kill(); return result; } @@ -357,15 +459,48 @@ int JackClient::Deactivate() // RT thread management //---------------------- +void JackClient::InitAux() +{ + if (fInit) { + jack_log("JackClient::Init calling client thread init callback"); + fInit(fInitArg); + } +} + /*! \brief Called once when the thread starts. */ bool JackClient::Init() { - if (fInit) { - jack_log("JackClient::Init calling client thread init callback"); - fInit(fInitArg); + /* + Execute buffer_size callback. + + Since StartThread uses fThread.StartSync, we are sure that buffer_size callback + is executed before StartThread returns (and then IsActive will be true). + So no RT callback can be called at the same time. + */ + jack_log("JackClient::kBufferSizeCallback buffer_size = %ld", GetEngineControl()->fBufferSize); + if (fBufferSize) { + fBufferSize(GetEngineControl()->fBufferSize, fBufferSizeArg); + } + + // Init callback + InitAux(); + + // Setup context + if (!jack_tls_set(JackGlobals::fRealTime, this)) + jack_error("failed to set thread realtime key"); + + if (GetEngineControl()->fRealTime) + set_threaded_log_function(); + + // Setup RT + if (GetEngineControl()->fRealTime) { + if (fThread.AcquireRealTime(GetEngineControl()->fClientPriority) < 0) { + jack_error("JackClient::AcquireRealTime error"); + } } + return true; } @@ -384,12 +519,6 @@ int JackClient::StartThread() return -1; } - if (GetEngineControl()->fRealTime) { - if (fThread.AcquireRealTime(GetEngineControl()->fClientPriority) < 0) { - jack_error("AcquireRealTime error"); - } - } - return 0; } @@ -399,21 +528,15 @@ int JackClient::StartThread() bool JackClient::Execute() { - if (!jack_tls_set(JackGlobals::fRealTime, this)) - jack_error("failed to set thread realtime key"); - - if (GetEngineControl()->fRealTime) - set_threaded_log_function(); - // Execute a dummy cycle to be sure thread has the correct properties DummyCycle(); - + if (fThreadFun) { fThreadFun(fThreadFunArg); } else { ExecuteThread(); } - return false; + return false; } void JackClient::DummyCycle() @@ -424,15 +547,15 @@ void JackClient::DummyCycle() inline void JackClient::ExecuteThread() { - while (true) { + while (true) { CycleWaitAux(); - CycleSignalAux(CallProcessCallback()); - } + CycleSignalAux(CallProcessCallback()); + } } inline jack_nframes_t JackClient::CycleWaitAux() { - if (!WaitSync()) + if (!WaitSync()) Error(); // Terminates the thread CallSyncCallbackAux(); return GetEngineControl()->fBufferSize; @@ -443,7 +566,7 @@ inline void JackClient::CycleSignalAux(int status) if (status == 0) CallTimebaseCallbackAux(); SignalSync(); - if (status != 0) + if (status != 0) End(); // Terminates the thread } @@ -531,7 +654,7 @@ int JackClient::PortRegister(const char* port_name, const char* port_type, unsig int result = -1; jack_port_id_t port_index = NO_PORT; fChannel->PortRegister(GetClientControl()->fRefNum, name.c_str(), port_type, flags, buffer_size, &port_index, &result); - + if (result == 0) { jack_log("JackClient::PortRegister ref = %ld name = %s type = %s port_index = %ld", GetClientControl()->fRefNum, name.c_str(), port_type, port_index); fPortList.push_back(port_index); @@ -612,6 +735,13 @@ int JackClient::SetFreeWheel(int onoff) return result; } +int JackClient::ComputeTotalLatencies() +{ + int result = -1; + fChannel->ComputeTotalLatencies(&result); + return result; +} + /* ShutDown is called: - from the RT thread when Execute method fails @@ -621,9 +751,9 @@ ShutDown is called: void JackClient::ShutDown() { - jack_log("ShutDown"); + jack_log("JackClient::ShutDown"); JackGlobals::fServerRunning = false; - + if (fInfoShutdown) { fInfoShutdown(JackFailure, "JACK server has been closed", fInfoShutdownArg); fInfoShutdown = NULL; @@ -641,18 +771,18 @@ inline int JackClient::ActivateAux() { // If activated without RT thread... if (IsActive() && fThread.GetStatus() != JackThread::kRunning) { - - jack_log("ActivateAux"); - + + jack_log("JackClient::ActivateAux"); + // RT thread is started if (StartThread() < 0) return -1; - + int result = -1; GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime(); fChannel->ClientActivate(GetClientControl()->fRefNum, IsRealTime(), &result); return result; - + } else { return 0; } @@ -683,7 +813,7 @@ int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timeba { int result = -1; fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result); - + if (result == 0) { GetClientControl()->fTransportTimebase = true; fTimebase = timebase_callback; @@ -709,14 +839,14 @@ void JackClient::TransportLocate(jack_nframes_t frame) jack_position_t pos; pos.frame = frame; pos.valid = (jack_position_bits_t)0; - jack_log("TransportLocate pos = %ld", pos.frame); + jack_log("JackClient::TransportLocate pos = %ld", pos.frame); GetEngineControl()->fTransport.RequestNewPos(&pos); } int JackClient::TransportReposition(jack_position_t* pos) { jack_position_t tmp = *pos; - jack_log("TransportReposition pos = %ld", pos->frame); + jack_log("JackClient::TransportReposition pos = %ld", pos->frame); if (tmp.valid & ~JACK_POSITION_MASK) { return EINVAL; } else { @@ -758,11 +888,11 @@ void JackClient::CallSyncCallback() inline void JackClient::CallSyncCallbackAux() { if (GetClientControl()->fTransportSync) { - + JackTransportEngine& transport = GetEngineControl()->fTransport; jack_position_t* cur_pos = transport.ReadCurrentState(); jack_transport_state_t transport_state = transport.GetState(); - + if (fSync != NULL) { if (fSync(transport_state, cur_pos, fSyncArg)) { GetClientControl()->fTransportState = JackTransportRolling; @@ -785,21 +915,21 @@ inline void JackClient::CallTimebaseCallbackAux() JackTransportEngine& transport = GetEngineControl()->fTransport; int master; bool unused; - + transport.GetTimebaseMaster(master, unused); - + if (GetClientControl()->fRefNum == master && fTimebase) { // Client *is* timebase... - + jack_transport_state_t transport_state = transport.GetState(); jack_position_t* cur_pos = transport.WriteNextStateStart(1); - + if (GetClientControl()->fTransportTimebase) { - fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg); - GetClientControl()->fTransportTimebase = false; // Callback is called only once with "new_pos" = true + fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg); + GetClientControl()->fTransportTimebase = false; // Callback is called only once with "new_pos" = true } else if (transport_state == JackTransportRolling) { fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, false, fTimebaseArg); - } - + } + transport.WriteNextStateStop(1); } } @@ -817,7 +947,7 @@ void JackClient::OnShutdown(JackShutdownCallback callback, void *arg) fShutdown = callback; } } - + void JackClient::OnInfoShutdown(JackInfoShutdownCallback callback, void *arg) { if (IsActive()) { @@ -873,8 +1003,6 @@ int JackClient::SetInitCallback(JackThreadInitCallback callback, void *arg) int JackClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg) { - jack_log("SetGraphOrderCallback "); - if (IsActive()) { jack_error("You cannot set callbacks on an active client"); return -1; @@ -908,8 +1036,8 @@ int JackClient::SetSampleRateCallback(JackSampleRateCallback callback, void *arg GetClientControl()->fCallback[kSampleRateCallback] = (callback != NULL); fSampleRateArg = arg; fSampleRate = callback; - // Now invoke it - if (callback) + // Now invoke it + if (callback) callback(GetEngineControl()->fSampleRate, arg); return 0; } @@ -1011,6 +1139,19 @@ int JackClient::SetSessionCallback(JackSessionCallback callback, void *arg) } } +int JackClient::SetLatencyCallback(JackLatencyCallback callback, void *arg) +{ + if (IsActive()) { + jack_error("You cannot set callbacks on an active client"); + return -1; + } else { + // fCallback[kLatencyCallback] must always be 'true' + fLatencyArg = arg; + fLatency = callback; + return 0; + } +} + //------------------ // Internal clients //------------------ @@ -1072,65 +1213,64 @@ void JackClient::InternalClientUnload(int ref, jack_status_t* status) // Session API //------------------ -jack_session_command_t *JackClient::SessionNotify( const char* target, jack_session_event_type_t type, const char* path ) +jack_session_command_t* JackClient::SessionNotify(const char* target, jack_session_event_type_t type, const char* path) { - jack_session_command_t *res; - fChannel->SessionNotify( GetClientControl()->fRefNum, target, type, path, &res ); + jack_session_command_t* res; + fChannel->SessionNotify(GetClientControl()->fRefNum, target, type, path, &res); return res; } -int JackClient::SessionReply( jack_session_event_t *ev ) +int JackClient::SessionReply(jack_session_event_t* ev) { if (ev->command_line) { - strncpy( GetClientControl()->fSessionCommand, ev->command_line, sizeof(GetClientControl()->fSessionCommand) ); + strncpy(GetClientControl()->fSessionCommand, ev->command_line, sizeof(GetClientControl()->fSessionCommand)); } else { GetClientControl()->fSessionCommand[0] = '\0'; } GetClientControl()->fSessionFlags = ev->flags; - jack_log( "JackClient::SessionReply... we are here" ); + jack_log("JackClient::SessionReply... we are here"); if (fChannel->IsChannelThread()) { - jack_log( "JackClient::SessionReply... in callback reply" ); + jack_log( "JackClient::SessionReply... in callback reply"); fImmediateSessionReply = true; return 0; } - jack_log( "JackClient::SessionReply... out of cb" ); + jack_log("JackClient::SessionReply... out of cb"); - int res; - fChannel->SessionReply( GetClientControl()->fRefNum, &res); - return res; + int result = -1; + fChannel->SessionReply(GetClientControl()->fRefNum, &result); + return result; } char* JackClient::GetUUIDForClientName(const char* client_name) { char uuid_res[JACK_UUID_SIZE]; int result = -1; - fChannel->GetUUIDForClientName( GetClientControl()->fRefNum, client_name, uuid_res, &result); - - if (result) - return NULL; - - return strdup(uuid_res); + fChannel->GetUUIDForClientName(GetClientControl()->fRefNum, client_name, uuid_res, &result); + return (result) ? NULL : strdup(uuid_res); } -char* JackClient::GetClientNameForUUID(const char* uuid) +char* JackClient::GetClientNameByUUID(const char* uuid) { char name_res[JACK_CLIENT_NAME_SIZE + 1]; int result = -1; fChannel->GetClientNameForUUID(GetClientControl()->fRefNum, uuid, name_res, &result); + return (result) ? NULL : strdup(name_res); +} - if (result) - return NULL; - - return strdup(name_res); +int JackClient::ReserveClientName(const char* client_name, const char* uuid) +{ + int result = -1; + fChannel->ReserveClientName( GetClientControl()->fRefNum, client_name, uuid, &result); + return result; } -int JackClient::ReserveClientName(const char *name, const char* uuid) +int JackClient::ClientHasSessionCallback(const char* client_name) { int result = -1; - fChannel->ReserveClientName( GetClientControl()->fRefNum, name, uuid, &result); + fChannel->ClientHasSessionCallback(client_name, &result); return result; } diff --git a/common/JackClient.h b/common/JackClient.h index cd5ab090..230edf53 100644 --- a/common/JackClient.h +++ b/common/JackClient.h @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -27,7 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackSynchro.h" #include "JackPlatformPlug.h" #include "JackChannel.h" -#include "types.h" #include "session.h" #include "varargs.h" #include @@ -68,6 +67,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface JackSyncCallback fSync; JackThreadCallback fThreadFun; JackSessionCallback fSession; + JackLatencyCallback fLatency; void* fProcessArg; void* fGraphOrderArg; @@ -86,6 +86,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface void* fSyncArg; void* fThreadFunArg; void* fSessionArg; + void* fLatencyArg; char fServerName[64]; JackThread fThread; /*! Thread to execute the Process function */ @@ -94,14 +95,14 @@ class JackClient : public JackClientInterface, public JackRunnableInterface std::list fPortList; bool fImmediateSessionReply; - + int StartThread(); void SetupDriverSync(bool freewheel); bool IsActive(); void CallSyncCallback(); void CallTimebaseCallback(); - + virtual int ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value); inline void DummyCycle(); @@ -116,7 +117,10 @@ class JackClient : public JackClientInterface, public JackRunnableInterface inline void CallSyncCallbackAux(); inline void CallTimebaseCallbackAux(); inline int ActivateAux(); - + inline void InitAux(); + + int HandleLatencyCallback(int status); + public: JackClient(); @@ -138,8 +142,9 @@ class JackClient : public JackClientInterface, public JackRunnableInterface // Context virtual int SetBufferSize(jack_nframes_t buffer_size); virtual int SetFreeWheel(int onoff); + virtual int ComputeTotalLatencies(); virtual void ShutDown(); - virtual pthread_t GetThreadID(); + virtual jack_native_thread_t GetThreadID(); // Port management virtual int PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size); @@ -179,6 +184,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface virtual int SetPortConnectCallback(JackPortConnectCallback callback, void *arg); virtual int SetPortRenameCallback(JackPortRenameCallback callback, void *arg); virtual int SetSessionCallback(JackSessionCallback callback, void *arg); + virtual int SetLatencyCallback(JackLatencyCallback callback, void *arg); // Internal clients virtual char* GetInternalClientName(int ref); @@ -186,16 +192,18 @@ class JackClient : public JackClientInterface, public JackRunnableInterface virtual int InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va); virtual void InternalClientUnload(int ref, jack_status_t* status); + // RT Thread jack_nframes_t CycleWait(); void CycleSignal(int status); int SetProcessThread(JackThreadCallback fun, void *arg); - // Session api - virtual jack_session_command_t *SessionNotify(const char *target, jack_session_event_type_t type, const char *path); - virtual int SessionReply(jack_session_event_t *ev); -char* GetUUIDForClientName(const char* client_name); -char* GetClientNameForUUID(const char* uuid); -int ReserveClientName(const char *name, const char* uuid); + // Session API + virtual jack_session_command_t* SessionNotify(const char* target, jack_session_event_type_t type, const char* path); + virtual int SessionReply(jack_session_event_t* ev); + char* GetUUIDForClientName(const char* client_name); + char* GetClientNameByUUID(const char* uuid); + int ReserveClientName(const char* client_name, const char* uuid); + int ClientHasSessionCallback(const char* client_name); // JackRunnableInterface interface bool Init(); diff --git a/common/JackClientControl.h b/common/JackClientControl.h index 98f2ad31..29e4a5b7 100644 --- a/common/JackClientControl.h +++ b/common/JackClientControl.h @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -25,8 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackPort.h" #include "JackSynchro.h" #include "JackNotification.h" - -#include "jack/session.h" +#include "session.h" namespace Jack { @@ -74,6 +73,7 @@ struct JackClientControl : public JackShmMemAble fCallback[kAddClient] = true; fCallback[kRemoveClient] = true; fCallback[kActivateClient] = true; + fCallback[kLatencyCallback] = true; // So that driver synchro are correctly setup in "flush" or "normal" mode fCallback[kStartFreewheelCallback] = true; fCallback[kStopFreewheelCallback] = true; diff --git a/common/JackConnectionManager.cpp b/common/JackConnectionManager.cpp index f6a74dca..2be93fc9 100644 --- a/common/JackConnectionManager.cpp +++ b/common/JackConnectionManager.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackEngineControl.h" #include "JackGlobals.h" #include "JackError.h" +#include #include #include @@ -246,7 +247,7 @@ int JackConnectionManager::SuspendRefNum(JackClientControl* control, JackSynchro int JackConnectionManager::ResumeRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing) { jack_time_t current_date = GetMicroSeconds(); - const jack_int_t* outputRef = fConnectionRef.GetItems(control->fRefNum); + const jack_int_t* output_ref = fConnectionRef.GetItems(control->fRefNum); int res = 0; // Update state and timestamp of current client @@ -256,7 +257,7 @@ int JackConnectionManager::ResumeRefNum(JackClientControl* control, JackSynchro* for (int i = 0; i < CLIENT_NUM; i++) { // Signal connected clients or drivers - if (outputRef[i] > 0) { + if (output_ref[i] > 0) { // Update state and timestamp of destination clients timing[i].fStatus = Triggered; @@ -272,6 +273,44 @@ int JackConnectionManager::ResumeRefNum(JackClientControl* control, JackSynchro* return res; } +static bool HasNoConnection(jack_int_t* table) +{ + for (int ref = 0; ref < CLIENT_NUM; ref++) { + if (table[ref] > 0) return false; + } + return true; +} + +// Using http://en.wikipedia.org/wiki/Topological_sorting + +void JackConnectionManager::TopologicalSort(std::vector& sorted) +{ + JackFixedMatrix tmp; + std::set level; + + fConnectionRef.Copy(tmp); + + // Inputs of the graph + level.insert(AUDIO_DRIVER_REFNUM); + level.insert(FREEWHEEL_DRIVER_REFNUM); + + while (level.size() > 0) { + jack_int_t refnum = *level.begin(); + sorted.push_back(refnum); + level.erase(level.begin()); + const jack_int_t* output_ref1 = tmp.GetItems(refnum); + for (int dst = 0; dst < CLIENT_NUM; dst++) { + if (output_ref1[dst] > 0) { + tmp.ClearItem(refnum, dst); + jack_int_t output_ref2[CLIENT_NUM]; + tmp.GetOutputTable1(dst, output_ref2); + if (HasNoConnection(output_ref2)) + level.insert(dst); + } + } + } +} + /*! \brief Increment the number of ports between 2 clients, if the 2 clients become connected, then the Activation counter is updated. */ diff --git a/common/JackConnectionManager.h b/common/JackConnectionManager.h index 5d5b8c62..804ffcc3 100644 --- a/common/JackConnectionManager.h +++ b/common/JackConnectionManager.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackActivationCount.h" #include "JackError.h" #include "JackCompilerDeps.h" - +#include #include namespace Jack @@ -151,7 +151,7 @@ class JackFixedArray1 : public JackFixedArray return true; } } - + } POST_PACKED_STRUCTURE; /*! @@ -200,6 +200,11 @@ class JackFixedMatrix return fTable[index1][index2]; } + void ClearItem(jack_int_t index1, jack_int_t index2) + { + fTable[index1][index2] = 0; + } + /*! \brief Get the output indexes of a given index. */ @@ -218,6 +223,13 @@ class JackFixedMatrix } } + void GetOutputTable1(jack_int_t index, jack_int_t* output) const + { + for (int i = 0; i < SIZE; i++) { + output[i] = fTable[i][index]; + } + } + bool IsInsideTable(jack_int_t index, jack_int_t* output) const { for (int i = 0; i < SIZE && output[i] != EMPTY; i++) { @@ -227,6 +239,14 @@ class JackFixedMatrix return false; } + void Copy(JackFixedMatrix& copy) + { + for (int i = 0; i < SIZE; i++) { + memcpy(copy.fTable[i], fTable[i], sizeof(jack_int_t) * SIZE); + } + } + + } POST_PACKED_STRUCTURE; /*! @@ -359,7 +379,7 @@ struct JackClientTiming } ~JackClientTiming() {} - + void Init() { fSignaledAt = 0; @@ -367,7 +387,7 @@ struct JackClientTiming fFinishedAt = 0; fStatus = NotTriggered; } - + } POST_PACKED_STRUCTURE; /*! @@ -375,11 +395,9 @@ struct JackClientTiming
  • The fConnection array contains the list (array line) of connected ports for a given port. -
  • The fConnectionCount array contains the number of connected ports to a given port.
  • The fInputPort array contains the list (array line) of input connected ports for a given client.
  • The fOutputPort array contains the list (array line) of ouput connected ports for a given client.
  • The fConnectionRef array contains the number of ports connected between two clients. -
  • The fInputRef array contains the number of input clients connected to a given client.
  • The fInputCounter array contains the number of input clients connected to a given for activation purpose.
*/ @@ -461,7 +479,8 @@ class SERVER_EXPORT JackConnectionManager void ResetGraph(JackClientTiming* timing); int ResumeRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing); int SuspendRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing, long time_out_usec); - + void TopologicalSort(std::vector& sorted); + } POST_PACKED_STRUCTURE; } // end of namespace diff --git a/common/JackDebugClient.cpp b/common/JackDebugClient.cpp index 77a6df28..3c389abc 100644 --- a/common/JackDebugClient.cpp +++ b/common/JackDebugClient.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -116,17 +116,17 @@ int JackDebugClient::Close() void JackDebugClient::CheckClient(const char* function_name) const { *fStream << "CheckClient : " << function_name << ", calling thread : " << pthread_self() << endl; - + if (fIsClosed > 0) { - *fStream << "!!! ERROR !!! : Accessing a client '" << fClientName << "' already closed " << "from " << function_name << endl; + *fStream << "!!! ERROR !!! : Accessing a client '" << fClientName << "' already closed " << "from " << function_name << endl; *fStream << "This is likely to cause crash !'" << endl; #ifdef __APPLE__ // Debugger(); - #endif + #endif } } -pthread_t JackDebugClient::GetThreadID() +jack_native_thread_t JackDebugClient::GetThreadID() { CheckClient("GetThreadID"); return fClient->GetThreadID(); @@ -428,7 +428,7 @@ void JackDebugClient::OnInfoShutdown(JackInfoShutdownCallback callback, void *ar CheckClient("OnInfoShutdown"); fClient->OnInfoShutdown(callback, arg); } - + int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg) { JackDebugClient* client = (JackDebugClient*)arg; diff --git a/common/JackDebugClient.h b/common/JackDebugClient.h index fc9ebf55..6a19deca 100644 --- a/common/JackDebugClient.h +++ b/common/JackDebugClient.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -84,7 +84,7 @@ class JackDebugClient : public JackClient int SetBufferSize(jack_nframes_t buffer_size); int SetFreeWheel(int onoff); void ShutDown(); - pthread_t GetThreadID(); + jack_native_thread_t GetThreadID(); // Port management int PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size); diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index a485d810..a2c6ccd6 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -167,7 +167,7 @@ int JackDriver::Open(jack_nframes_t buffer_size, int JackDriver::Close() { - if (fClientControl.fRefNum >= 0) { + if (fClientControl.fRefNum >= 0) { jack_log("JackDriver::Close"); fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync fClientControl.fActive = false; @@ -207,7 +207,7 @@ int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, jack_log("JackDriver::kStopFreewheel"); SetupDriverSync(fClientControl.fRefNum, false); break; - } + } return 0; } @@ -223,13 +223,13 @@ void JackDriver::CycleIncTime() } void JackDriver::CycleTakeBeginTime() -{ +{ fBeginDateUst = GetMicroSeconds(); // Take callback date here fEngineControl->CycleIncTime(fBeginDateUst); } void JackDriver::CycleTakeEndTime() -{ +{ fEndDateUst = GetMicroSeconds(); // Take end date here } @@ -254,7 +254,7 @@ void JackDriver::NotifySampleRate(jack_nframes_t sample_rate) fEngine->NotifySampleRate(sample_rate); fEngineControl->InitFrameTime(); } - + void JackDriver::NotifyFailure(int code, const char* reason) { fEngine->NotifyFailure(code, reason); diff --git a/common/JackDriver.h b/common/JackDriver.h index 901e6bf3..6f230831 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -1,21 +1,21 @@ /* Copyright (C) 2001 Paul Davis Copyright (C) 2004-2008 Grame - + 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 __JackDriver__ @@ -30,27 +30,27 @@ namespace Jack { - + class JackLockedEngine; class JackGraphManager; struct JackEngineControl; - + /*! \brief The base interface for drivers. */ - + class SERVER_EXPORT JackDriverInterface { public: - + JackDriverInterface() {} virtual ~JackDriverInterface() {} - + virtual int Open() = 0; - + virtual int Open (bool capturing, bool playing, int inchannels, @@ -60,7 +60,7 @@ class SERVER_EXPORT JackDriverInterface const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency) = 0; - + virtual int Open(jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, @@ -72,30 +72,30 @@ class SERVER_EXPORT JackDriverInterface const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency) = 0; - + virtual int Attach() = 0; virtual int Detach() = 0; - + virtual int Read() = 0; virtual int Write() = 0; - + virtual int Start() = 0; virtual int Stop() = 0; - + virtual bool IsFixedBufferSize() = 0; virtual int SetBufferSize(jack_nframes_t buffer_size) = 0; virtual int SetSampleRate(jack_nframes_t sample_rate) = 0; - + virtual int Process() = 0; virtual int ProcessNull() = 0; - + virtual void SetMaster(bool onoff) = 0; virtual bool GetMaster() = 0; virtual void AddSlave(JackDriverInterface* slave) = 0; virtual void RemoveSlave(JackDriverInterface* slave) = 0; virtual std::list GetSlaves() = 0; virtual int ProcessSlaves() = 0; - + virtual bool IsRealTime() const = 0; }; @@ -109,16 +109,16 @@ class SERVER_EXPORT JackDriverClientInterface : public JackDriverInterface, publ /*! \brief The base class for drivers. */ - -#define CaptureDriverFlags static_cast(JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal | JackPortIsActive) -#define PlaybackDriverFlags static_cast(JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal | JackPortIsActive) -#define MonitorDriverFlags static_cast(JackPortIsOutput | JackPortIsActive) + +#define CaptureDriverFlags static_cast(JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal) +#define PlaybackDriverFlags static_cast(JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal) +#define MonitorDriverFlags static_cast(JackPortIsOutput) class SERVER_EXPORT JackDriver : public JackDriverClientInterface { - + protected: - + char fCaptureDriverName[JACK_CLIENT_NAME_SIZE + 1]; char fPlaybackDriverName[JACK_CLIENT_NAME_SIZE + 1]; char fAliasName[JACK_CLIENT_NAME_SIZE + 1]; @@ -134,27 +134,27 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface JackClientControl fClientControl; std::list fSlaveList; bool fIsMaster; - + void CycleIncTime(); void CycleTakeBeginTime(); void CycleTakeEndTime(); - + void SetupDriverSync(int ref, bool freewheel); - + void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); // XRun notification sent by the driver void NotifyBufferSize(jack_nframes_t buffer_size); // BufferSize notification sent by the driver void NotifySampleRate(jack_nframes_t sample_rate); // SampleRate notification sent by the driver void NotifyFailure(int code, const char* reason); // Failure notification sent by the driver - + public: - + JackDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); JackDriver(); virtual ~JackDriver(); - + void SetMaster(bool onoff); bool GetMaster(); - + void AddSlave(JackDriverInterface* slave); void RemoveSlave(JackDriverInterface* slave); std::list GetSlaves() @@ -162,9 +162,9 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface return fSlaveList; } int ProcessSlaves(); - + virtual int Open(); - + virtual int Open (bool capturing, bool playing, int inchannels, @@ -174,7 +174,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency); - + virtual int Open(jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, @@ -187,31 +187,31 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface jack_nframes_t capture_latency, jack_nframes_t playback_latency); virtual int Close(); - + virtual int Process(); virtual int ProcessNull(); - + virtual int Attach(); virtual int Detach(); - + virtual int Read(); virtual int Write(); - + virtual int Start(); virtual int Stop(); - + virtual bool IsFixedBufferSize(); virtual int SetBufferSize(jack_nframes_t buffer_size); virtual int SetSampleRate(jack_nframes_t sample_rate); - + virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); virtual JackClientControl* GetClientControl() const; - + virtual bool IsRealTime() const; - virtual bool Initialize(); // To be called by the wrapping thread Init method when the driver is a "blocking" one - + virtual bool Initialize(); // To be called by the wrapping thread Init method when the driver is a "blocking" one + }; - + } // end of namespace #endif diff --git a/common/JackDummyDriver.cpp b/common/JackDummyDriver.cpp index 5f31cb88..fb996a11 100644 --- a/common/JackDummyDriver.cpp +++ b/common/JackDummyDriver.cpp @@ -56,6 +56,12 @@ int JackDummyDriver::Open(jack_nframes_t buffer_size, fEngineControl->fPeriod = 0; fEngineControl->fComputation = 500 * 1000; fEngineControl->fConstraint = 500 * 1000; + int buffer_size = int((fWaitTime * fEngineControl->fSampleRate) / 1000000.0f); + if (buffer_size > BUFFER_SIZE_MAX) { + buffer_size = BUFFER_SIZE_MAX; + jack_error("Buffer size set to %d ", BUFFER_SIZE_MAX); + } + SetBufferSize(buffer_size); return 0; } else { return -1; diff --git a/common/JackEngine.cpp b/common/JackEngine.cpp index 28f54432..338e5a42 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include +#include #include #include "JackSystemDeps.h" @@ -90,7 +91,7 @@ int JackEngine::Close() return 0; } - + void JackEngine::NotifyQuit() { fChannel.NotifyQuit(); @@ -137,8 +138,10 @@ void JackEngine::ReleaseRefnum(int ref) void JackEngine::ProcessNext(jack_time_t cur_cycle_begin) { fLastSwitchUsecs = cur_cycle_begin; - if (fGraphManager->RunNextGraph()) // True if the graph actually switched to a new state + if (fGraphManager->RunNextGraph()) { // True if the graph actually switched to a new state fChannel.Notify(ALL_CLIENTS, kGraphOrderCallback, 0); + //NotifyGraphReorder(); + } fSignal.Signal(); // Signal for threads waiting for next cycle } @@ -195,16 +198,44 @@ void JackEngine::CheckXRun(jack_time_t callback_usecs) // REVOIR les conditions if (status != NotTriggered && status != Finished) { jack_error("JackEngine::XRun: client = %s was not run: state = %ld", client->GetClientControl()->fName, status); fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); // Notify all clients + //NotifyXRun(ALL_CLIENTS); } if (status == Finished && (long)(finished_date - callback_usecs) > 0) { jack_error("JackEngine::XRun: client %s finished after current callback", client->GetClientControl()->fName); fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); // Notify all clients + //NotifyXRun(ALL_CLIENTS); } } } } +int JackEngine::ComputeTotalLatencies() +{ + std::vector sorted; + std::vector::iterator it; + std::vector::reverse_iterator rit; + + fGraphManager->TopologicalSort(sorted); + + /* iterate over all clients in graph order, and emit + * capture latency callback. + */ + + for (it = sorted.begin(); it != sorted.end(); it++) { + jack_log("Sorted %d", *it); + NotifyClient(*it, kLatencyCallback, true, "", 0, 0); + } + + /* now issue playback latency callbacks in reverse graph order. + */ + for (rit = sorted.rbegin(); rit != sorted.rend(); rit++) { + NotifyClient(*rit, kLatencyCallback, true, "", 1, 0); + } + + return 0; +} + //--------------- // Notifications //--------------- @@ -215,8 +246,8 @@ void JackEngine::NotifyClient(int refnum, int event, int sync, const char* messa // The client may be notified by the RT thread while closing if (client) { - - if (client && client->GetClientControl()->fCallback[event]) { + + if (client->GetClientControl()->fCallback[event]) { /* Important for internal clients : unlock before calling the notification callbacks. */ @@ -225,7 +256,7 @@ void JackEngine::NotifyClient(int refnum, int event, int sync, const char* messa jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2); if (res) fMutex.Lock(); - + } else { jack_log("JackEngine::NotifyClient: no callback for event = %ld", event); } @@ -277,6 +308,7 @@ void JackEngine::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) // Use the audio thread => request thread communication channel fEngineControl->NotifyXRun(callback_usecs, delayed_usecs); fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); + //NotifyXRun(ALL_CLIENTS); } void JackEngine::NotifyXRun(int refnum) @@ -290,6 +322,7 @@ void JackEngine::NotifyXRun(int refnum) void JackEngine::NotifyGraphReorder() { + ComputeTotalLatencies(); NotifyClients(kGraphOrderCallback, false, "", 0, 0); } @@ -307,7 +340,7 @@ void JackEngine::NotifyFailure(int code, const char* reason) { NotifyClients(kShutDownCallback, false, reason, code, 0); } - + void JackEngine::NotifyFreewheel(bool onoff) { if (onoff) { @@ -406,7 +439,7 @@ int JackEngine::ClientCheck(const char* name, int uuid, char* name_res, int prot std::map::iterator res = fReservationMap.find(uuid); if (res != fReservationMap.end()) { - strncpy( name_res, res->second.c_str(), JACK_CLIENT_NAME_SIZE ); + strncpy(name_res, res->second.c_str(), JACK_CLIENT_NAME_SIZE); } else if (ClientCheckName(name)) { *status |= JackNameNotUnique; @@ -467,7 +500,7 @@ bool JackEngine::ClientCheckName(const char* name) return true; } - for (std::map::iterator i=fReservationMap.begin(); i!=fReservationMap.end(); i++) { + for (std::map::iterator i = fReservationMap.begin(); i != fReservationMap.end(); i++) { if (i->second == name) return true; } @@ -522,14 +555,14 @@ int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref if (uuid < 0) { uuid = GetNewUUID(); - strncpy( real_name, name, JACK_CLIENT_NAME_SIZE ); + strncpy(real_name, name, JACK_CLIENT_NAME_SIZE); } else { std::map::iterator res = fReservationMap.find(uuid); if (res != fReservationMap.end()) { - strncpy( real_name, res->second.c_str(), JACK_CLIENT_NAME_SIZE ); + strncpy(real_name, res->second.c_str(), JACK_CLIENT_NAME_SIZE); fReservationMap.erase(uuid); } else { - strncpy( real_name, name, JACK_CLIENT_NAME_SIZE ); + strncpy(real_name, name, JACK_CLIENT_NAME_SIZE); } EnsureUUID(uuid); @@ -689,7 +722,7 @@ int JackEngine::ClientActivate(int refnum, bool is_real_time) { JackClientInterface* client = fClientTable[refnum]; jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName); - + if (is_real_time) fGraphManager->Activate(refnum); @@ -702,18 +735,10 @@ int JackEngine::ClientActivate(int refnum, bool is_real_time) jack_int_t output_ports[PORT_NUM_FOR_CLIENT]; fGraphManager->GetInputPorts(refnum, input_ports); fGraphManager->GetOutputPorts(refnum, output_ports); - - // First add port state to JackPortIsActive - for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { - fGraphManager->ActivatePort(input_ports[i]); - } - for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { - fGraphManager->ActivatePort(output_ports[i]); - } - + // Notify client NotifyActivate(refnum); - + // Then issue port registration notification for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { NotifyPortRegistation(input_ports[i], true); @@ -740,13 +765,11 @@ int JackEngine::ClientDeactivate(int refnum) // First disconnect all ports and remove their JackPortIsActive state for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { PortDisconnect(refnum, input_ports[i], ALL_PORTS); - fGraphManager->DeactivatePort(input_ports[i]); } for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { PortDisconnect(refnum, output_ports[i], ALL_PORTS); - fGraphManager->DeactivatePort(output_ports[i]); } - + // Then issue port registration notification for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { NotifyPortRegistation(input_ports[i], false); @@ -867,7 +890,7 @@ int JackEngine::PortDisconnect(int refnum, const char* src, const char* dst) int JackEngine::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst) { jack_log("JackEngine::PortDisconnect src = %d dst = %d", src, dst); - + if (dst == ALL_PORTS) { jack_int_t connections[CONNECTION_NUM_FOR_PORT]; @@ -910,6 +933,10 @@ int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) return 0; } +//-------------------- +// Session management +//-------------------- + void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket) { if (fSessionPendingReplies != 0) { @@ -940,11 +967,11 @@ void JackEngine::SessionNotify(int refnum, const char *target, jack_session_even char path_buf[JACK_PORT_NAME_SIZE]; snprintf( path_buf, sizeof(path_buf), "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR ); - + int res = JackTools::MkDir(path_buf); - if (res) + if (res) jack_error( "JackEngine::SessionNotify: can not create session directory '%s'", path_buf ); - + int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int) type, 0); if (result == 2) { @@ -952,9 +979,9 @@ void JackEngine::SessionNotify(int refnum, const char *target, jack_session_even } else if (result == 1) { char uuid_buf[JACK_UUID_SIZE]; snprintf( uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID ); - fSessionResult->fCommandList.push_back( JackSessionCommand( uuid_buf, + fSessionResult->fCommandList.push_back( JackSessionCommand( uuid_buf, client->GetClientControl()->fName, - client->GetClientControl()->fSessionCommand, + client->GetClientControl()->fSessionCommand, client->GetClientControl()->fSessionFlags )); } } @@ -973,11 +1000,11 @@ void JackEngine::SessionReply(int refnum) { JackClientInterface* client = fClientTable[refnum]; char uuid_buf[JACK_UUID_SIZE]; - snprintf( uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID ); - fSessionResult->fCommandList.push_back( JackSessionCommand( uuid_buf, - client->GetClientControl()->fName, - client->GetClientControl()->fSessionCommand, - client->GetClientControl()->fSessionFlags )); + snprintf( uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID); + fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf, + client->GetClientControl()->fName, + client->GetClientControl()->fSessionCommand, + client->GetClientControl()->fSessionFlags)); fSessionPendingReplies -= 1; if (fSessionPendingReplies == 0) { @@ -998,9 +1025,8 @@ void JackEngine::GetUUIDForClientName(const char *client_name, char *uuid_res, i return; } } - // did not find name. + // Did not find name. *result = -1; - return; } void JackEngine::GetClientNameForUUID(const char *uuid, char *name_res, int *result) @@ -1020,18 +1046,17 @@ void JackEngine::GetClientNameForUUID(const char *uuid, char *name_res, int *res return; } } - // did not find uuid. + // Did not find uuid. *result = -1; - return; } void JackEngine::ReserveClientName(const char *name, const char *uuid, int *result) { - jack_log( "JackEngine::ReserveClientName ( name = %s, uuid = %s )", name, uuid ); + jack_log("JackEngine::ReserveClientName ( name = %s, uuid = %s )", name, uuid); if (ClientCheckName(name)) { *result = -1; - jack_log( "name already taken" ); + jack_log("name already taken"); return; } @@ -1040,5 +1065,21 @@ void JackEngine::ReserveClientName(const char *name, const char *uuid, int *resu *result = 0; } +void JackEngine::ClientHasSessionCallbackRequest(const char *name, int *result) +{ + JackClientInterface* client = NULL; + for (int i = 0; i < CLIENT_NUM; i++) { + JackClientInterface* client = fClientTable[i]; + if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) + break; + } + + if (client) { + *result = client->GetClientControl()->fCallback[kSessionCallback]; + } else { + *result = -1; + } +} + } // end of namespace diff --git a/common/JackEngine.h b/common/JackEngine.h index ae969cb7..185c1b16 100644 --- a/common/JackEngine.h +++ b/common/JackEngine.h @@ -129,6 +129,8 @@ class SERVER_EXPORT JackEngine : public JackLockAble int PortRename(int refnum, jack_port_id_t port, const char* name); + int ComputeTotalLatencies(); + // Graph bool Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end); @@ -142,12 +144,14 @@ class SERVER_EXPORT JackEngine : public JackLockAble void NotifyFreewheel(bool onoff); void NotifyQuit(); - void SessionNotify( int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket ); - void SessionReply( int refnum ); + // Session management + void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket); + void SessionReply(int refnum); void GetUUIDForClientName(const char *client_name, char *uuid_res, int *result); void GetClientNameForUUID(const char *uuid, char *name_res, int *result); void ReserveClientName(const char *name, const char *uuid, int *result); + void ClientHasSessionCallbackRequest(const char *name, int *result); }; diff --git a/common/JackEngineControl.cpp b/common/JackEngineControl.cpp index db13ae78..d9ab2b16 100644 --- a/common/JackEngineControl.cpp +++ b/common/JackEngineControl.cpp @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -33,39 +33,39 @@ static inline jack_time_t JACK_MAX(jack_time_t a, jack_time_t b) return (a < b) ? b : a; } -void JackEngineControl::CalcCPULoad(JackClientInterface** table, - JackGraphManager* manager, - jack_time_t cur_cycle_begin, +void JackEngineControl::CalcCPULoad(JackClientInterface** table, + JackGraphManager* manager, + jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end) { fPrevCycleTime = fCurCycleTime; fCurCycleTime = cur_cycle_begin; jack_time_t last_cycle_end = prev_cycle_end; - + // In Asynchronous mode, last cycle end is the max of client end dates if (!fSyncMode) { for (int i = fDriverNum; i < CLIENT_NUM; i++) { JackClientInterface* client = table[i]; JackClientTiming* timing = manager->GetClientTiming(i); - if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) + if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) last_cycle_end = JACK_MAX(last_cycle_end, timing->fFinishedAt); } } - // Store the execution time for later averaging + // Store the execution time for later averaging fRollingClientUsecs[fRollingClientUsecsIndex++] = last_cycle_end - fPrevCycleTime; - if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) + if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) fRollingClientUsecsIndex = 0; - + // Every so often, recompute the current maximum use over the // last JACK_ENGINE_ROLLING_COUNT client iterations. - + if (++fRollingClientUsecsCnt % fRollingInterval == 0) { jack_time_t max_usecs = 0; - for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) + for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) max_usecs = JACK_MAX(fRollingClientUsecs[i], max_usecs); - + fMaxUsecs = JACK_MAX(fMaxUsecs, max_usecs); fSpareUsecs = jack_time_t((max_usecs < fPeriodUsecs) ? fPeriodUsecs - max_usecs : 0); fCPULoad = ((1.f - (float(fSpareUsecs) / float(fPeriodUsecs))) * 50.f + (fCPULoad * 0.5f)); @@ -80,7 +80,7 @@ void JackEngineControl::ResetRollingUsecs() fSpareUsecs = 0; fRollingInterval = int(floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.f) / fPeriodUsecs)); } - + void JackEngineControl::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) { ResetFrameTime(callback_usecs); @@ -88,5 +88,5 @@ void JackEngineControl::NotifyXRun(jack_time_t callback_usecs, float delayed_use if (delayed_usecs > fMaxDelayedUsecs) fMaxDelayedUsecs = delayed_usecs; } - + } // end of namespace diff --git a/common/JackError.h b/common/JackError.h index 425266f9..15e39f86 100644 --- a/common/JackError.h +++ b/common/JackError.h @@ -7,12 +7,12 @@ it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -25,7 +25,6 @@ #include #include #include "JackCompilerDeps.h" -#include "types.h" #ifdef __cplusplus extern "C" @@ -44,17 +43,17 @@ extern "C" EXPORT extern void (*jack_error_callback)(const char *desc); EXPORT extern void (*jack_info_callback)(const char *desc); - + EXPORT extern void default_jack_error_callback(const char *desc); EXPORT extern void default_jack_info_callback(const char *desc); - + EXPORT extern void silent_jack_error_callback(const char *desc); EXPORT extern void silent_jack_info_callback(const char *desc); typedef void (* jack_log_function_t)(int level, const char *message); void jack_log_function(int level, const char *message); - + EXPORT int set_threaded_log_function(); #ifdef __cplusplus diff --git a/common/JackFrameTimer.h b/common/JackFrameTimer.h index aca70add..afac2f78 100644 --- a/common/JackFrameTimer.h +++ b/common/JackFrameTimer.h @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -36,9 +36,9 @@ class SERVER_EXPORT JackTimer { friend class JackFrameTimer; - - private: - + + private: + jack_nframes_t fFrames; jack_time_t fCurrentWakeup; jack_time_t fCurrentCallback; @@ -47,21 +47,21 @@ class SERVER_EXPORT JackTimer float fFilterCoefficient; /* set once, never altered */ bool fInitialized; - public: - + public: + JackTimer(); ~JackTimer() {} - + jack_nframes_t Time2Frames(jack_time_t time, jack_nframes_t buffer_size); jack_time_t Frames2Time(jack_nframes_t frames, jack_nframes_t buffer_size); jack_nframes_t FramesSinceCycleStart(jack_time_t cur_time, jack_nframes_t frames_rate); - + jack_nframes_t CurFrame() { return fFrames; } - + jack_time_t CurTime() { return fCurrentWakeup; @@ -75,7 +75,7 @@ class SERVER_EXPORT JackTimer class SERVER_EXPORT JackFrameTimer : public JackAtomicState { - + private: bool fFirstWakeUp; @@ -93,7 +93,7 @@ class SERVER_EXPORT JackFrameTimer : public JackAtomicState void ResetFrameTime(jack_nframes_t frames_rate, jack_time_t callback_usecs, jack_time_t period_usecs); void IncFrameTime(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs); void ReadFrameTime(JackTimer* timer); - + } POST_PACKED_STRUCTURE; diff --git a/common/JackGraphManager.cpp b/common/JackGraphManager.cpp index 1a92191c..451d8cce 100644 --- a/common/JackGraphManager.cpp +++ b/common/JackGraphManager.cpp @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -37,7 +37,7 @@ static void AssertBufferSize(jack_nframes_t buffer_size) assert(buffer_size <= BUFFER_SIZE_MAX); } } - + void JackGraphManager::AssertPort(jack_port_id_t port_index) { if (port_index >= fPortMax) { @@ -45,7 +45,7 @@ void JackGraphManager::AssertPort(jack_port_id_t port_index) assert(port_index < fPortMax); } } - + JackGraphManager* JackGraphManager::Allocate(int port_max) { // Using "Placement" new @@ -59,18 +59,18 @@ void JackGraphManager::Destroy(JackGraphManager* manager) manager->~JackGraphManager(); JackShmMem::operator delete(manager); } - -JackGraphManager::JackGraphManager(int port_max) + +JackGraphManager::JackGraphManager(int port_max) { assert(port_max <= PORT_NUM_MAX); - + for (int i = 0; i < port_max; i++) { fPortArray[i].Release(); } - + fPortMax = port_max; } - + JackPort* JackGraphManager::GetPort(jack_port_id_t port_index) { AssertPort(port_index); @@ -127,6 +127,19 @@ int JackGraphManager::SuspendRefNum(JackClientControl* control, JackSynchro* tab return manager->SuspendRefNum(control, table, fClientTiming, usec); } +void JackGraphManager::TopologicalSort(std::vector& sorted) +{ + UInt16 cur_index; + UInt16 next_index; + + do { + cur_index = GetCurrentIndex(); + sorted.clear(); + ReadCurrentState()->TopologicalSort(sorted); + next_index = GetCurrentIndex(); + } while (cur_index != next_index); // Until a coherent state has been read +} + // Server void JackGraphManager::DirectConnect(int ref1, int ref2) { @@ -176,14 +189,14 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff jack_int_t len = manager->Connections(port_index); // No connections : return a zero-filled buffer - if (len == 0) { + if (len == 0) { port->ClearBuffer(buffer_size); return port->GetBuffer(); - + // One connection - } else if (len == 1) { + } else if (len == 1) { jack_port_id_t src_index = manager->GetPort(port_index, 0); - + // Ports in same client : copy the buffer if (GetPort(src_index)->GetRefNum() == port->GetRefNum()) { void* buffers[1]; @@ -194,10 +207,10 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff } else { return GetBuffer(src_index, buffer_size); } - + // Multiple connections : mix all buffers - } else { - + } else { + const jack_int_t* connections = manager->GetConnections(port_index); void* buffers[CONNECTION_NUM_FOR_PORT]; jack_port_id_t src_index; @@ -220,10 +233,10 @@ int JackGraphManager::RequestMonitor(jack_port_id_t port_index, bool onoff) // C JackPort* port = GetPort(port_index); /** - jackd.h + jackd.h * If @ref JackPortCanMonitor is set for this @a port, turn input * monitoring on or off. Otherwise, do nothing. - + if (!(fFlags & JackPortCanMonitor)) return -1; */ @@ -245,7 +258,7 @@ int JackGraphManager::RequestMonitor(jack_port_id_t port_index, bool onoff) // C // Client jack_nframes_t JackGraphManager::ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count) { - const jack_int_t* connections = manager->GetConnections(port_index); + const jack_int_t* connections = ReadCurrentState()->GetConnections(port_index); jack_nframes_t max_latency = 0; jack_port_id_t dst_index; @@ -296,6 +309,46 @@ int JackGraphManager::ComputeTotalLatencies() return 0; } +void JackGraphManager::RecalculateLatencyAux(jack_port_id_t port_index, jack_latency_callback_mode_t mode) +{ + const jack_int_t* connections = ReadCurrentState()->GetConnections(port_index); + JackPort* port = GetPort(port_index); + jack_latency_range_t latency = { UINT32_MAX, 0 }; + jack_port_id_t dst_index; + + for (int i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((dst_index = connections[i]) != EMPTY); i++) { + AssertPort(dst_index); + JackPort* dst_port = GetPort(dst_index); + jack_latency_range_t other_latency; + + dst_port->GetLatencyRange(mode, &other_latency); + + if (other_latency.max > latency.max) + latency.max = other_latency.max; + if (other_latency.min < latency.min) + latency.min = other_latency.min; + } + + if (latency.min == UINT32_MAX) + latency.min = 0; + + port->SetLatencyRange(mode, &latency); +} + +void JackGraphManager::RecalculateLatency(jack_port_id_t port_index, jack_latency_callback_mode_t mode) +{ + UInt16 cur_index; + UInt16 next_index; + + do { + cur_index = GetCurrentIndex(); + RecalculateLatencyAux(port_index, mode); + next_index = GetCurrentIndex(); + } while (cur_index != next_index); // Until a coherent state has been read + + jack_log("JackGraphManager::RecalculateLatency port_index = %ld", port_index); +} + // Server void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size) { @@ -376,18 +429,6 @@ int JackGraphManager::ReleasePort(int refnum, jack_port_id_t port_index) return res; } -void JackGraphManager::ActivatePort(jack_port_id_t port_index) -{ - JackPort* port = GetPort(port_index); - port->fFlags = (JackPortFlags)(port->fFlags | JackPortIsActive); -} - -void JackGraphManager::DeactivatePort(jack_port_id_t port_index) -{ - JackPort* port = GetPort(port_index); - port->fFlags = (JackPortFlags)(port->fFlags & ~JackPortIsActive); -} - void JackGraphManager::GetInputPorts(int refnum, jack_int_t* res) { JackConnectionManager* manager = WriteNextStateStart(); @@ -430,7 +471,7 @@ void JackGraphManager::RemoveAllPorts(int refnum) jack_error("JackGraphManager::RemoveAllPorts failure ref = %ld port_index = %ld", refnum, port_index); assert(true); break; - } + } } WriteNextStateStop(); @@ -717,7 +758,7 @@ void JackGraphManager::GetConnectionsAux(JackConnectionManager* manager, const c const jack_int_t* connections = manager->GetConnections(port_index); jack_int_t index; int i; - + // Cleanup connection array memset(res, 0, sizeof(char*) * CONNECTION_NUM_FOR_PORT); @@ -740,7 +781,7 @@ const char** JackGraphManager::GetConnections(jack_port_id_t port_index) { const char** res = (const char**)malloc(sizeof(char*) * CONNECTION_NUM_FOR_PORT); UInt16 cur_index, next_index; - + if (!res) return NULL; @@ -763,7 +804,7 @@ void JackGraphManager::GetPortsAux(const char** matching_ports, const char* port { int match_cnt = 0; regex_t port_regex, type_regex; - + if (port_name_pattern && port_name_pattern[0]) { regcomp(&port_regex, port_name_pattern, REG_EXTENDED | REG_NOSUB); } @@ -823,15 +864,15 @@ const char** JackGraphManager::GetPorts(const char* port_name_pattern, const cha { const char** res = (const char**)malloc(sizeof(char*) * fPortMax); UInt16 cur_index, next_index; - + if (!res) return NULL; - + do { cur_index = GetCurrentIndex(); GetPortsAux(res, port_name_pattern, type_name_pattern, flags); next_index = GetCurrentIndex(); - } while (cur_index != next_index); // Until a coherent state has been read + } while (cur_index != next_index); // Until a coherent state has been read if (res[0]) { // at least one port return res; diff --git a/common/JackGraphManager.h b/common/JackGraphManager.h index 93b09ff9..5db84209 100644 --- a/common/JackGraphManager.h +++ b/common/JackGraphManager.h @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -29,14 +29,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackPlatformPlug.h" #include "JackSystemDeps.h" - namespace Jack { /*! \brief Graph manager: contains the connection manager and the port array. */ - + class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState { @@ -53,6 +52,7 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState float* GetBuffer(jack_port_id_t port_index); void* GetBufferAux(JackConnectionManager* manager, jack_port_id_t port_index, jack_nframes_t frames); jack_nframes_t ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count); + void RecalculateLatencyAux(jack_port_id_t port_index, jack_latency_callback_mode_t mode); public: @@ -65,8 +65,6 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState // Ports management jack_port_id_t AllocatePort(int refnum, const char* port_name, const char* port_type, JackPortFlags flags, jack_nframes_t buffer_size); int ReleasePort(int refnum, jack_port_id_t port_index); - void ActivatePort(jack_port_id_t port_index); - void DeactivatePort(jack_port_id_t port_index); void GetInputPorts(int refnum, jack_int_t* res); void GetOutputPorts(int refnum, jack_int_t* res); void RemoveAllPorts(int refnum); @@ -74,10 +72,13 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState JackPort* GetPort(jack_port_id_t index); jack_port_id_t GetPort(const char* name); + int ComputeTotalLatency(jack_port_id_t port_index); int ComputeTotalLatencies(); + void RecalculateLatency(jack_port_id_t port_index, jack_latency_callback_mode_t mode); + int RequestMonitor(jack_port_id_t port_index, bool onoff); - + // Connections management int Connect(jack_port_id_t src_index, jack_port_id_t dst_index); int Disconnect(jack_port_id_t src_index, jack_port_id_t dst_index); @@ -122,6 +123,7 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState void InitRefNum(int refnum); int ResumeRefNum(JackClientControl* control, JackSynchro* table); int SuspendRefNum(JackClientControl* control, JackSynchro* table, long usecs); + void TopologicalSort(std::vector& sorted); JackClientTiming* GetClientTiming(int refnum) { @@ -130,7 +132,7 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState void Save(JackConnectionManager* dst); void Restore(JackConnectionManager* src); - + static JackGraphManager* Allocate(int port_max); static void Destroy(JackGraphManager* manager); diff --git a/common/JackInternalClientChannel.h b/common/JackInternalClientChannel.h index 8deb6b7b..6b0772ce 100644 --- a/common/JackInternalClientChannel.h +++ b/common/JackInternalClientChannel.h @@ -80,7 +80,6 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface { *result = fEngine->PortUnRegister(refnum, port_index); } - void PortConnect(int refnum, const char* src, const char* dst, int* result) { *result = fEngine->PortConnect(refnum, src, dst); @@ -89,7 +88,6 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface { *result = fEngine->PortDisconnect(refnum, src, dst); } - void PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) { *result = fEngine->PortConnect(refnum, src, dst); @@ -111,10 +109,9 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface { *result = fServer->SetFreewheel(onoff); } - - void SessionNotify( int refnum, const char *target, jack_session_event_type_t type, const char *path, jack_session_command_t **result ) + void ComputeTotalLatencies(int* result) { - *result = NULL; + *result = fEngine->ComputeTotalLatencies(); } void ReleaseTimebase(int refnum, int* result) @@ -126,7 +123,7 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface { *result = fServer->SetTimebaseCallback(refnum, conditional); } - + void GetInternalClientName(int refnum, int int_ref, char* name_res, int* result) { *result = fEngine->GetInternalClientName(int_ref, name_res); @@ -139,7 +136,7 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface void InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, int* result) { - *result = fServer->InternalClientLoad(client_name, so_name, objet_data, options, int_ref, uuid, status); + *result = fServer->InternalClientLoad(client_name, so_name, objet_data, options, int_ref, uuid, status); } void InternalClientUnload(int refnum, int int_ref, int* status, int* result) @@ -147,6 +144,12 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface *result = fEngine->InternalClientUnload(int_ref, status); } + void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, jack_session_command_t** result) + { + *result = NULL; + } + + }; } // end of namespace diff --git a/common/JackLockedEngine.h b/common/JackLockedEngine.h index b1620859..c311f57d 100644 --- a/common/JackLockedEngine.h +++ b/common/JackLockedEngine.h @@ -66,7 +66,7 @@ catch (...) { \brief Locked Engine, access to methods is serialized using a mutex. */ -class SERVER_EXPORT JackLockedEngine +class SERVER_EXPORT JackLockedEngine { private: @@ -94,7 +94,7 @@ class SERVER_EXPORT JackLockedEngine return fEngine.Close(); CATCH_EXCEPTION_RETURN } - + // Client management int ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status) { @@ -226,6 +226,14 @@ class SERVER_EXPORT JackLockedEngine CATCH_EXCEPTION_RETURN } + int ComputeTotalLatencies() + { + TRY_CALL + JackLock lock(&fEngine); + return fEngine.ComputeTotalLatencies(); + CATCH_EXCEPTION_RETURN + } + // Graph bool Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end) { @@ -245,7 +253,7 @@ class SERVER_EXPORT JackLockedEngine // RT : no lock fEngine.NotifyXRun(refnum); } - + void NotifyGraphReorder() { TRY_CALL @@ -298,7 +306,7 @@ class SERVER_EXPORT JackLockedEngine return fEngine.GetClientRefNum(name); CATCH_EXCEPTION_RETURN } - + void NotifyQuit() { TRY_CALL @@ -314,7 +322,7 @@ class SERVER_EXPORT JackLockedEngine fEngine.SessionNotify(refnum, target, type, path, socket); CATCH_EXCEPTION } - + void SessionReply(int refnum) { TRY_CALL @@ -322,7 +330,7 @@ class SERVER_EXPORT JackLockedEngine fEngine.SessionReply(refnum); CATCH_EXCEPTION } - + void GetUUIDForClientName(const char *client_name, char *uuid_res, int *result) { TRY_CALL @@ -344,6 +352,14 @@ class SERVER_EXPORT JackLockedEngine fEngine.ReserveClientName(name, uuid, result); CATCH_EXCEPTION } + + void ClientHasSessionCallbackRequest(const char *name, int *result) + { + TRY_CALL + JackLock lock(&fEngine); + fEngine.ClientHasSessionCallbackRequest(name, result); + CATCH_EXCEPTION + } }; } // end of namespace diff --git a/common/JackMessageBuffer.cpp b/common/JackMessageBuffer.cpp index b9f28463..d867933d 100644 --- a/common/JackMessageBuffer.cpp +++ b/common/JackMessageBuffer.cpp @@ -2,19 +2,19 @@ * Copyright (C) 2004 Rui Nuno Capela, Steve Harris * Copyright (C) 2008 Nedko Arnaudov * Copyright (C) 2008 Grame - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ @@ -34,7 +34,7 @@ JackMessageBuffer::JackMessageBuffer() JackMessageBuffer::~JackMessageBuffer() {} - + void JackMessageBuffer::Start() { fRunning = true; @@ -44,9 +44,9 @@ void JackMessageBuffer::Start() void JackMessageBuffer::Stop() { if (fOverruns > 0) { - jack_error("WARNING: %d message buffer overruns!", fOverruns); + jack_error("WARNING: %d message buffer overruns!", fOverruns); } else { - jack_log("no message buffer overruns"); + jack_log("no message buffer overruns"); } fGuard.Lock(); fRunning = false; @@ -55,7 +55,7 @@ void JackMessageBuffer::Stop() fThread.Stop(); Flush(); } - + void JackMessageBuffer::Flush() { while (fOutBuffer != fInBuffer) { @@ -76,7 +76,7 @@ void JackMessageBuffer::AddMessage(int level, const char *message) INC_ATOMIC(&fOverruns); } } - + bool JackMessageBuffer::Execute() { while (fRunning) { @@ -94,10 +94,10 @@ bool JackMessageBuffer::Execute() Flush(); fGuard.Unlock(); } - return false; + return false; } -void JackMessageBuffer::Create() +void JackMessageBuffer::Create() { if (fInstance == NULL) { fInstance = new JackMessageBuffer(); @@ -105,7 +105,7 @@ void JackMessageBuffer::Create() } } -void JackMessageBuffer::Destroy() +void JackMessageBuffer::Destroy() { if (fInstance != NULL) { fInstance->Stop(); @@ -114,7 +114,7 @@ void JackMessageBuffer::Destroy() } } -void JackMessageBufferAdd(int level, const char *message) +void JackMessageBufferAdd(int level, const char *message) { if (Jack::JackMessageBuffer::fInstance == NULL) { /* Unable to print message with realtime safety. Complain and print it anyway. */ @@ -137,7 +137,6 @@ void JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *a /* and we're done */ fGuard.Unlock(); } - }; diff --git a/common/JackMidiPort.cpp b/common/JackMidiPort.cpp index fb933c85..117b7a70 100644 --- a/common/JackMidiPort.cpp +++ b/common/JackMidiPort.cpp @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -133,11 +133,17 @@ static void MidiBufferMixdown(void* mixbuffer, void** src_buffers, int src_count mix->lost_events += event_count - events_done; } +static size_t MidiBufferSize() +{ + return BUFFER_SIZE_MAX * sizeof(float); +} + const JackPortType gMidiPortType = - { - JACK_DEFAULT_MIDI_TYPE, - MidiBufferInit, - MidiBufferMixdown - }; +{ + JACK_DEFAULT_MIDI_TYPE, + MidiBufferSize, + MidiBufferInit, + MidiBufferMixdown +}; } // namespace Jack diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index 5f36c3f9..f587411d 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -118,10 +118,10 @@ namespace Jack //init and restart-------------------------------------------------------------------- /* - JackNetDriver is wrapped in a JackWaitThreadedDriver decorator that behaves + JackNetDriver is wrapped in a JackWaitThreadedDriver decorator that behaves as a "dummy driver, until Init method returns. */ - + bool JackNetDriver::Initialize() { jack_log("JackNetDriver::Initialize()"); @@ -221,7 +221,7 @@ namespace Jack void JackNetDriver::FreeAll() { FreePorts(); - + delete[] fTxBuffer; delete[] fRxBuffer; delete fNetAudioCaptureBuffer; @@ -230,7 +230,7 @@ namespace Jack delete fNetMidiPlaybackBuffer; delete[] fMidiCapturePortList; delete[] fMidiPlaybackPortList; - + fTxBuffer = NULL; fRxBuffer = NULL; fNetAudioCaptureBuffer = NULL; @@ -239,7 +239,7 @@ namespace Jack fNetMidiPlaybackBuffer = NULL; fMidiCapturePortList = NULL; fMidiPlaybackPortList = NULL; - + #ifdef JACK_MONITOR delete fNetTimeMon; fNetTimeMon = NULL; @@ -258,6 +258,7 @@ namespace Jack unsigned long port_flags; int audio_port_index; uint midi_port_index; + jack_latency_range_t range; //audio port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; @@ -274,7 +275,8 @@ namespace Jack port = fGraphManager->GetPort ( port_id ); port->SetAlias ( alias ); //port latency - port->SetLatency ( fEngineControl->fBufferSize ); + range.min = range.max = fEngineControl->fBufferSize; + port->SetLatencyRange(JackCaptureLatency, &range); fCapturePortList[audio_port_index] = port_id; jack_log ( "JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() ); } @@ -295,15 +297,16 @@ namespace Jack switch ( fParams.fNetworkMode ) { case 'f' : - port->SetLatency ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); + range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize; break; case 'n' : - port->SetLatency ( fEngineControl->fBufferSize + ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); + range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); break; case 's' : - port->SetLatency ( 2 * fEngineControl->fBufferSize + ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); + range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); break; } + port->SetLatencyRange(JackPlaybackLatency, &range); fPlaybackPortList[audio_port_index] = port_id; jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() ); } @@ -321,7 +324,8 @@ namespace Jack } port = fGraphManager->GetPort ( port_id ); //port latency - port->SetLatency ( fEngineControl->fBufferSize ); + range.min = range.max = fEngineControl->fBufferSize; + port->SetLatencyRange(JackCaptureLatency, &range); fMidiCapturePortList[midi_port_index] = port_id; jack_log ( "JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() ); } @@ -342,15 +346,16 @@ namespace Jack switch ( fParams.fNetworkMode ) { case 'f' : - port->SetLatency ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); + range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize; break; case 'n' : - port->SetLatency ( fEngineControl->fBufferSize + ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) ; + range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); break; case 's' : - port->SetLatency ( 2 * fEngineControl->fBufferSize + ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); + range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); break; } + port->SetLatencyRange(JackPlaybackLatency, &range); fMidiPlaybackPortList[midi_port_index] = port_id; jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() ); } @@ -409,7 +414,7 @@ namespace Jack //is there a transport state change to handle ? if ( fSendTransportData.fNewState && ( fSendTransportData.fState != fEngineControl->fTransport.GetState() ) ) { - + switch ( fSendTransportData.fState ) { case JackTransportStopped : @@ -458,13 +463,13 @@ namespace Jack else fReturnTransportData.fTimebaseMaster = NO_CHANGE; */ - + //update transport state and position fReturnTransportData.fState = fEngineControl->fTransport.Query ( &fReturnTransportData.fPosition ); - + //is it a new state (that the master need to know...) ? fReturnTransportData.fNewState = (( fReturnTransportData.fState == JackTransportNetStarting) && - ( fReturnTransportData.fState != fLastTransportState ) && + ( fReturnTransportData.fState != fLastTransportState ) && ( fReturnTransportData.fState != fSendTransportData.fState ) ); if ( fReturnTransportData.fNewState ) jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) ); @@ -492,14 +497,14 @@ namespace Jack return 0; #ifdef JACK_MONITOR - // For timing + // For timing fRcvSyncUst = GetMicroSeconds(); #endif //decode sync //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified DecodeSyncPacket(); - + #ifdef JACK_MONITOR fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f ); #endif @@ -534,7 +539,7 @@ namespace Jack //sync EncodeSyncPacket(); - + //send sync if ( SyncSend() == SOCKET_ERROR ) return SOCKET_ERROR; diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index 123c513a..fbe8aef1 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -134,7 +134,7 @@ namespace Jack if (jack_set_process_callback(fJackClient, SetProcess, this ) < 0) goto fail; - + if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0) goto fail; @@ -153,7 +153,7 @@ namespace Jack jack_error ( "Can't activate jack client." ); goto fail; } - + if (auto_connect) ConnectPorts(); jack_info ( "New NetMaster started." ); @@ -172,7 +172,8 @@ namespace Jack uint i; char name[24]; jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient ); - + jack_latency_range_t range; + jack_log ( "JackNetMaster::AllocPorts" ); //audio @@ -182,9 +183,10 @@ namespace Jack if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL ) return -1; //port latency - jack_port_set_latency ( fAudioCapturePorts[i], 0 ); + range.min = range.max = 0; + jack_port_set_latency_range(fAudioCapturePorts[i], JackCaptureLatency, &range); } - + for ( i = 0; i < fParams.fReturnAudioChannels; i++ ) { sprintf ( name, "from_slave_%d", i+1 ); @@ -194,17 +196,20 @@ namespace Jack switch ( fParams.fNetworkMode ) { case 'f' : - jack_port_set_latency ( fAudioPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); + range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency; + jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); break; case 'n' : - jack_port_set_latency ( fAudioPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); + range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; + jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); break; case 's' : - jack_port_set_latency ( fAudioPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); + range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; + jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); break; } } - + //midi for ( i = 0; i < fParams.fSendMidiChannels; i++ ) { @@ -212,7 +217,8 @@ namespace Jack if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL ) return -1; //port latency - jack_port_set_latency ( fMidiCapturePorts[i], 0 ); + range.min = range.max = 0; + jack_port_set_latency_range(fMidiCapturePorts[i], JackCaptureLatency, &range); } for ( i = 0; i < fParams.fReturnMidiChannels; i++ ) { @@ -223,23 +229,26 @@ namespace Jack switch ( fParams.fNetworkMode ) { case 'f' : - jack_port_set_latency ( fMidiPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); + range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency; + jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); break; case 'n' : - jack_port_set_latency ( fMidiPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); + range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; + jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); break; case 's' : - jack_port_set_latency ( fMidiPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); + range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; + jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); break; } } return 0; } - + void JackNetMaster::ConnectPorts() { const char **ports; - + ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); if (ports != NULL) { for (unsigned int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) { @@ -247,7 +256,7 @@ namespace Jack } free(ports); } - + ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); if (ports != NULL) { for (unsigned int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) { @@ -309,7 +318,7 @@ namespace Jack else jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName ); break; - + case TIMEBASEMASTER : timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this ); if ( timebase < 0 ) @@ -317,7 +326,7 @@ namespace Jack else jack_info ( "'%s' is the new timebase master.", fParams.fName ); break; - + case CONDITIONAL_TIMEBASEMASTER : timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this ); if ( timebase != EBUSY ) @@ -340,18 +349,18 @@ namespace Jack jack_transport_stop ( fJackClient ); jack_info ( "'%s' stops transport.", fParams.fName ); break; - + case JackTransportStarting : if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) == EINVAL ) jack_error ( "Can't set new position." ); jack_transport_start ( fJackClient ); jack_info ( "'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame); break; - + case JackTransportNetStarting : jack_info ( "'%s' is ready to roll..", fParams.fName ); break; - + case JackTransportRolling : jack_info ( "'%s' is rolling.", fParams.fName ); break; @@ -377,16 +386,19 @@ namespace Jack } //sync-------------------------------------------------------------------------------- - + bool JackNetMaster::IsSlaveReadyToRoll() { return ( fReturnTransportData.fState == JackTransportNetStarting ); } - - int JackNetMaster::SetBufferSize (jack_nframes_t nframes, void* arg) + + int JackNetMaster::SetBufferSize(jack_nframes_t nframes, void* arg) { - jack_error("Cannot handle bufer size change, so proxy will be removed..."); - static_cast ( arg )->Exit(); + JackNetMaster* obj = static_cast(arg); + if (nframes != obj->fParams.fPeriodSize) { + jack_error("Cannot handle bufer size change, so JackNetMaster proxy will be removed..."); + obj->Exit(); + } return 0; } @@ -424,10 +436,10 @@ namespace Jack fParams.fPeriodSize ) ) ); if (IsSynched()) { // only send if connection is "synched" - + //encode the first packet EncodeSyncPacket(); - + //send sync if ( SyncSend() == SOCKET_ERROR ) return SOCKET_ERROR; @@ -443,7 +455,7 @@ namespace Jack #ifdef JACK_MONITOR fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f ); #endif - + } else { jack_error("Connection is not synched, skip cycle..."); } @@ -459,7 +471,7 @@ namespace Jack //decode sync DecodeSyncPacket(); - + //receive data res = DataRecv(); if ( ( res == 0 ) || ( res == SOCKET_ERROR ) ) @@ -498,11 +510,11 @@ namespace Jack else jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP); break; - + case 'p': fSocket.SetPort ( param->value.ui ); break; - + case 'c': fAutoConnect = param->value.i; break; @@ -646,7 +658,7 @@ namespace Jack JackNetMaster* JackNetMasterManager::InitMaster ( session_params_t& params ) { jack_log ( "JackNetMasterManager::InitMaster, Slave : %s", params.fName ); - + //check MASTER <<==> SLAVE network protocol coherency if (params.fProtocolVersion != MASTER_PROTOCOL) { jack_error ( "Error : slave is running with a different protocol %s", params.fName ); @@ -740,7 +752,7 @@ extern "C" desc->params[i].value.i = DEFAULT_PORT; strcpy ( desc->params[i].short_desc, "UDP port" ); strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); - + i++; strcpy ( desc->params[i].name, "auto_connect" ); desc->params[i].character = 'c'; diff --git a/common/JackNetManager.h b/common/JackNetManager.h index 29c8386d..cbeaee9e 100644 --- a/common/JackNetManager.h +++ b/common/JackNetManager.h @@ -54,7 +54,7 @@ namespace Jack //sync and transport int fLastTransportState; - + //monitoring #ifdef JACK_MONITOR jack_time_t fPeriodUsecs; @@ -64,7 +64,7 @@ namespace Jack bool Init(bool auto_connect); int AllocPorts(); void FreePorts(); - + //transport void EncodeTransportData(); void DecodeTransportData(); @@ -98,7 +98,7 @@ namespace Jack const char* fManagerName; char fMulticastIP[32]; JackNetSocket fSocket; - pthread_t fManagerThread; + jack_native_thread_t fManagerThread; master_list_t fMasterList; uint32_t fGlobalID; bool fRunning; diff --git a/common/JackNetOneDriver.cpp b/common/JackNetOneDriver.cpp index 4364606b..5b1b8cdd 100644 --- a/common/JackNetOneDriver.cpp +++ b/common/JackNetOneDriver.cpp @@ -46,10 +46,10 @@ using namespace std; namespace Jack { JackNetOneDriver::JackNetOneDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, - int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports, - int sample_rate, int period_size, int resample_factor, - const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, - int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val ) + int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports, + int sample_rate, int period_size, int resample_factor, + const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, + int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val ) : JackAudioDriver ( name, alias, engine, table ) { jack_log ( "JackNetOneDriver::JackNetOneDriver port %d", port ); @@ -157,23 +157,23 @@ namespace Jack jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_id); if( netj.bitdepth == CELT_MODE ) { - #if HAVE_CELT - #if HAVE_CELT_API_0_7 - celt_int32 lookahead; - CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); - netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); - #else - celt_int32_t lookahead; - CELTMode *celt_mode = celt_mode_create( netj.sample_rate, 1, netj.period_size, NULL ); - netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode ) ); - #endif - celt_mode_info( celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); - netj.codec_latency = 2*lookahead; - #endif + #if HAVE_CELT + #if HAVE_CELT_API_0_7 + celt_int32 lookahead; + CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); + netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); + #else + celt_int32_t lookahead; + CELTMode *celt_mode = celt_mode_create( netj.sample_rate, 1, netj.period_size, NULL ); + netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode ) ); + #endif + celt_mode_info( celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); + netj.codec_latency = 2*lookahead; + #endif } else { - #if HAVE_SAMPLERATE - netj.capture_srcs = jack_slist_append(netj.capture_srcs, (void *)src_new(SRC_LINEAR, 1, NULL)); - #endif + #if HAVE_SAMPLERATE + netj.capture_srcs = jack_slist_append(netj.capture_srcs, (void *)src_new(SRC_LINEAR, 1, NULL)); + #endif } } for (chn = netj.capture_channels_audio; chn < netj.capture_channels; chn++) { @@ -206,19 +206,19 @@ namespace Jack jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_id); if( netj.bitdepth == CELT_MODE ) { - #if HAVE_CELT - #if HAVE_CELT_API_0_7 - CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); - netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); - #else - CELTMode *celt_mode = celt_mode_create( netj.sample_rate, 1, netj.period_size, NULL ); - netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode ) ); - #endif - #endif - } else { - #if HAVE_SAMPLERATE - netj.playback_srcs = jack_slist_append(netj.playback_srcs, (void *)src_new(SRC_LINEAR, 1, NULL)); - #endif + #if HAVE_CELT + #if HAVE_CELT_API_0_7 + CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); + netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); + #else + CELTMode *celt_mode = celt_mode_create( netj.sample_rate, 1, netj.period_size, NULL ); + netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode ) ); + #endif + #endif + } else { + #if HAVE_SAMPLERATE + netj.playback_srcs = jack_slist_append(netj.playback_srcs, (void *)src_new(SRC_LINEAR, 1, NULL)); + #endif } } for (chn = netj.playback_channels_audio; chn < netj.playback_channels; chn++) { @@ -243,10 +243,8 @@ namespace Jack { jack_log ( "JackNetOneDriver::Init()" ); - if( global_packcache != NULL ) { - FreePorts(); - netjack_release( &netj ); - } + FreePorts(); + netjack_release( &netj ); //display some additional infos jack_info ( "NetOne driver started" ); @@ -330,63 +328,64 @@ namespace Jack // Now check if we have to start or stop local transport to sync to remote... switch (pkthdr->transport_state) { - case JackTransportStarting: - // the master transport is starting... so we set our reply to the sync_callback; - if (local_trans_state == JackTransportStopped) { - fEngineControl->fTransport.SetCommand ( TransportCommandStart ); - //jack_transport_start(netj.client); - //last_transport_state = JackTransportStopped; - netj.sync_state = 0; - jack_info("locally stopped... starting..."); - } - if (local_trans_pos.frame != compensated_tranport_pos) - { - jack_position_t new_pos = local_trans_pos; - new_pos.frame = compensated_tranport_pos + 2*netj.period_size; - new_pos.valid = (jack_position_bits_t) 0; + case JackTransportStarting: + // the master transport is starting... so we set our reply to the sync_callback; + if (local_trans_state == JackTransportStopped) { + fEngineControl->fTransport.SetCommand ( TransportCommandStart ); + //jack_transport_start(netj.client); + //last_transport_state = JackTransportStopped; + netj.sync_state = 0; + jack_info("locally stopped... starting..."); + } + if (local_trans_pos.frame != compensated_tranport_pos) { + jack_position_t new_pos = local_trans_pos; + new_pos.frame = compensated_tranport_pos + 2*netj.period_size; + new_pos.valid = (jack_position_bits_t) 0; - fEngineControl->fTransport.RequestNewPos ( &new_pos ); - //jack_transport_locate(netj.client, compensated_tranport_pos); - //last_transport_state = JackTransportRolling; - netj.sync_state = 0; - jack_info("starting locate to %d", compensated_tranport_pos ); - } - break; - case JackTransportStopped: - netj.sync_state = 1; - if (local_trans_pos.frame != (pkthdr->transport_frame)) { - jack_position_t new_pos = local_trans_pos; - new_pos.frame = pkthdr->transport_frame; - new_pos.valid = (jack_position_bits_t)0; - fEngineControl->fTransport.RequestNewPos ( &new_pos ); - //jack_transport_locate(netj.client, (pkthdr->transport_frame)); - jack_info("transport is stopped locate to %d", pkthdr->transport_frame); - } - if (local_trans_state != JackTransportStopped) - //jack_transport_stop(netj.client); - fEngineControl->fTransport.SetCommand ( TransportCommandStop ); - break; - case JackTransportRolling: - netj.sync_state = 1; - // if(local_trans_pos.frame != (pkthdr->transport_frame + (pkthdr->latency) * netj.period_size)) { - // jack_transport_locate(netj.client, (pkthdr->transport_frame + (pkthdr->latency + 2) * netj.period_size)); - // jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size); - // } - if (local_trans_state != JackTransportRolling) - fEngineControl->fTransport.SetState ( JackTransportRolling ); - - break; - - case JackTransportLooping: - break; + + fEngineControl->fTransport.RequestNewPos ( &new_pos ); + //jack_transport_locate(netj.client, compensated_tranport_pos); + //last_transport_state = JackTransportRolling; + netj.sync_state = 0; + jack_info("starting locate to %d", compensated_tranport_pos ); + } + break; + + case JackTransportStopped: + netj.sync_state = 1; + if (local_trans_pos.frame != (pkthdr->transport_frame)) { + jack_position_t new_pos = local_trans_pos; + new_pos.frame = pkthdr->transport_frame; + new_pos.valid = (jack_position_bits_t)0; + fEngineControl->fTransport.RequestNewPos ( &new_pos ); + //jack_transport_locate(netj.client, (pkthdr->transport_frame)); + jack_info("transport is stopped locate to %d", pkthdr->transport_frame); + } + if (local_trans_state != JackTransportStopped) + //jack_transport_stop(netj.client); + fEngineControl->fTransport.SetCommand ( TransportCommandStop ); + break; + + case JackTransportRolling: + netj.sync_state = 1; + // if(local_trans_pos.frame != (pkthdr->transport_frame + (pkthdr->latency) * netj.period_size)) { + // jack_transport_locate(netj.client, (pkthdr->transport_frame + (pkthdr->latency + 2) * netj.period_size)); + // jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size); + // } + if (local_trans_state != JackTransportRolling) + fEngineControl->fTransport.SetState ( JackTransportRolling ); + break; + + case JackTransportLooping: + break; } #endif } render_payload_to_jack_ports (netj.bitdepth, packet_bufX, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats ); - packet_cache_release_packet(global_packcache, netj.expected_framecnt ); + packet_cache_release_packet(netj.packcache, netj.expected_framecnt ); return 0; } @@ -419,12 +418,7 @@ namespace Jack if (netj.srcaddress_valid) { unsigned int r; - - #ifdef __APPLE__ static const int flag = 0; - #else - static const int flag = 0; - #endif if (netj.reply_port) netj.syncsource_address.sin_port = htons(netj.reply_port); @@ -436,690 +430,692 @@ namespace Jack return 0; } -void -JackNetOneDriver::FreePorts () -{ - JSList *node = netj.capture_ports; - - while( node != NULL ) { - JSList *this_node = node; - jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data; - node = jack_slist_remove_link( node, this_node ); - jack_slist_free_1( this_node ); - fGraphManager->ReleasePort( fClientControl.fRefNum, port_id ); - } - netj.capture_ports = NULL; - - node = netj.playback_ports; - while( node != NULL ) { - JSList *this_node = node; - jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data; - node = jack_slist_remove_link( node, this_node ); - jack_slist_free_1( this_node ); - fGraphManager->ReleasePort( fClientControl.fRefNum, port_id ); - } - netj.playback_ports = NULL; + void + JackNetOneDriver::FreePorts () + { + JSList *node = netj.capture_ports; + + while( node != NULL ) { + JSList *this_node = node; + jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data; + node = jack_slist_remove_link( node, this_node ); + jack_slist_free_1( this_node ); + fGraphManager->ReleasePort( fClientControl.fRefNum, port_id ); + } + netj.capture_ports = NULL; + + node = netj.playback_ports; + while( node != NULL ) { + JSList *this_node = node; + jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data; + node = jack_slist_remove_link( node, this_node ); + jack_slist_free_1( this_node ); + fGraphManager->ReleasePort( fClientControl.fRefNum, port_id ); + } + netj.playback_ports = NULL; - if( netj.bitdepth == CELT_MODE ) { -#if HAVE_CELT - node = netj.playback_srcs; - while( node != NULL ) { - JSList *this_node = node; - CELTEncoder *enc = (CELTEncoder *) node->data; - node = jack_slist_remove_link( node, this_node ); - jack_slist_free_1( this_node ); - celt_encoder_destroy( enc ); - } - netj.playback_srcs = NULL; - - node = netj.capture_srcs; - while( node != NULL ) { - JSList *this_node = node; - CELTDecoder *dec = (CELTDecoder *) node->data; - node = jack_slist_remove_link( node, this_node ); - jack_slist_free_1( this_node ); - celt_decoder_destroy( dec ); - } - netj.capture_srcs = NULL; -#endif - } else { -#if HAVE_SAMPLERATE - node = netj.playback_srcs; - while( node != NULL ) { - JSList *this_node = node; - SRC_STATE *state = (SRC_STATE *) node->data; - node = jack_slist_remove_link( node, this_node ); - jack_slist_free_1( this_node ); - src_delete( state ); - } - netj.playback_srcs = NULL; - - node = netj.capture_srcs; - while( node != NULL ) { - JSList *this_node = node; - SRC_STATE *state = (SRC_STATE *) node->data; - node = jack_slist_remove_link( node, this_node ); - jack_slist_free_1( this_node ); - src_delete( state ); - } - netj.capture_srcs = NULL; -#endif + if( netj.bitdepth == CELT_MODE ) { + #if HAVE_CELT + node = netj.playback_srcs; + while( node != NULL ) { + JSList *this_node = node; + CELTEncoder *enc = (CELTEncoder *) node->data; + node = jack_slist_remove_link( node, this_node ); + jack_slist_free_1( this_node ); + celt_encoder_destroy( enc ); + } + netj.playback_srcs = NULL; + + node = netj.capture_srcs; + while( node != NULL ) { + JSList *this_node = node; + CELTDecoder *dec = (CELTDecoder *) node->data; + node = jack_slist_remove_link( node, this_node ); + jack_slist_free_1( this_node ); + celt_decoder_destroy( dec ); + } + netj.capture_srcs = NULL; + #endif + } else { + #if HAVE_SAMPLERATE + node = netj.playback_srcs; + while( node != NULL ) { + JSList *this_node = node; + SRC_STATE *state = (SRC_STATE *) node->data; + node = jack_slist_remove_link( node, this_node ); + jack_slist_free_1( this_node ); + src_delete( state ); + } + netj.playback_srcs = NULL; + + node = netj.capture_srcs; + while( node != NULL ) { + JSList *this_node = node; + SRC_STATE *state = (SRC_STATE *) node->data; + node = jack_slist_remove_link( node, this_node ); + jack_slist_free_1( this_node ); + src_delete( state ); + } + netj.capture_srcs = NULL; + #endif + } } -} + //Render functions-------------------------------------------------------------------- // render functions for float -void -JackNetOneDriver::render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats) -{ - uint32_t chn = 0; - JSList *node = capture_ports; -#if HAVE_SAMPLERATE - JSList *src_node = capture_srcs; -#endif + void + JackNetOneDriver::render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats) + { + uint32_t chn = 0; + JSList *node = capture_ports; + #if HAVE_SAMPLERATE + JSList *src_node = capture_srcs; + #endif - uint32_t *packet_bufX = (uint32_t *)packet_payload; + uint32_t *packet_bufX = (uint32_t *)packet_payload; - if( !packet_payload ) - return; + if( !packet_payload ) + return; - while (node != NULL) - { - unsigned int i; - int_float_t val; -#if HAVE_SAMPLERATE - SRC_DATA src; -#endif - jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data; - JackPort *port = fGraphManager->GetPort( port_id ); + while (node != NULL) + { + unsigned int i; + int_float_t val; + #if HAVE_SAMPLERATE + SRC_DATA src; + #endif + jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data; + JackPort *port = fGraphManager->GetPort( port_id ); - jack_default_audio_sample_t* buf = - (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize); + jack_default_audio_sample_t* buf = + (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize); - const char *porttype = port->GetType(); + const char *porttype = port->GetType(); - if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) - { -#if HAVE_SAMPLERATE - // audio port, resample if necessary - if (net_period_down != nframes) + if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) { - SRC_STATE *src_state = (SRC_STATE *)src_node->data; - for (i = 0; i < net_period_down; i++) + #if HAVE_SAMPLERATE + // audio port, resample if necessary + if (net_period_down != nframes) { - packet_bufX[i] = ntohl (packet_bufX[i]); - } + SRC_STATE *src_state = (SRC_STATE *)src_node->data; + for (i = 0; i < net_period_down; i++) + { + packet_bufX[i] = ntohl (packet_bufX[i]); + } - src.data_in = (float *) packet_bufX; - src.input_frames = net_period_down; + src.data_in = (float *) packet_bufX; + src.input_frames = net_period_down; - src.data_out = buf; - src.output_frames = nframes; + src.data_out = buf; + src.output_frames = nframes; - src.src_ratio = (float) nframes / (float) net_period_down; - src.end_of_input = 0; + src.src_ratio = (float) nframes / (float) net_period_down; + src.end_of_input = 0; - src_set_ratio (src_state, src.src_ratio); - src_process (src_state, &src); - src_node = jack_slist_next (src_node); - } - else -#endif - { - if( dont_htonl_floats ) - { - memcpy( buf, packet_bufX, net_period_down*sizeof(jack_default_audio_sample_t)); + src_set_ratio (src_state, src.src_ratio); + src_process (src_state, &src); + src_node = jack_slist_next (src_node); } else + #endif { - for (i = 0; i < net_period_down; i++) + if( dont_htonl_floats ) + { + memcpy( buf, packet_bufX, net_period_down*sizeof(jack_default_audio_sample_t)); + } + else { - val.i = packet_bufX[i]; - val.i = ntohl (val.i); - buf[i] = val.f; + for (i = 0; i < net_period_down; i++) + { + val.i = packet_bufX[i]; + val.i = ntohl (val.i); + buf[i] = val.f; + } } } } + else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) + { + // midi port, decode midi events + // convert the data buffer to a standard format (uint32_t based) + unsigned int buffer_size_uint32 = net_period_down; + uint32_t * buffer_uint32 = (uint32_t*)packet_bufX; + decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); + } + packet_bufX = (packet_bufX + net_period_down); + node = jack_slist_next (node); + chn++; } - else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) - { - // midi port, decode midi events - // convert the data buffer to a standard format (uint32_t based) - unsigned int buffer_size_uint32 = net_period_down; - uint32_t * buffer_uint32 = (uint32_t*)packet_bufX; - decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); - } - packet_bufX = (packet_bufX + net_period_down); - node = jack_slist_next (node); - chn++; - } } -void -JackNetOneDriver::render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats ) -{ - uint32_t chn = 0; - JSList *node = playback_ports; -#if HAVE_SAMPLERATE - JSList *src_node = playback_srcs; -#endif + void + JackNetOneDriver::render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats ) + { + uint32_t chn = 0; + JSList *node = playback_ports; + #if HAVE_SAMPLERATE + JSList *src_node = playback_srcs; + #endif - uint32_t *packet_bufX = (uint32_t *) packet_payload; + uint32_t *packet_bufX = (uint32_t *) packet_payload; - while (node != NULL) - { -#if HAVE_SAMPLERATE - SRC_DATA src; -#endif - unsigned int i; - int_float_t val; - jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data; - JackPort *port = fGraphManager->GetPort( port_id ); + while (node != NULL) + { + #if HAVE_SAMPLERATE + SRC_DATA src; + #endif + unsigned int i; + int_float_t val; + jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data; + JackPort *port = fGraphManager->GetPort( port_id ); - jack_default_audio_sample_t* buf = - (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize); + jack_default_audio_sample_t* buf = + (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize); - const char *porttype = port->GetType(); + const char *porttype = port->GetType(); - if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) - { - // audio port, resample if necessary + if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) + { + // audio port, resample if necessary -#if HAVE_SAMPLERATE - if (net_period_up != nframes) { - SRC_STATE *src_state = (SRC_STATE *) src_node->data; - src.data_in = buf; - src.input_frames = nframes; + #if HAVE_SAMPLERATE + if (net_period_up != nframes) { + SRC_STATE *src_state = (SRC_STATE *) src_node->data; + src.data_in = buf; + src.input_frames = nframes; - src.data_out = (float *) packet_bufX; - src.output_frames = net_period_up; + src.data_out = (float *) packet_bufX; + src.output_frames = net_period_up; - src.src_ratio = (float) net_period_up / (float) nframes; - src.end_of_input = 0; + src.src_ratio = (float) net_period_up / (float) nframes; + src.end_of_input = 0; - src_set_ratio (src_state, src.src_ratio); - src_process (src_state, &src); + src_set_ratio (src_state, src.src_ratio); + src_process (src_state, &src); - for (i = 0; i < net_period_up; i++) - { - packet_bufX[i] = htonl (packet_bufX[i]); - } - src_node = jack_slist_next (src_node); - } - else -#endif - { - if( dont_htonl_floats ) - { - memcpy( packet_bufX, buf, net_period_up*sizeof(jack_default_audio_sample_t) ); + for (i = 0; i < net_period_up; i++) + { + packet_bufX[i] = htonl (packet_bufX[i]); + } + src_node = jack_slist_next (src_node); } else + #endif { - for (i = 0; i < net_period_up; i++) + if( dont_htonl_floats ) + { + memcpy( packet_bufX, buf, net_period_up*sizeof(jack_default_audio_sample_t) ); + } + else { - val.f = buf[i]; - val.i = htonl (val.i); - packet_bufX[i] = val.i; + for (i = 0; i < net_period_up; i++) + { + val.f = buf[i]; + val.i = htonl (val.i); + packet_bufX[i] = val.i; + } } } } + else if (strncmp(porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) + { + // encode midi events from port to packet + // convert the data buffer to a standard format (uint32_t based) + unsigned int buffer_size_uint32 = net_period_up; + uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; + encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); + } + packet_bufX = (packet_bufX + net_period_up); + node = jack_slist_next (node); + chn++; } - else if (strncmp(porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) - { - // encode midi events from port to packet - // convert the data buffer to a standard format (uint32_t based) - unsigned int buffer_size_uint32 = net_period_up; - uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; - encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); - } - packet_bufX = (packet_bufX + net_period_up); - node = jack_slist_next (node); - chn++; } -} -#if HAVE_CELT -// render functions for celt. -void -JackNetOneDriver::render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes) -{ - uint32_t chn = 0; - JSList *node = capture_ports; - JSList *src_node = capture_srcs; + #if HAVE_CELT + // render functions for celt. + void + JackNetOneDriver::render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes) + { + uint32_t chn = 0; + JSList *node = capture_ports; + JSList *src_node = capture_srcs; + unsigned char *packet_bufX = (unsigned char *)packet_payload; - unsigned char *packet_bufX = (unsigned char *)packet_payload; + while (node != NULL) + { + jack_port_id_t port_id = (jack_port_id_t) (intptr_t)node->data; + JackPort *port = fGraphManager->GetPort( port_id ); - while (node != NULL) - { - jack_port_id_t port_id = (jack_port_id_t) (intptr_t)node->data; - JackPort *port = fGraphManager->GetPort( port_id ); + jack_default_audio_sample_t* buf = + (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize); - jack_default_audio_sample_t* buf = - (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize); + const char *portname = port->GetType(); - const char *portname = port->GetType(); + if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) + { + // audio port, decode celt data. + CELTDecoder *decoder = (CELTDecoder *)src_node->data; + if( !packet_payload ) + celt_decode_float( decoder, NULL, net_period_down, buf ); + else + celt_decode_float( decoder, packet_bufX, net_period_down, buf ); - if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) - { - // audio port, decode celt data. - CELTDecoder *decoder = (CELTDecoder *)src_node->data; - if( !packet_payload ) - celt_decode_float( decoder, NULL, net_period_down, buf ); - else - celt_decode_float( decoder, packet_bufX, net_period_down, buf ); - - src_node = jack_slist_next (src_node); - } - else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) - { - // midi port, decode midi events - // convert the data buffer to a standard format (uint32_t based) - unsigned int buffer_size_uint32 = net_period_down / 2; - uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; - if( packet_payload ) - decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); + src_node = jack_slist_next (src_node); + } + else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) + { + // midi port, decode midi events + // convert the data buffer to a standard format (uint32_t based) + unsigned int buffer_size_uint32 = net_period_down / 2; + uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; + if( packet_payload ) + decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); + } + packet_bufX = (packet_bufX + net_period_down); + node = jack_slist_next (node); + chn++; } - packet_bufX = (packet_bufX + net_period_down); - node = jack_slist_next (node); - chn++; } -} -void -JackNetOneDriver::render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up) -{ - uint32_t chn = 0; - JSList *node = playback_ports; - JSList *src_node = playback_srcs; + void + JackNetOneDriver::render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up) + { + uint32_t chn = 0; + JSList *node = playback_ports; + JSList *src_node = playback_srcs; - unsigned char *packet_bufX = (unsigned char *)packet_payload; + unsigned char *packet_bufX = (unsigned char *)packet_payload; - while (node != NULL) - { - jack_port_id_t port_id = (jack_port_id_t) (intptr_t) node->data; - JackPort *port = fGraphManager->GetPort( port_id ); + while (node != NULL) + { + jack_port_id_t port_id = (jack_port_id_t) (intptr_t) node->data; + JackPort *port = fGraphManager->GetPort( port_id ); - jack_default_audio_sample_t* buf = - (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize); + jack_default_audio_sample_t* buf = + (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize); - const char *portname = port->GetType(); + const char *portname = port->GetType(); - if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) - { - // audio port, encode celt data. - - int encoded_bytes; - float *floatbuf = (float *)alloca (sizeof(float) * nframes ); - memcpy( floatbuf, buf, nframes*sizeof(float) ); - CELTEncoder *encoder = (CELTEncoder *)src_node->data; - encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); - if( encoded_bytes != (int)net_period_up ) - jack_error( "something in celt changed. netjack needs to be changed to handle this." ); - src_node = jack_slist_next( src_node ); - } - else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) - { - // encode midi events from port to packet - // convert the data buffer to a standard format (uint32_t based) - unsigned int buffer_size_uint32 = net_period_up / 2; - uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; - encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); + if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) + { + // audio port, encode celt data. + + int encoded_bytes; + float *floatbuf = (float *)alloca (sizeof(float) * nframes ); + memcpy( floatbuf, buf, nframes*sizeof(float) ); + CELTEncoder *encoder = (CELTEncoder *)src_node->data; + encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); + if( encoded_bytes != (int)net_period_up ) + jack_error( "something in celt changed. netjack needs to be changed to handle this." ); + src_node = jack_slist_next( src_node ); + } + else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) + { + // encode midi events from port to packet + // convert the data buffer to a standard format (uint32_t based) + unsigned int buffer_size_uint32 = net_period_up / 2; + uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; + encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); + } + packet_bufX = (packet_bufX + net_period_up); + node = jack_slist_next (node); + chn++; } - packet_bufX = (packet_bufX + net_period_up); - node = jack_slist_next (node); - chn++; } -} -#endif -/* Wrapper functions with bitdepth argument... */ -void -JackNetOneDriver::render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats) -{ -#if HAVE_CELT - if (bitdepth == CELT_MODE) - render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes); - else -#endif - render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats); -} + #endif + /* Wrapper functions with bitdepth argument... */ + void + JackNetOneDriver::render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats) + { + #if HAVE_CELT + if (bitdepth == CELT_MODE) + render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes); + else + #endif + render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats); + } -void -JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats) -{ -#if HAVE_CELT - if (bitdepth == CELT_MODE) - render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up); - else -#endif - render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats); -} + void + JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats) + { + #if HAVE_CELT + if (bitdepth == CELT_MODE) + render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up); + else + #endif + render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats); + } -//driver loader----------------------------------------------------------------------- + //driver loader----------------------------------------------------------------------- -#ifdef __cplusplus - extern "C" - { -#endif - SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor () - { - jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) ); - jack_driver_param_desc_t * params; - - strcpy ( desc->name, "netone" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 - strcpy ( desc->desc, "netjack one slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 - - desc->nparams = 18; - params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); - - int i = 0; - strcpy (params[i].name, "audio-ins"); - params[i].character = 'i'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 2U; - strcpy (params[i].short_desc, "Number of capture channels (defaults to 2)"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "audio-outs"); - params[i].character = 'o'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 2U; - strcpy (params[i].short_desc, "Number of playback channels (defaults to 2)"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "midi-ins"); - params[i].character = 'I'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 1U; - strcpy (params[i].short_desc, "Number of midi capture channels (defaults to 1)"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "midi-outs"); - params[i].character = 'O'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 1U; - strcpy (params[i].short_desc, "Number of midi playback channels (defaults to 1)"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "rate"); - params[i].character = 'r'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 48000U; - strcpy (params[i].short_desc, "Sample rate"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "period"); - params[i].character = 'p'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 1024U; - strcpy (params[i].short_desc, "Frames per period"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "num-periods"); - params[i].character = 'n'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 5U; - strcpy (params[i].short_desc, - "Network latency setting in no. of periods"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "listen-port"); - params[i].character = 'l'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 3000U; - strcpy (params[i].short_desc, - "The socket port we are listening on for sync packets"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "factor"); - params[i].character = 'f'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 1U; - strcpy (params[i].short_desc, - "Factor for sample rate reduction"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "upstream-factor"); - params[i].character = 'u'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 0U; - strcpy (params[i].short_desc, - "Factor for sample rate reduction on the upstream"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "celt"); - params[i].character = 'c'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 0U; - strcpy (params[i].short_desc, - "sets celt encoding and number of kbits per channel"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "bit-depth"); - params[i].character = 'b'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 0U; - strcpy (params[i].short_desc, - "Sample bit-depth (0 for float, 8 for 8bit and 16 for 16bit)"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "transport-sync"); - params[i].character = 't'; - params[i].type = JackDriverParamBool; - params[i].value.ui = 1U; - strcpy (params[i].short_desc, - "Whether to slave the transport to the master transport"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "autoconf"); - params[i].character = 'a'; - params[i].type = JackDriverParamBool; - params[i].value.ui = 1U; - strcpy (params[i].short_desc, - "Whether to use Autoconfig, or just start."); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "redundancy"); - params[i].character = 'R'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 1U; - strcpy (params[i].short_desc, - "Send packets N times"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "native-endian"); - params[i].character = 'e'; - params[i].type = JackDriverParamBool; - params[i].value.ui = 0U; - strcpy (params[i].short_desc, - "Dont convert samples to network byte order."); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "jitterval"); - params[i].character = 'J'; - params[i].type = JackDriverParamInt; - params[i].value.i = 0; - strcpy (params[i].short_desc, - "attempted jitterbuffer microseconds on master"); - strcpy (params[i].long_desc, params[i].short_desc); - - i++; - strcpy (params[i].name, "always-deadline"); - params[i].character = 'D'; - params[i].type = JackDriverParamBool; - params[i].value.ui = 0U; - strcpy (params[i].short_desc, - "always use deadline"); - strcpy (params[i].long_desc, params[i].short_desc); - - desc->params = params; - - return desc; - } - - SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params ) + #ifdef __cplusplus + extern "C" { - jack_nframes_t sample_rate = 48000; - jack_nframes_t resample_factor = 1; - jack_nframes_t period_size = 1024; - unsigned int capture_ports = 2; - unsigned int playback_ports = 2; - unsigned int capture_ports_midi = 1; - unsigned int playback_ports_midi = 1; - unsigned int listen_port = 3000; - unsigned int bitdepth = 0; - unsigned int handle_transport_sync = 1; - unsigned int use_autoconfig = 1; - unsigned int latency = 5; - unsigned int redundancy = 1; - unsigned int mtu = 1400; - unsigned int resample_factor_up = 1; - int dont_htonl_floats = 0; - int always_deadline = 0; - int jitter_val = 0; - const JSList * node; - const jack_driver_param_t * param; - - for ( node = params; node; node = jack_slist_next ( node ) ) + #endif + SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor () + { + jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) ); + jack_driver_param_desc_t * params; + + strcpy ( desc->name, "netone" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 + strcpy ( desc->desc, "netjack one slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 + + desc->nparams = 18; + params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); + + int i = 0; + strcpy (params[i].name, "audio-ins"); + params[i].character = 'i'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 2U; + strcpy (params[i].short_desc, "Number of capture channels (defaults to 2)"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "audio-outs"); + params[i].character = 'o'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 2U; + strcpy (params[i].short_desc, "Number of playback channels (defaults to 2)"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "midi-ins"); + params[i].character = 'I'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 1U; + strcpy (params[i].short_desc, "Number of midi capture channels (defaults to 1)"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "midi-outs"); + params[i].character = 'O'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 1U; + strcpy (params[i].short_desc, "Number of midi playback channels (defaults to 1)"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "rate"); + params[i].character = 'r'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 48000U; + strcpy (params[i].short_desc, "Sample rate"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "period"); + params[i].character = 'p'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 1024U; + strcpy (params[i].short_desc, "Frames per period"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "num-periods"); + params[i].character = 'n'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 5U; + strcpy (params[i].short_desc, + "Network latency setting in no. of periods"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "listen-port"); + params[i].character = 'l'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 3000U; + strcpy (params[i].short_desc, + "The socket port we are listening on for sync packets"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "factor"); + params[i].character = 'f'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 1U; + strcpy (params[i].short_desc, + "Factor for sample rate reduction"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "upstream-factor"); + params[i].character = 'u'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 0U; + strcpy (params[i].short_desc, + "Factor for sample rate reduction on the upstream"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "celt"); + params[i].character = 'c'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 0U; + strcpy (params[i].short_desc, + "sets celt encoding and number of kbits per channel"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "bit-depth"); + params[i].character = 'b'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 0U; + strcpy (params[i].short_desc, + "Sample bit-depth (0 for float, 8 for 8bit and 16 for 16bit)"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "transport-sync"); + params[i].character = 't'; + params[i].type = JackDriverParamBool; + params[i].value.ui = 1U; + strcpy (params[i].short_desc, + "Whether to slave the transport to the master transport"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "autoconf"); + params[i].character = 'a'; + params[i].type = JackDriverParamBool; + params[i].value.ui = 1U; + strcpy (params[i].short_desc, + "Whether to use Autoconfig, or just start."); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "redundancy"); + params[i].character = 'R'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 1U; + strcpy (params[i].short_desc, + "Send packets N times"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "native-endian"); + params[i].character = 'e'; + params[i].type = JackDriverParamBool; + params[i].value.ui = 0U; + strcpy (params[i].short_desc, + "Dont convert samples to network byte order."); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "jitterval"); + params[i].character = 'J'; + params[i].type = JackDriverParamInt; + params[i].value.i = 0; + strcpy (params[i].short_desc, + "attempted jitterbuffer microseconds on master"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "always-deadline"); + params[i].character = 'D'; + params[i].type = JackDriverParamBool; + params[i].value.ui = 0U; + strcpy (params[i].short_desc, + "always use deadline"); + strcpy (params[i].long_desc, params[i].short_desc); + + desc->params = params; + + return desc; + } + + SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params ) { - param = ( const jack_driver_param_t* ) node->data; - switch ( param->character ) + jack_nframes_t sample_rate = 48000; + jack_nframes_t resample_factor = 1; + jack_nframes_t period_size = 1024; + unsigned int capture_ports = 2; + unsigned int playback_ports = 2; + unsigned int capture_ports_midi = 1; + unsigned int playback_ports_midi = 1; + unsigned int listen_port = 3000; + unsigned int bitdepth = 0; + unsigned int handle_transport_sync = 1; + unsigned int use_autoconfig = 1; + unsigned int latency = 5; + unsigned int redundancy = 1; + unsigned int mtu = 1400; + #if HAVE_SAMPLERATE + unsigned int resample_factor_up = 1; + #endif + int dont_htonl_floats = 0; + int always_deadline = 0; + int jitter_val = 0; + const JSList * node; + const jack_driver_param_t * param; + + for ( node = params; node; node = jack_slist_next ( node ) ) { - case 'i': - capture_ports = param->value.ui; - break; - - case 'o': - playback_ports = param->value.ui; - break; - - case 'I': - capture_ports_midi = param->value.ui; - break; - - case 'O': - playback_ports_midi = param->value.ui; - break; - - case 'r': - sample_rate = param->value.ui; - break; - - case 'p': - period_size = param->value.ui; - break; - - case 'l': - listen_port = param->value.ui; - break; - - case 'f': - #if HAVE_SAMPLERATE - resample_factor = param->value.ui; - #else - jack_error( "not built with libsamplerate support" ); - return NULL; - #endif - break; - - case 'u': - #if HAVE_SAMPLERATE - resample_factor_up = param->value.ui; - #else - jack_error( "not built with libsamplerate support" ); - return NULL; - #endif - break; - - case 'b': - bitdepth = param->value.ui; - break; - - case 'c': - #if HAVE_CELT - bitdepth = CELT_MODE; - resample_factor = param->value.ui; - #else - jack_error( "not built with celt support" ); - return NULL; - #endif - break; + param = ( const jack_driver_param_t* ) node->data; + switch ( param->character ) + { + case 'i': + capture_ports = param->value.ui; + break; + + case 'o': + playback_ports = param->value.ui; + break; + + case 'I': + capture_ports_midi = param->value.ui; + break; + + case 'O': + playback_ports_midi = param->value.ui; + break; + + case 'r': + sample_rate = param->value.ui; + break; + + case 'p': + period_size = param->value.ui; + break; + + case 'l': + listen_port = param->value.ui; + break; + + case 'f': + #if HAVE_SAMPLERATE + resample_factor = param->value.ui; + #else + jack_error( "not built with libsamplerate support" ); + return NULL; + #endif + break; + + case 'u': + #if HAVE_SAMPLERATE + resample_factor_up = param->value.ui; + #else + jack_error( "not built with libsamplerate support" ); + return NULL; + #endif + break; + + case 'b': + bitdepth = param->value.ui; + break; + + case 'c': + #if HAVE_CELT + bitdepth = CELT_MODE; + resample_factor = param->value.ui; + #else + jack_error( "not built with celt support" ); + return NULL; + #endif + break; - case 't': - handle_transport_sync = param->value.ui; - break; + case 't': + handle_transport_sync = param->value.ui; + break; - case 'a': - use_autoconfig = param->value.ui; - break; + case 'a': + use_autoconfig = param->value.ui; + break; - case 'n': - latency = param->value.ui; - break; + case 'n': + latency = param->value.ui; + break; - case 'R': - redundancy = param->value.ui; - break; + case 'R': + redundancy = param->value.ui; + break; - case 'H': - dont_htonl_floats = param->value.ui; - break; + case 'H': + dont_htonl_floats = param->value.ui; + break; - case 'J': - jitter_val = param->value.i; - break; + case 'J': + jitter_val = param->value.i; + break; - case 'D': - always_deadline = param->value.ui; - break; + case 'D': + always_deadline = param->value.ui; + break; + } } - } - try - { - Jack::JackDriverClientInterface* driver = - new Jack::JackWaitThreadedDriver ( - new Jack::JackNetOneDriver ( "system", "net_pcm", engine, table, listen_port, mtu, - capture_ports_midi, playback_ports_midi, capture_ports, playback_ports, - sample_rate, period_size, resample_factor, - "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy, - dont_htonl_floats, always_deadline, jitter_val ) ); - - if ( driver->Open ( period_size, sample_rate, 1, 1, capture_ports, playback_ports, - 0, "from_master_", "to_master_", 0, 0 ) == 0 ) + try { - return driver; + Jack::JackDriverClientInterface* driver = + new Jack::JackWaitThreadedDriver ( + new Jack::JackNetOneDriver ( "system", "net_pcm", engine, table, listen_port, mtu, + capture_ports_midi, playback_ports_midi, capture_ports, playback_ports, + sample_rate, period_size, resample_factor, + "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy, + dont_htonl_floats, always_deadline, jitter_val ) ); + + if ( driver->Open ( period_size, sample_rate, 1, 1, capture_ports, playback_ports, + 0, "from_master_", "to_master_", 0, 0 ) == 0 ) + { + return driver; + } + else + { + delete driver; + return NULL; + } + } - else + catch ( ... ) { - delete driver; return NULL; } - } - catch ( ... ) - { - return NULL; - } - } -#ifdef __cplusplus - } -#endif + #ifdef __cplusplus + } + #endif } diff --git a/common/JackNetOneDriver.h b/common/JackNetOneDriver.h index b288c91f..348b4628 100644 --- a/common/JackNetOneDriver.h +++ b/common/JackNetOneDriver.h @@ -34,45 +34,47 @@ namespace Jack class JackNetOneDriver : public JackAudioDriver { private: - netjack_driver_state_t netj; - -void -render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats); -void -render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats ); -#ifdef HAVE_CELT -void -render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes); -void -render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up); -#endif -void -render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats); -void -render_jack_ports_to_payload (int bitdepth, JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats); + + netjack_driver_state_t netj; + + void + render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats); + void + render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats ); + #ifdef HAVE_CELT + void + render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes); + void + render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up); + #endif + void + render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats); + void + render_jack_ports_to_payload (int bitdepth, JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats); public: - JackNetOneDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, - int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports, - int sample_rate, int period_size, int resample_factor, - const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, - int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val ); - ~JackNetOneDriver(); + + JackNetOneDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, + int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports, + int sample_rate, int period_size, int resample_factor, + const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, + int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val ); + ~JackNetOneDriver(); int Open ( jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing, int inchannels, int outchannels, bool monitor, const char* capture_driver_name, const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency ); - int Close(); + int Close(); int Attach(); int Detach(); int Read(); int Write(); - bool Initialize(); - int AllocPorts(); - void FreePorts(); + bool Initialize(); + int AllocPorts(); + void FreePorts(); // BufferSize can't be changed bool IsFixedBufferSize() diff --git a/common/JackNotification.h b/common/JackNotification.h index bca178af..673ab838 100644 --- a/common/JackNotification.h +++ b/common/JackNotification.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -46,6 +46,7 @@ enum NotificationType { kShutDownCallback = 15, kQUIT = 16, kSessionCallback = 17, + kLatencyCallback = 18, kMaxNotification }; diff --git a/common/JackPort.cpp b/common/JackPort.cpp index f8c62d67..e3dd12f6 100644 --- a/common/JackPort.cpp +++ b/common/JackPort.cpp @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -44,6 +44,8 @@ bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type fInUse = true; fLatency = 0; fTotalLatency = 0; + fPlaybackLatency.min = fPlaybackLatency.max = 0; + fCaptureLatency.min = fCaptureLatency.max = 0; fTied = NO_PORT; // DB: At this point we do not know current buffer size in frames, // but every time buffer will be returned to any user, @@ -86,6 +88,48 @@ jack_nframes_t JackPort::GetTotalLatency() const void JackPort::SetLatency(jack_nframes_t nframes) { fLatency = nframes; + + /* setup the new latency values here, + * so we dont need to change the backend codes. + */ + if (fFlags & JackPortIsOutput) { + fCaptureLatency.min = nframes; + fCaptureLatency.max = nframes; + } + if (fFlags & JackPortIsInput) { + fPlaybackLatency.min = nframes; + fPlaybackLatency.max = nframes; + } +} + +void JackPort::SetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) +{ + if (mode == JackCaptureLatency) { + fCaptureLatency = *range; + + /* hack to set port->shared->latency up for + * backend ports + */ + if ((fFlags & JackPortIsOutput) && (fFlags & JackPortIsPhysical)) + fLatency = (range->min + range->max) / 2; + } else { + fPlaybackLatency = *range; + + /* hack to set port->shared->latency up for + * backend ports + */ + if ((fFlags & JackPortIsInput) && (fFlags & JackPortIsPhysical)) + fLatency = (range->min + range->max) / 2; + } +} + +void JackPort::GetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) const +{ + if (mode == JackCaptureLatency) { + *range = fCaptureLatency; + } else { + *range = fPlaybackLatency; + } } int JackPort::Tie(jack_port_id_t port_index) @@ -103,10 +147,10 @@ int JackPort::UnTie() int JackPort::RequestMonitor(bool onoff) { /** - jackd.h + jackd.h * If @ref JackPortCanMonitor is set for this @a port, turn input * monitoring on or off. Otherwise, do nothing. - + if (!(fFlags & JackPortCanMonitor)) return -1; */ @@ -123,10 +167,10 @@ int JackPort::RequestMonitor(bool onoff) int JackPort::EnsureMonitor(bool onoff) { /** - jackd.h + jackd.h * If @ref JackPortCanMonitor is set for this @a port, turn input * monitoring on or off. Otherwise, do nothing. - + if (!(fFlags & JackPortCanMonitor)) return -1; */ @@ -165,7 +209,7 @@ int JackPort::GetFlags() const const char* JackPort::GetType() const { const JackPortType* type = GetPortType(fTypeId); - return type->name; + return type->fName; } void JackPort::SetName(const char* new_name) diff --git a/common/JackPort.h b/common/JackPort.h index 45f90733..758e402b 100644 --- a/common/JackPort.h +++ b/common/JackPort.h @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -51,12 +51,14 @@ class SERVER_EXPORT JackPort jack_nframes_t fLatency; jack_nframes_t fTotalLatency; + jack_latency_range_t fPlaybackLatency; + jack_latency_range_t fCaptureLatency; uint8_t fMonitorRequests; bool fInUse; jack_port_id_t fTied; // Locally tied source port float fBuffer[BUFFER_SIZE_MAX + 4]; - + bool IsUsed() const { return fInUse; @@ -88,9 +90,13 @@ class SERVER_EXPORT JackPort int UnTie(); jack_nframes_t GetLatency() const; - jack_nframes_t GetTotalLatency() const; void SetLatency(jack_nframes_t latency); + void SetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range); + void GetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) const; + + jack_nframes_t GetTotalLatency() const; + int RequestMonitor(bool onoff); int EnsureMonitor(bool onoff); bool MonitoringInput() @@ -105,7 +111,7 @@ class SERVER_EXPORT JackPort } int GetRefNum() const; - + } POST_PACKED_STRUCTURE; } // end of namespace diff --git a/common/JackPortType.cpp b/common/JackPortType.cpp index 7f720805..d2150562 100644 --- a/common/JackPortType.cpp +++ b/common/JackPortType.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -24,20 +24,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. namespace Jack { -static const JackPortType* port_types[] = +static const JackPortType* gPortTypes[] = { &gAudioPortType, &gMidiPortType, }; -jack_port_type_id_t PORT_TYPES_MAX = sizeof(port_types) / sizeof(port_types[0]); +jack_port_type_id_t PORT_TYPES_MAX = sizeof(gPortTypes) / sizeof(gPortTypes[0]); jack_port_type_id_t GetPortTypeId(const char* port_type) { for (jack_port_type_id_t i = 0; i < PORT_TYPES_MAX; ++i) { - const JackPortType* type = port_types[i]; + const JackPortType* type = gPortTypes[i]; assert(type != 0); - if (strcmp(port_type, type->name) == 0) + if (strcmp(port_type, type->fName) == 0) return i; } return PORT_TYPES_MAX; @@ -46,7 +46,7 @@ jack_port_type_id_t GetPortTypeId(const char* port_type) const JackPortType* GetPortType(jack_port_type_id_t type_id) { assert(type_id >= 0 && type_id <= PORT_TYPES_MAX); - const JackPortType* type = port_types[type_id]; + const JackPortType* type = gPortTypes[type_id]; assert(type != 0); return type; } diff --git a/common/JackPortType.h b/common/JackPortType.h index 616e0ae9..efb8ca2f 100644 --- a/common/JackPortType.h +++ b/common/JackPortType.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -31,7 +31,8 @@ extern jack_port_type_id_t PORT_TYPES_MAX; struct JackPortType { - const char* name; + const char* fName; + size_t (*size)(); void (*init)(void* buffer, size_t buffer_size, jack_nframes_t nframes); void (*mixdown)(void *mixbuffer, void** src_buffers, int src_count, jack_nframes_t nframes); }; diff --git a/common/JackRequest.h b/common/JackRequest.h index c83753a3..90d0644a 100644 --- a/common/JackRequest.h +++ b/common/JackRequest.h @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -71,7 +71,9 @@ struct JackRequest kSessionReply = 34, kGetClientByUUID = 35, kReserveClientName = 36, - kGetUUIDByClient = 37 + kGetUUIDByClient = 37, + kClientHasSessionCallback = 38, + kComputeTotalLatencies = 39 }; RequestType fType; @@ -122,7 +124,7 @@ struct JackResult { return trans->Write(&fResult, sizeof(int)); } - + }; /*! @@ -161,7 +163,7 @@ struct JackClientCheckRequest : public JackRequest CheckRes(trans->Write(&fOptions, sizeof(int))); return trans->Write(&fUUID, sizeof(int)); } - + }; /*! @@ -197,7 +199,7 @@ struct JackClientCheckResult : public JackResult CheckRes(trans->Write(&fStatus, sizeof(int))); return 0; } - + }; /*! @@ -210,7 +212,7 @@ struct JackClientOpenRequest : public JackRequest int fPID; int fUUID; char fName[JACK_CLIENT_NAME_SIZE + 1]; - + JackClientOpenRequest() {} JackClientOpenRequest(const char* name, int pid, int uuid): JackRequest(JackRequest::kClientOpen) @@ -234,7 +236,7 @@ struct JackClientOpenRequest : public JackRequest CheckRes(trans->Write(&fUUID, sizeof(int))); return trans->Write(&fName, sizeof(fName)); } - + }; /*! @@ -247,7 +249,7 @@ struct JackClientOpenResult : public JackResult int fSharedEngine; int fSharedClient; int fSharedGraph; - + JackClientOpenResult() : JackResult(), fSharedEngine(-1), fSharedClient(-1), fSharedGraph(-1) {} @@ -272,7 +274,7 @@ struct JackClientOpenResult : public JackResult CheckRes(trans->Write(&fSharedGraph, sizeof(int))); return 0; } - + }; /*! @@ -299,7 +301,7 @@ struct JackClientCloseRequest : public JackRequest CheckRes(JackRequest::Write(trans)); return trans->Write(&fRefNum, sizeof(int)); } - + }; /*! @@ -402,7 +404,7 @@ struct JackPortRegisterRequest : public JackRequest CheckRes(trans->Write(&fBufferSize, sizeof(unsigned int))); return 0; } - + }; /*! @@ -428,7 +430,7 @@ struct JackPortRegisterResult : public JackResult CheckRes(JackResult::Write(trans)); return trans->Write(&fPortIndex, sizeof(jack_port_id_t)); } - + }; /*! @@ -461,7 +463,7 @@ struct JackPortUnRegisterRequest : public JackRequest CheckRes(trans->Write(&fPortIndex, sizeof(jack_port_id_t))); return 0; } - + }; /*! @@ -501,7 +503,7 @@ struct JackPortConnectNameRequest : public JackRequest CheckRes(trans->Write(&fDst, sizeof(fDst))); return 0; } - + }; /*! @@ -540,7 +542,7 @@ struct JackPortDisconnectNameRequest : public JackRequest CheckRes(trans->Write(&fDst, sizeof(fDst))); return 0; } - + }; /*! @@ -576,7 +578,7 @@ struct JackPortConnectRequest : public JackRequest CheckRes(trans->Write(&fDst, sizeof(jack_port_id_t))); return 0; } - + }; /*! @@ -612,7 +614,7 @@ struct JackPortDisconnectRequest : public JackRequest CheckRes(trans->Write(&fDst, sizeof(jack_port_id_t))); return 0; } - + }; /*! @@ -651,7 +653,7 @@ struct JackPortRenameRequest : public JackRequest return 0; } - + }; /*! @@ -679,7 +681,7 @@ struct JackSetBufferSizeRequest : public JackRequest CheckRes(JackRequest::Write(trans)); return trans->Write(&fBufferSize, sizeof(jack_nframes_t)); } - + }; /*! @@ -707,7 +709,31 @@ struct JackSetFreeWheelRequest : public JackRequest CheckRes(JackRequest::Write(trans)); return trans->Write(&fOnOff, sizeof(int)); } - + +}; + +/*! +\brief ComputeTotalLatencies request. +*/ + +struct JackComputeTotalLatenciesRequest : public JackRequest +{ + + JackComputeTotalLatenciesRequest() + : JackRequest(JackRequest::kComputeTotalLatencies) + {} + + int Read(JackChannelTransaction* trans) + { + return 0; + } + + int Write(JackChannelTransaction* trans) + { + CheckRes(JackRequest::Write(trans)); + return 0; + } + }; /*! @@ -735,7 +761,7 @@ struct JackReleaseTimebaseRequest : public JackRequest CheckRes(JackRequest::Write(trans)); return trans->Write(&fRefNum, sizeof(int)); } - + }; /*! @@ -766,7 +792,7 @@ struct JackSetTimebaseCallbackRequest : public JackRequest CheckRes(trans->Write(&fRefNum, sizeof(int))); return trans->Write(&fConditionnal, sizeof(int)); } - + }; /*! @@ -797,7 +823,7 @@ struct JackGetInternalClientNameRequest : public JackRequest CheckRes(trans->Write(&fRefNum, sizeof(int))); return trans->Write(&fIntRefNum, sizeof(int)); } - + }; /*! @@ -830,7 +856,7 @@ struct JackGetInternalClientNameResult : public JackResult CheckRes(trans->Write(&fName, sizeof(fName))); return 0; } - + }; /*! @@ -863,7 +889,7 @@ struct JackInternalClientHandleRequest : public JackRequest CheckRes(trans->Write(&fRefNum, sizeof(int))); return trans->Write(&fName, sizeof(fName)); } - + }; /*! @@ -897,7 +923,7 @@ struct JackInternalClientHandleResult : public JackResult CheckRes(trans->Write(&fIntRefNum, sizeof(int))); return 0; } - + }; /*! @@ -949,7 +975,7 @@ struct JackInternalClientLoadRequest : public JackRequest CheckRes(trans->Write(&fUUID, sizeof(int))); return trans->Write(&fOptions, sizeof(int)); } - + }; /*! @@ -983,7 +1009,7 @@ struct JackInternalClientLoadResult : public JackResult CheckRes(trans->Write(&fIntRefNum, sizeof(int))); return 0; } - + }; /*! @@ -1044,7 +1070,7 @@ struct JackInternalClientUnloadResult : public JackResult CheckRes(trans->Write(&fStatus, sizeof(int))); return 0; } - + }; /*! @@ -1147,7 +1173,7 @@ struct JackSessionNotifyResult : public JackResult CheckRes(trans->Write(terminator, sizeof(terminator))); return 0; } - + }; /*! @@ -1245,7 +1271,7 @@ struct JackClientNameResult : public JackResult CheckRes(trans->Write(&fName, sizeof(fName))); return 0; } - + }; struct JackUUIDResult : public JackResult @@ -1274,7 +1300,7 @@ struct JackUUIDResult : public JackResult CheckRes(trans->Write(&fUUID, sizeof(fUUID))); return 0; } - + }; struct JackGetUUIDRequest : public JackRequest @@ -1368,6 +1394,34 @@ struct JackReserveNameRequest : public JackRequest }; +struct JackClientHasSessionCallbackRequest : public JackRequest +{ + char fName[JACK_CLIENT_NAME_SIZE + 1]; + + JackClientHasSessionCallbackRequest() + {} + + JackClientHasSessionCallbackRequest(const char *name) + : JackRequest(JackRequest::kClientHasSessionCallback) + { + strncpy(fName, name, sizeof(fName)); + } + + int Read(JackChannelTransaction* trans) + { + CheckRes(trans->Read(&fName, sizeof(fName))); + return 0; + } + + int Write(JackChannelTransaction* trans) + { + CheckRes(JackRequest::Write(trans)); + CheckRes(trans->Write(&fName, sizeof(fName))); + return 0; + } + +}; + /*! \brief ClientNotification. */ diff --git a/common/JackServer.cpp b/common/JackServer.cpp index 126e7c4f..50894529 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -45,7 +45,7 @@ JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int prio } else { jack_info("JACK server starting in non-realtime mode"); } - + fGraphManager = JackGraphManager::Allocate(port_max); fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name); fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl); @@ -72,17 +72,17 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) { // TODO: move that in reworked JackServerGlobals::Init() JackMessageBuffer::Create(); - + if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) { jack_error("Cannot initialize driver"); goto fail_close1; } - + if (fChannel.Open(fEngineControl->fServerName, this) < 0) { jack_error("Server channel open error"); goto fail_close2; } - + if (fEngine->Open() < 0) { jack_error("Cannot open engine"); goto fail_close3; @@ -92,12 +92,12 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) jack_error("Cannot open driver"); goto fail_close4; } - + if (fAudioDriver->Attach() < 0) { jack_error("Cannot attach audio driver"); goto fail_close5; } - + fFreewheelDriver->SetMaster(false); fAudioDriver->SetMaster(true); fAudioDriver->AddSlave(fFreewheelDriver); // After ??? @@ -113,11 +113,11 @@ fail_close4: fail_close3: fChannel.Close(); - -fail_close2: + +fail_close2: fAudioDriver->Close(); -fail_close1: +fail_close1: JackMessageBuffer::Destroy(); return -1; } @@ -190,7 +190,7 @@ int JackServer::SetBufferSize(jack_nframes_t buffer_size) jack_log("SetBufferSize: requirement for new buffer size equals current value"); return 0; } - + if (fAudioDriver->IsFixedBufferSize()) { jack_log("SetBufferSize: driver only supports a fixed buffer size"); return -1; @@ -316,37 +316,37 @@ int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_par fAudioDriver->Stop(); fAudioDriver->Detach(); fAudioDriver->Close(); - + // Open new master JackDriverInfo* info = new JackDriverInfo(); JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); - + if (master == NULL || info == NULL) { delete info; delete master; return -1; } else { - + // Get slaves list std::list slave_list = fAudioDriver->GetSlaves(); std::list::const_iterator it; - + // Move slaves in new master for (it = slave_list.begin(); it != slave_list.end(); it++) { JackDriverInterface* slave = *it; master->AddSlave(slave); } - + // Delete old master delete fAudioDriver; delete fDriverInfo; - + // Activate master fAudioDriver = master; fDriverInfo = info; fAudioDriver->Attach(); fAudioDriver->SetMaster(true); - return fAudioDriver->Start(); + return fAudioDriver->Start(); } } diff --git a/common/JackServerGlobals.cpp b/common/JackServerGlobals.cpp index fcad0a71..04489190 100644 --- a/common/JackServerGlobals.cpp +++ b/common/JackServerGlobals.cpp @@ -28,8 +28,10 @@ static char* server_name = NULL; namespace Jack { -JackServer* JackServerGlobals::fInstance; +JackServer* JackServerGlobals::fInstance; unsigned int JackServerGlobals::fUserCount; +int JackServerGlobals::fRTNotificationSocket; + bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL; void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL; @@ -95,7 +97,7 @@ bool JackServerGlobals::Init() int argc = 0; char* argv[32]; jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK; - + // First user starts the server if (fUserCount++ == 0) { @@ -158,7 +160,7 @@ bool JackServerGlobals::Init() (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) { switch (opt) { - + case 'c': if (tolower (optarg[0]) == 'h') { clock_source = JACK_TIMER_HPET; @@ -168,7 +170,7 @@ bool JackServerGlobals::Init() clock_source = JACK_TIMER_SYSTEM_CLOCK; } else { jack_error("unknown option character %c", optopt); - } + } break; case 'd': diff --git a/common/JackServerGlobals.h b/common/JackServerGlobals.h index b4b688c1..f7d6e439 100644 --- a/common/JackServerGlobals.h +++ b/common/JackServerGlobals.h @@ -38,9 +38,10 @@ struct SERVER_EXPORT JackServerGlobals { static JackServer* fInstance; static unsigned int fUserCount; - static bool (* on_device_acquire)(const char * device_name); - static void (* on_device_release)(const char * device_name); - + static int fRTNotificationSocket; // For debugging purpose + static bool (* on_device_acquire)(const char* device_name); + static void (* on_device_release)(const char* device_name); + JackServerGlobals(); ~JackServerGlobals(); diff --git a/common/JackThread.h b/common/JackThread.h index 34dd798c..a61c5ab1 100644 --- a/common/JackThread.h +++ b/common/JackThread.h @@ -1,21 +1,21 @@ /* Copyright (C) 2001 Paul Davis Copyright (C) 2004-2008 Grame - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software + along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + */ #ifndef __JackThread__ @@ -26,23 +26,23 @@ namespace Jack { - + /*! \brief The base class for runnable objects, that have an Init and Execute method to be called in a thread. */ class JackRunnableInterface { - + protected: - + JackRunnableInterface() {} virtual ~JackRunnableInterface() {} - + public: - + virtual bool Init() /*! Called once when the thread is started */ { return true; @@ -61,23 +61,23 @@ class SERVER_EXPORT JackThreadInterface { public: - + enum kThreadState {kIdle, kStarting, kIniting, kRunning}; - + protected: - + JackRunnableInterface* fRunnable; int fPriority; bool fRealTime; volatile kThreadState fStatus; int fCancellation; - + public: - + JackThreadInterface(JackRunnableInterface* runnable, int priority, bool real_time, int cancellation): fRunnable(runnable), fPriority(priority), fRealTime(real_time), fStatus(kIdle), fCancellation(cancellation) {} - + kThreadState GetStatus() { return fStatus; @@ -86,10 +86,10 @@ class SERVER_EXPORT JackThreadInterface { fStatus = status; } - + void SetParams(UInt64 period, UInt64 computation, UInt64 constraint) // Empty implementation, will only make sense on OSX... {} - + int Start(); int StartSync(); int Kill(); @@ -98,24 +98,24 @@ class SERVER_EXPORT JackThreadInterface int AcquireRealTime(); // Used when called from another thread int AcquireSelfRealTime(); // Used when called from thread itself - + int AcquireRealTime(int priority); // Used when called from another thread int AcquireSelfRealTime(int priority); // Used when called from thread itself - + int DropRealTime(); // Used when called from another thread int DropSelfRealTime(); // Used when called from thread itself - pthread_t GetThreadID(); + jack_native_thread_t GetThreadID(); bool IsThread(); - static int AcquireRealTimeImp(pthread_t thread, int priority); - static int AcquireRealTimeImp(pthread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint); - static int DropRealTimeImp(pthread_t thread); - static int StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); - static int StopImp(pthread_t thread); - static int KillImp(pthread_t thread); + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority); + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint); + static int DropRealTimeImp(jack_native_thread_t thread); + static int StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); + static int StopImp(jack_native_thread_t thread); + static int KillImp(jack_native_thread_t thread); }; - + } } // end of namespace diff --git a/common/JackTime.h b/common/JackTime.h index 10ef1e8c..505903c6 100644 --- a/common/JackTime.h +++ b/common/JackTime.h @@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __JackTime__ #define __JackTime__ -#include "types.h" #include "JackCompilerDeps.h" #include "JackTypes.h" diff --git a/common/JackTypes.h b/common/JackTypes.h index 234be17a..b4bad8d6 100644 --- a/common/JackTypes.h +++ b/common/JackTypes.h @@ -34,6 +34,12 @@ typedef signed long SInt32; #include "JackTypes_os.h" +/** + * Type used to represent the value of free running + * monotonic clock with units of microseconds. + */ +typedef uint64_t jack_time_t; + typedef uint16_t jack_int_t; // Internal type for ports and refnum typedef enum { diff --git a/common/Jackdmp.cpp b/common/Jackdmp.cpp index 1eda4d11..1d05eeb8 100644 --- a/common/Jackdmp.cpp +++ b/common/Jackdmp.cpp @@ -33,7 +33,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackDriverLoader.h" #if defined(JACK_DBUS) && defined(__linux__) -#include +#include #include "audio_reserve.h" #endif @@ -85,7 +85,7 @@ static void copyright(FILE* file) { fprintf(file, "jackdmp " VERSION "\n" "Copyright 2001-2005 Paul Davis and others.\n" - "Copyright 2004-2010 Grame.\n" + "Copyright 2004-2011 Grame.\n" "jackdmp comes with ABSOLUTELY NO WARRANTY\n" "This is free software, and you are welcome to redistribute it\n" "under certain conditions; see the file COPYING for details\n"); @@ -114,10 +114,10 @@ static void usage(FILE* file) " -d backend [ ... backend args ... ]\n" #ifdef __APPLE__ " Available backends may include: coreaudio, dummy or net.\n\n" -#endif +#endif #ifdef WIN32 " Available backends may include: portaudio, dummy or net.\n\n" -#endif +#endif #ifdef __linux__ " Available backends may include: alsa, dummy, freebob, firewire or net\n\n" #endif @@ -178,13 +178,13 @@ int main(int argc, char* argv[]) jackctl_driver_t * midi_driver_ctl; jackctl_driver_t * loopback_driver_ctl; int replace_registry = 0; - + const char *options = "-d:X:P:uvshVrRL:STFl:t:mn:p:" #ifdef __linux__ "c:" #endif ; - + struct option long_options[] = { #ifdef __linux__ { "clock-source", 1, 0, 'c' }, @@ -199,7 +199,7 @@ int main(int argc, char* argv[]) { "name", 1, 0, 'n' }, { "unlock", 0, 0, 'u' }, { "realtime", 0, 0, 'R' }, - { "no-realtime", 0, 0, 'r' }, + { "no-realtime", 0, 0, 'r' }, { "replace-registry", 0, &replace_registry, 0 }, { "loopback", 0, 0, 'L' }, { "realtime-priority", 1, 0, 'P' }, @@ -239,23 +239,23 @@ int main(int argc, char* argv[]) fprintf(stderr, "Failed to create server object\n"); return -1; } - + server_parameters = jackctl_server_get_parameters(server_ctl); - + // Default setting param = jackctl_get_parameter(server_parameters, "realtime"); if (param != NULL) { value.b = true; jackctl_parameter_set_value(param, &value); } - + opterr = 0; while (!seen_audio_driver && (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) { switch (opt) { - #ifdef __linux__ + #ifdef __linux__ case 'c': param = jackctl_get_parameter(server_parameters, "clock-source"); if (param != NULL) { @@ -280,7 +280,7 @@ int main(int argc, char* argv[]) seen_audio_driver = true; audio_driver_name = optarg; break; - + case 'L': loopback = atoi(optarg); break; @@ -342,7 +342,7 @@ int main(int argc, char* argv[]) jackctl_parameter_set_value(param, &value); } break; - + case 'r': param = jackctl_get_parameter(server_parameters, "realtime"); if (param != NULL) { @@ -388,14 +388,14 @@ int main(int argc, char* argv[]) goto fail_free1; } } - + // Long option with no letter so treated separately param = jackctl_get_parameter(server_parameters, "replace-registry"); if (param != NULL) { value.b = replace_registry; jackctl_parameter_set_value(param, &value); } - + if (show_version) { printf( "jackdmp version " VERSION " tmpdir " jack_server_dir @@ -441,7 +441,7 @@ int main(int argc, char* argv[]) // Setup signals then start server signals = jackctl_setup_signals(0); - + if (!jackctl_server_start(server_ctl, audio_driver_ctl)) { fprintf(stderr, "Failed to start server\n"); goto fail_free1; @@ -458,7 +458,7 @@ int main(int argc, char* argv[]) jackctl_server_add_slave(server_ctl, midi_driver_ctl); } - + // Loopback driver if (loopback > 0) { loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback"); @@ -480,7 +480,7 @@ int main(int argc, char* argv[]) if (!jackctl_server_stop(server_ctl)) fprintf(stderr, "Cannot stop server...\n"); - + jackctl_server_destroy(server_ctl); notify_server_stop(server_name); return 0; @@ -488,7 +488,7 @@ int main(int argc, char* argv[]) fail_free1: jackctl_server_destroy(server_ctl); return -1; - + fail_free2: jackctl_server_stop(server_ctl); jackctl_server_destroy(server_ctl); diff --git a/common/jack/jack.h b/common/jack/jack.h index a63fcd12..40f06ddd 100644 --- a/common/jack/jack.h +++ b/common/jack/jack.h @@ -1,19 +1,19 @@ /* Copyright (C) 2001 Paul Davis Copyright (C) 2004 Jack O'Quin - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software + along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -33,21 +33,21 @@ extern "C" /** * Note: More documentation can be found in jack/types.h. */ - + /************************************************************* * NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function * added to the JACK API after the 0.116.2 release. - * - * Functions that predate this release are marked with + * + * Functions that predate this release are marked with * JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile * time in a variety of ways. The default definition is empty, * so that these symbols get normal linkage. If you wish to - * use all JACK symbols with weak linkage, include + * use all JACK symbols with weak linkage, include * before jack.h. *************************************************************/ - + #include - + /** * Call this function to get version of the JACK, in form of several numbers * @@ -200,7 +200,7 @@ int jack_get_client_pid (const char *name) JACK_OPTIONAL_WEAK_EXPORT; * @return the pthread ID of the thread running the JACK client side * code. */ -pthread_t jack_client_thread_id (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; +jack_native_thread_t jack_client_thread_id (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; /*@}*/ @@ -228,7 +228,7 @@ jack_nframes_t jack_thread_wait (jack_client_t*, int status) JACK_OPTIONAL_WEAK_ /** * Wait until this JACK client should process data. - * + * * @param client - pointer to a JACK client structure * * @return the number of frames of data to process @@ -237,7 +237,7 @@ jack_nframes_t jack_thread_wait (jack_client_t*, int status) JACK_OPTIONAL_WEAK_ /** * Signal next clients in the graph. - * + * * @param client - pointer to a JACK client structure * @param status - if non-zero, calling thread should exit */ @@ -254,7 +254,7 @@ void jack_cycle_signal (jack_client_t* client, int status) JACK_OPTIONAL_WEAK_EX * http://jackit.sourceforge.net/docs/design/design.html#SECTION00411000000000000000 * for more information. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code. @@ -270,13 +270,13 @@ int jack_set_process_thread(jack_client_t* client, JackThreadCallback thread_cal /** * Tell JACK to call @a thread_init_callback once just after - * the creation of the thread in which all other callbacks + * the creation of the thread in which all other callbacks * will be handled. * * The code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code, causing JACK @@ -337,7 +337,7 @@ void jack_on_shutdown (jack_client_t *client, */ void jack_on_info_shutdown (jack_client_t *client, JackInfoShutdownCallback shutdown_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - + /** * Tell the Jack server to call @a process_callback whenever there is * work be done, passing @a arg as the second argument. @@ -350,7 +350,7 @@ void jack_on_info_shutdown (jack_client_t *client, * http://jackit.sourceforge.net/docs/design/design.html#SECTION00411000000000000000 * for more information. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code. @@ -370,7 +370,7 @@ int jack_set_process_callback (jack_client_t *client, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code. @@ -389,7 +389,7 @@ int jack_set_freewheel_callback (jack_client_t *client, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @param client pointer to JACK client structure. @@ -410,7 +410,7 @@ int jack_set_buffer_size_callback (jack_client_t *client, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code @@ -427,7 +427,7 @@ int jack_set_sample_rate_callback (jack_client_t *client, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code @@ -444,7 +444,7 @@ int jack_set_client_registration_callback (jack_client_t *, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code @@ -452,7 +452,7 @@ int jack_set_client_registration_callback (jack_client_t *, int jack_set_port_registration_callback (jack_client_t *, JackPortRegistrationCallback registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - + /** * Tell the JACK server to call @a connect_callback whenever a * port is connected or disconnected, passing @a arg as a parameter. @@ -461,7 +461,7 @@ int jack_set_client_registration_callback (jack_client_t *, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code @@ -478,7 +478,7 @@ int jack_set_port_connect_callback (jack_client_t *, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code @@ -495,7 +495,7 @@ int jack_set_port_rename_callback (jack_client_t *, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code @@ -512,39 +512,97 @@ int jack_set_graph_order_callback (jack_client_t *, * the code in the supplied function does not need to be * suitable for real-time execution. * - * NOTE: this function cannot be called while the client is activated + * NOTE: this function cannot be called while the client is activated * (after jack_activate has been called.) * * @return 0 on success, otherwise a non-zero error code */ int jack_set_xrun_callback (jack_client_t *, JackXRunCallback xrun_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - + +/*@}*/ + +/** + * Tell the Jack server to call @a latency_callback whenever it + * is necessary to recompute the latencies for some or all + * Jack ports. + * + * @a latency_callback will be called twice each time it is + * needed, once being passed JackCaptureLatency and once + * JackPlaybackLatency. See @ref LatencyFunctions for + * the definition of each type of latency and related functions. + * + * IMPORTANT: Most JACK clients do NOT need to register a latency + * callback. + * + * Clients that meet any of the following conditions do NOT + * need to register a latency callback: + * + * - have only input ports + * - have only output ports + * - their output is totally unrelated to their input + * - their output is not delayed relative to their input + * (i.e. data that arrives in a given process() + * callback is processed and output again in the + * same callback) + * + * Clients NOT registering a latency callback MUST also + * satisfy this condition: + * + * - have no multiple distinct internal signal pathways + * + * This means that if your client has more than 1 input and + * output port, and considers them always "correlated" + * (e.g. as a stereo pair), then there is only 1 (e.g. stereo) + * signal pathway through the client. This would be true, + * for example, of a stereo FX rack client that has a + * left/right input pair and a left/right output pair. + * + * However, this is somewhat a matter of perspective. The + * same FX rack client could be connected so that its + * two input ports were connected to entirely separate + * sources. Under these conditions, the fact that the client + * does not register a latency callback MAY result + * in port latency values being incorrect. + * + * Clients that do not meet any of those conditions SHOULD + * register a latency callback. + * + * See the documentation for @ref jack_port_set_latency_range() + * on how the callback should operate. Remember that the @a mode + * argument given to the latency callback will need to be + * passed into @ref jack_port_set_latency_range() + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_latency_callback (jack_client_t *, + JackLatencyCallback latency_callback, + void *) JACK_WEAK_EXPORT; /*@}*/ /** * @defgroup ServerClientControl Controlling & querying JACK server operation * @{ */ - + /** * Start/Stop JACK's "freewheel" mode. * * When in "freewheel" mode, JACK no longer waits for * any external event to begin the start of the next process - * cycle. + * cycle. * * As a result, freewheel mode causes "faster than realtime" * execution of a JACK graph. If possessed, real-time * scheduling is dropped when entering freewheel mode, and * if appropriate it is reacquired when stopping. - * + * * IMPORTANT: on systems using capabilities to provide real-time * scheduling (i.e. Linux kernel 2.4), if onoff is zero, this function - * must be called from the thread that originally called jack_activate(). - * This restriction does not apply to other systems (e.g. Linux kernel 2.6 + * must be called from the thread that originally called jack_activate(). + * This restriction does not apply to other systems (e.g. Linux kernel 2.6 * or OS X). - * + * * @param client pointer to JACK client structure * @param onoff if non-zero, freewheel mode starts. Otherwise * freewheel mode ends. @@ -569,7 +627,7 @@ int jack_set_freewheel(jack_client_t* client, int onoff) JACK_OPTIONAL_WEAK_EXPO * @return 0 on success, otherwise a non-zero error code */ int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) JACK_OPTIONAL_WEAK_EXPORT; - + /** * @return the sample rate of the jack system, as set by the user when * jackd was started. @@ -613,7 +671,7 @@ float jack_cpu_load (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; * @defgroup PortFunctions Creating & manipulating ports * @{ */ - + /** * Create a new port for the client. This is an object used for moving * data of any type in or out of the client. Ports may be connected @@ -625,16 +683,16 @@ float jack_cpu_load (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; * name. Exceeding that will cause the port registration to fail and * return NULL. * - * The @a port_name must be unique among all ports owned by this client. - * If the name is not unique, the registration will fail. - * + * The @a port_name must be unique among all ports owned by this client. + * If the name is not unique, the registration will fail. + * * All ports have a type, which may be any non-NULL and non-zero * length string, passed as an argument. Some port types are built * into the JACK API, currently only JACK_DEFAULT_AUDIO_TYPE. * * @param client pointer to JACK client structure. * @param port_name non-empty short name for the new port (not - * including the leading @a "client_name:"). Must be unique. + * including the leading @a "client_name:"). Must be unique. * @param port_type port type name. If longer than * jack_port_type_size(), only that many characters are significant. * @param flags @ref JackPortFlags bit mask. @@ -663,7 +721,7 @@ int jack_port_unregister (jack_client_t *, jack_port_t *) JACK_OPTIONAL_WEAK_EXP * that can be written to; for an input port, it will be an area * containing the data from the port's connection(s), or * zero-filled. if there are multiple inbound connections, the data - * will be mixed appropriately. + * will be mixed appropriately. * * FOR OUTPUT PORTS ONLY : DEPRECATED in Jack 2.0 !! * --------------------------------------------------- @@ -672,9 +730,9 @@ int jack_port_unregister (jack_client_t *, jack_port_t *) JACK_OPTIONAL_WEAK_EXP * either never cache the return value or ensure you have * a "blocksize" callback and be sure to invalidate the cached * address from there. - * + * * Caching output ports is DEPRECATED in Jack 2.0, due to some new optimization (like "pipelining"). - * Port buffers have to be retrieved in each callback for proper functionning. + * Port buffers have to be retrieved in each callback for proper functionning. */ void * jack_port_get_buffer (jack_port_t *, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; @@ -759,7 +817,7 @@ const char ** jack_port_get_connections (const jack_port_t *port) JACK_OPTIONAL_ * you cannot use it in a GraphReordered handler. * * 2) You need not be the owner of the port to get information - * about its connections. + * about its connections. * * @see jack_port_name_size() */ @@ -768,8 +826,8 @@ const char ** jack_port_get_all_connections (const jack_client_t *client, /** * - * @deprecated This function will be removed from a future version - * of JACK. Do not use it. There is no replacement. It has + * @deprecated This function will be removed from a future version + * of JACK. Do not use it. There is no replacement. It has * turned out to serve essentially no purpose in real-life * JACK clients. */ @@ -777,73 +835,13 @@ int jack_port_tie (jack_port_t *src, jack_port_t *dst) JACK_OPTIONAL_WEAK_DEPREC /** * - * @deprecated This function will be removed from a future version - * of JACK. Do not use it. There is no replacement. It has + * @deprecated This function will be removed from a future version + * of JACK. Do not use it. There is no replacement. It has * turned out to serve essentially no purpose in real-life * JACK clients. */ int jack_port_untie (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - /** - * @return the time (in frames) between data being available or - * delivered at/to a port, and the time at which it arrived at or is - * delivered to the "other side" of the port. E.g. for a physical - * audio output port, this is the time between writing to the port and - * when the signal will leave the connector. For a physical audio - * input port, this is the time between the sound arriving at the - * connector and the corresponding frames being readable from the - * port. - */ -jack_nframes_t jack_port_get_latency (jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * The maximum of the sum of the latencies in every - * connection path that can be drawn between the port and other - * ports with the @ref JackPortIsTerminal flag set. - */ -jack_nframes_t jack_port_get_total_latency (jack_client_t *, - jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * The port latency is zero by default. Clients that control - * physical hardware with non-zero latency should call this - * to set the latency to its correct value. Note that the value - * should include any systemic latency present "outside" the - * physical hardware controlled by the client. For example, - * for a client controlling a digital audio interface connected - * to an external digital converter, the latency setting should - * include both buffering by the audio interface *and* the converter. - */ -void jack_port_set_latency (jack_port_t *, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; - -/** -* Request a complete recomputation of a port's total latency. This -* can be called by a client that has just changed the internal -* latency of its port using @function jack_port_set_latency -* and wants to ensure that all signal pathways in the graph -* are updated with respect to the values that will be returned -* by @function jack_port_get_total_latency. -* -* @return zero for successful execution of the request. non-zero -* otherwise. -*/ -int jack_recompute_total_latency (jack_client_t*, jack_port_t* port) JACK_OPTIONAL_WEAK_EXPORT; - -/** -* Request a complete recomputation of all port latencies. This -* can be called by a client that has just changed the internal -* latency of its port using @function jack_port_set_latency -* and wants to ensure that all signal pathways in the graph -* are updated with respect to the values that will be returned -* by @function jack_port_get_total_latency. It allows a client -* to change multiple port latencies without triggering a -* recompute for each change. -* -* @return zero for successful execution of the request. non-zero -* otherwise. -*/ - int jack_recompute_total_latencies (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; - /** * Modify a port's short name. May be called at any time. If the * resulting full name (including the @a "client_name:" prefix) is @@ -856,12 +854,12 @@ int jack_port_set_name (jack_port_t *port, const char *port_name) JACK_OPTIONAL_ /** * Set @a alias as an alias for @a port. May be called at any time. * If the alias is longer than jack_port_name_size(), it will be truncated. - * + * * After a successful call, and until JACK exits or * @function jack_port_unset_alias() is called, @alias may be * used as a alternate name for the port. * - * Ports can have up to two aliases - if both are already + * Ports can have up to two aliases - if both are already * set, this function will return an error. * * @return 0 on success, otherwise a non-zero error code. @@ -870,8 +868,8 @@ int jack_port_set_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEA /** * Remove @a alias as an alias for @a port. May be called at any time. - * - * After a successful call, @a alias can no longer be + * + * After a successful call, @a alias can no longer be * used as a alternate name for the port. * * @return 0 on success, otherwise a non-zero error code. @@ -981,6 +979,224 @@ int jack_port_name_size(void) JACK_OPTIONAL_WEAK_EXPORT; */ int jack_port_type_size(void) JACK_OPTIONAL_WEAK_EXPORT; +/** + * @return the buffersize of a port of type @arg port_type. + * + * this function may only be called in a buffer_size callback. + */ +size_t jack_port_type_get_buffer_size (jack_client_t *client, const char *port_type) JACK_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup LatencyFunctions Managing and determining latency + * + * The purpose of JACK's latency API is to allow clients to + * easily answer two questions: + * + * - How long has it been since the data read from a port arrived + * at the edge of the JACK graph (either via a physical port + * or being synthesized from scratch)? + * + * - How long will it be before the data written to a port arrives + * at the edge of a JACK graph? + + * To help answering these two questions, all JACK ports have two + * latency values associated with them, both measured in frames: + * + * capture latency: how long since the data read from + * the buffer of a port arrived at at + * a port marked with JackPortIsTerminal. + * The data will have come from the "outside + * world" if the terminal port is also + * marked with JackPortIsPhysical, or + * will have been synthesized by the client + * that owns the terminal port. + * + * playback latency: how long until the data + * written to the buffer of port will reach a port + * marked with JackPortIsTerminal. + * + * Both latencies might potentially have more than one value + * because there may be multiple pathways to/from a given port + * and a terminal port. Latency is therefore generally + * expressed a min/max pair. + * + * In most common setups, the minimum and maximum latency + * are the same, but this design accomodates more complex + * routing, and allows applications (and thus users) to + * detect cases where routing is creating an anomalous + * situation that may either need fixing or more + * sophisticated handling by clients that care about + * latency. + * + * See also @ref jack_set_latency_callback for details on how + * clients that add latency to the signal path should interact + * with JACK to ensure that the correct latency figures are + * used. + * @{ + */ + +/** + * The port latency is zero by default. Clients that control + * physical hardware with non-zero latency should call this + * to set the latency to its correct value. Note that the value + * should include any systemic latency present "outside" the + * physical hardware controlled by the client. For example, + * for a client controlling a digital audio interface connected + * to an external digital converter, the latency setting should + * include both buffering by the audio interface *and* the converter. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by a latency callback that calls @ref + * jack_port_set_latency_range(). + */ +void jack_port_set_latency (jack_port_t *, jack_nframes_t) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * return the latency range defined by @a mode for + * @a port, in frames. + * + * See @ref LatencyFunctions for the definition of each latency value. + * + * This is normally used in the LatencyCallback. + * and therefor safe to execute from callbacks. + */ +void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) JACK_WEAK_EXPORT; + +/** + * set the minimum and maximum latencies defined by + * @a mode for @a port, in frames. + * + * See @ref LatencyFunctions for the definition of each latency value. + * + * This function should ONLY be used inside a latency + * callback. The client should determine the current + * value of the latency using @ref jack_port_get_latency_range() + * (called using the same mode as @a mode) + * and then add some number of frames to that reflects + * latency added by the client. + * + * How much latency a client adds will vary + * dramatically. For most clients, the answer is zero + * and there is no reason for them to register a latency + * callback and thus they should never call this + * function. + * + * More complex clients that take an input signal, + * transform it in some way and output the result but + * not during the same process() callback will + * generally know a single constant value to add + * to the value returned by @ref jack_port_get_latency_range(). + * + * Such clients would register a latency callback (see + * @ref jack_set_latency_callback) and must know what input + * ports feed which output ports as part of their + * internal state. Their latency callback will update + * the ports' latency values appropriately. + * + * A pseudo-code example will help. The @a mode argument to the latency + * callback will determine whether playback or capture + * latency is being set. The callback will use + * @ref jack_port_set_latency_range() as follows: + * + * \code + * jack_latency_range_t range; + * if (mode == JackPlaybackLatency) { + * foreach input_port in (all self-registered port) { + * jack_port_get_latency_range (port_feeding_input_port, JackPlaybackLatency, &range); + * range.min += min_delay_added_as_signal_flows_from port_feeding to input_port; + * range.max += max_delay_added_as_signal_flows_from port_feeding to input_port; + * jack_port_set_latency_range (input_port, JackPlaybackLatency, &range); + * } + * } else if (mode == JackCaptureLatency) { + * foreach output_port in (all self-registered port) { + * jack_port_get_latency_range (port_fed_by_output_port, JackCaptureLatency, &range); + * range.min += min_delay_added_as_signal_flows_from_output_port_to_fed_by_port; + * range.max += max_delay_added_as_signal_flows_from_output_port_to_fed_by_port; + * jack_port_set_latency_range (output_port, JackCaptureLatency, &range); + * } + * } + * \endcode + * + * In this relatively simple pseudo-code example, it is assumed that + * each input port or output is connected to only 1 output or input + * port respectively. + * + * If a port is connected to more than 1 other port, then the + * range.min and range.max values passed to @ref + * jack_port_set_latency_range() should reflect the minimum and + * maximum values across all connected ports. + * + * See the description of @ref jack_set_latency_callback for more + * information. + */ +void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) JACK_WEAK_EXPORT; + +/** + * Request a complete recomputation of all port latencies. This + * can be called by a client that has just changed the internal + * latency of its port using jack_port_set_latency + * and wants to ensure that all signal pathways in the graph + * are updated with respect to the values that will be returned + * by jack_port_get_total_latency. It allows a client + * to change multiple port latencies without triggering a + * recompute for each change. + * + * @return zero for successful execution of the request. non-zero + * otherwise. + */ +int jack_recompute_total_latencies (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the time (in frames) between data being available or + * delivered at/to a port, and the time at which it arrived at or is + * delivered to the "other side" of the port. E.g. for a physical + * audio output port, this is the time between writing to the port and + * when the signal will leave the connector. For a physical audio + * input port, this is the time between the sound arriving at the + * connector and the corresponding frames being readable from the + * port. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_port_get_latency_range() in any existing + * use cases. + */ +jack_nframes_t jack_port_get_latency (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * The maximum of the sum of the latencies in every + * connection path that can be drawn between the port and other + * ports with the @ref JackPortIsTerminal flag set. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_port_get_latency_range() in any existing + * use cases. + */ +jack_nframes_t jack_port_get_total_latency (jack_client_t *, + jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Request a complete recomputation of a port's total latency. This + * can be called by a client that has just changed the internal + * latency of its port using jack_port_set_latency + * and wants to ensure that all signal pathways in the graph + * are updated with respect to the values that will be returned + * by jack_port_get_total_latency. + * + * @return zero for successful execution of the request. non-zero + * otherwise. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_recompute_total_latencies() in any existing + * use cases. + */ +int jack_recompute_total_latency (jack_client_t*, jack_port_t* port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + /*@}*/ /** @@ -989,13 +1205,13 @@ int jack_port_type_size(void) JACK_OPTIONAL_WEAK_EXPORT; */ /** - * @param port_name_pattern A regular expression used to select - * ports by name. If NULL or of zero length, no selection based + * @param port_name_pattern A regular expression used to select + * ports by name. If NULL or of zero length, no selection based * on name will be carried out. - * @param type_name_pattern A regular expression used to select - * ports by type. If NULL or of zero length, no selection based + * @param type_name_pattern A regular expression used to select + * ports by type. If NULL or of zero length, no selection based * on type will be carried out. - * @param flags A value used to select ports by their flags. + * @param flags A value used to select ports by their flags. * If zero, no selection based on flags will be carried out. * * @return a NULL-terminated array of ports that match the specified @@ -1021,8 +1237,8 @@ jack_port_t * jack_port_by_name (jack_client_t *, const char *port_name) JACK_OP */ jack_port_t * jack_port_by_id (jack_client_t *client, jack_port_id_t port_id) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ + +/*@}*/ /** * @defgroup TimeFunctions Handling time @@ -1052,7 +1268,7 @@ jack_nframes_t jack_frame_time (const jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT * This function may only be used from the process callback, and can * be used to interpret timestamps generated by jack_frame_time() in * other threads with respect to the current process cycle. - * + * * This is the only jack time function that returns exact time: * when used during the process callback it always returns the same * value (until the next process callback, where it will return @@ -1075,8 +1291,8 @@ jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) JAC /** * @return return JACK's current system time in microseconds, - * using the JACK clock source. - * + * using the JACK clock source. + * * The value returned is guaranteed to be monotonic, but not linear. */ jack_time_t jack_get_time() JACK_OPTIONAL_WEAK_EXPORT; @@ -1129,7 +1345,7 @@ void jack_set_info_function (void (*func)(const char *)) JACK_OPTIONAL_WEAK_EXPO /*@}*/ /** - * The free function to be used on memory returned by jack_port_get_connections, + * The free function to be used on memory returned by jack_port_get_connections, * jack_port_get_all_connections and jack_get_ports functions. * This is MANDATORY on Windows when otherwise all nasty runtime version related crashes can occur. * Developers are strongly encouraged to use this function instead of the standard "free" function in new code. diff --git a/common/jack/midiport.h b/common/jack/midiport.h index e7e079a8..72780740 100644 --- a/common/jack/midiport.h +++ b/common/jack/midiport.h @@ -1,18 +1,18 @@ /* Copyright (C) 2004 Ian Esten - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software + along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -24,11 +24,12 @@ #ifdef __cplusplus extern "C" { #endif - + +#include #include #include -#include - + + /** Type for raw event data contained in @ref jack_midi_event_t. */ typedef unsigned char jack_midi_data_t; @@ -43,7 +44,7 @@ typedef struct _jack_midi_event /** - * @defgroup MIDIAPI Reading and writing MIDI data + * @defgroup MIDIAPI Reading and writing MIDI data * @{ */ @@ -57,7 +58,7 @@ jack_midi_get_event_count(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; /** Get a MIDI event from an event port buffer. - * + * * Jack MIDI is normalised, the MIDI event returned by this function is * guaranteed to be a complete MIDI event (the status byte will always be * present, and no realtime events will interspered with the event). @@ -74,7 +75,7 @@ jack_midi_event_get(jack_midi_event_t *event, /** Clear an event buffer. - * + * * This should be called at the beginning of each process cycle before calling * @ref jack_midi_event_reserve or @ref jack_midi_event_write. This * function may not be called on an input port's buffer. @@ -105,10 +106,10 @@ jack_midi_max_event_size(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; * messages interspersed with other messages (realtime messages are fine * when they occur on their own, like other messages). * - * Events must be written in order, sorted by their sample offsets. - * JACK will not sort the events for you, and will refuse to store - * out-of-order events. - * + * Events must be written in order, sorted by their sample offsets. + * JACK will not sort the events for you, and will refuse to store + * out-of-order events. + * * @param port_buffer Buffer to write event to. * @param time Sample offset of event. * @param data_size Length of event's raw data in bytes. @@ -117,7 +118,7 @@ jack_midi_max_event_size(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; */ jack_midi_data_t* jack_midi_event_reserve(void *port_buffer, - jack_nframes_t time, + jack_nframes_t time, size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; @@ -125,18 +126,17 @@ jack_midi_event_reserve(void *port_buffer, * * This function is simply a wrapper for @ref jack_midi_event_reserve * which writes the event data into the space reserved in the buffer. - * The same restrictions on the MIDI data apply. - * - * Clients must not write more than - * @a data_size bytes into this buffer. Clients must write normalised - * MIDI data to the port - no running status and no (1-byte) realtime - * messages interspersed with other messages (realtime messages are fine - * when they occur on their own, like other messages). - * - * Events must be written in order, sorted by their sample offsets. - * JACK will not sort the events for you, and will refuse to store + * + * Clients must not write more than + * @a data_size bytes into this buffer. Clients must write normalised + * MIDI data to the port - no running status and no (1-byte) realtime + * messages interspersed with other messages (realtime messages are fine + * when they occur on their own, like other messages). + * + * Events must be written in order, sorted by their sample offsets. + * JACK will not sort the events for you, and will refuse to store * out-of-order events. - * + * * @param port_buffer Buffer to write event to. * @param time Sample offset of event. * @param data Message data to be written. diff --git a/common/jack/session.h b/common/jack/session.h index f44048c0..fd0469c6 100644 --- a/common/jack/session.h +++ b/common/jack/session.h @@ -2,21 +2,20 @@ Copyright (C) 2001 Paul Davis Copyright (C) 2004 Jack O'Quin Copyright (C) 2010 Torben Hohn - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software + along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ #ifndef __jack_session_h__ @@ -36,80 +35,114 @@ extern "C" { /** - * session event types. + * Session event type. * * if a client cant save templates, i might just do a normal save. * - * the rationale, why there is no quit without save, is that a client - * might refuse to quit when it has unsaved data. - * however some other clients might have already quit. - * this results in too much confusion, so we just dont support that. - * the session manager can check, if the saved state is different from a previous - * save, and just remove the saved stuff. - * - * (an inquiry function, whether a quit is ok, followed by a quit event - * would have a race) + * There is no "quit without saving" event because a client might refuse to + * quit when it has unsaved data, but other clients may have already quit. + * This results in too much confusion, so it is unsupported. */ enum JackSessionEventType { + /** + * Save the session completely. + * + * The client may save references to data outside the provided directory, + * but it must do so by creating a link inside the provided directory and + * referring to that in any save files. The client must not refer to data + * files outside the provided directory directly in save files, because + * this makes it impossible for the session manager to create a session + * archive for distribution or archival. + */ JackSessionSave = 1, + + /** + * Save the session completly, then quit. + * + * The rules for saving are exactly the same as for JackSessionSave. + */ JackSessionSaveAndQuit = 2, + + /** + * Save a session template. + * + * A session template is a "skeleton" of the session, but without any data. + * Clients must save a session that, when restored, will create the same + * ports as a full save would have. However, the actual data contained in + * the session may not be saved (e.g. a DAW would create the necessary + * tracks, but not save the actual recorded data). + */ JackSessionSaveTemplate = 3 }; typedef enum JackSessionEventType jack_session_event_type_t; +/** + * @ref jack_session_flags_t bits + */ enum JackSessionFlags { /** - * an error occured while saving. + * An error occured while saving. */ JackSessionSaveError = 0x01, /** - * this reply indicates that a client is part of a multiclient application. - * the command reply is left empty. but the session manager should still - * consider this client part of a session. it will come up due to invocation of another - * client. + * Client needs to be run in a terminal. */ - JackSessionChildClient = 0x02 + JackSessionNeedTerminal = 0x02 }; +/** + * Session flags. + */ typedef enum JackSessionFlags jack_session_flags_t; struct _jack_session_event { /** - * the actual type of this session event. + * The type of this session event. */ jack_session_event_type_t type; /** - * session_directory with trailing separator - * this is per client. so the client can do whatever it likes in here. + * Session directory path, with trailing separator. + * + * This directory is exclusive to the client; when saving the client may + * create any files it likes in this directory. */ const char *session_dir; /** - * client_uuid which must be specified to jack_client_open on session reload. - * client can specify it in the returned commandline as an option, or just save it - * with the state file. + * Client UUID which must be passed to jack_client_open on session load. + * + * The client can specify this in the returned command line, or save it + * in a state file within the session directory. */ const char *client_uuid; /** - * the command_line is the reply of the client. - * it specifies in a platform dependent way, how the client must be restarted upon session reload. + * Reply (set by client): the command line needed to restore the client. * - * probably it should contain ${SESSION_DIR} instead of the actual session dir. - * this would basically make the session dir moveable. + * This is a platform dependent command line. It must contain + * ${SESSION_DIR} instead of the actual session directory path. More + * generally, just as in session files, clients should not include any + * paths outside the session directory here as this makes + * archival/distribution impossible. * - * ownership of the memory is handed to jack. - * initially set to NULL by jack; + * This field is set to NULL by Jack when the event is delivered to the + * client. The client must set to allocated memory that is safe to + * free(). This memory will be freed by jack_session_event_free. */ char *command_line; /** - * flags to be set by the client. normally left 0. + * Reply (set by client): Session flags. */ jack_session_flags_t flags; + + /** + * Future flags. Set to zero for now. + */ + uint32_t future; }; typedef struct _jack_session_event jack_session_event_t; @@ -118,35 +151,42 @@ typedef struct _jack_session_event jack_session_event_t; * Prototype for the client supplied function that is called * whenever a session notification is sent via jack_session_notify(). * - * The session_id must be passed to jack_client_open on session reload (this can be - * done by specifying it somehow on the returned command line). + * Ownership of the memory of @a event is passed to the application. + * It must be freed using jack_session_event_free when its not used anymore. + * + * The client must promptly call jack_session_reply for this event. * - * @param event the event_structure. - * @param arg pointer to a client supplied structure + * @param event The event structure. + * @param arg Pointer to a client supplied structure. */ -typedef void (*JackSessionCallback)(jack_session_event_t *event, void *arg); +typedef void (*JackSessionCallback)(jack_session_event_t *event, + void *arg); /** - * Tell the JACK server to call @a save_callback the session handler wants - * to save. + * Tell the JACK server to call @a session_callback when a session event + * is to be delivered. + * + * setting more than one session_callback per process is probably a design + * error. if you have a multiclient application its more sensible to create + * a jack_client with only a session callback set. * * @return 0 on success, otherwise a non-zero error code */ -int jack_set_session_callback(jack_client_t *client, - JackSessionCallback session_callback, - void *arg) JACK_WEAK_EXPORT; +int jack_set_session_callback (jack_client_t *client, + JackSessionCallback session_callback, + void *arg) JACK_WEAK_EXPORT; /** - * reply to a session_event + * Reply to a session event. * - * this can either be called directly from the callback, or later from a different thread. - * so its possible to just stick the event pointer into a pipe and execute the save code - * from the gui thread. + * This can either be called directly from the callback, or later from a + * different thread. For example, it is possible to push the event through a + * queue and execute the save code from the GUI thread. * * @return 0 on success, otherwise a non-zero error code */ - -int jack_session_reply( jack_client_t *client, jack_session_event_t *event ) JACK_WEAK_EXPORT; +int jack_session_reply (jack_client_t *client, + jack_session_event_t *event) JACK_WEAK_EXPORT; /** @@ -154,74 +194,90 @@ int jack_session_reply( jack_client_t *client, jack_session_event_t *event ) JAC * this also frees the memory used by the command_line pointer. * if its non NULL. */ +void jack_session_event_free (jack_session_event_t *event) JACK_WEAK_EXPORT; -void jack_session_event_free (jack_session_event_t *event); -/*@}*/ +/** + * get the assigned uuid for client. + * safe to call from callback and all other threads. + * memory needs to be freed. + */ +char *jack_client_get_uuid (jack_client_t *client) JACK_WEAK_EXPORT; /** - * @defgroup JackSessionManagerAPI this API is intended for a sessionmanager. - * this API could be server specific. if we dont reach consensus here, - * we can just drop it. - * i know its a bit clumsy. - * but this api isnt required to be as stable as the client api. + * @} + */ + +/** + * @defgroup JackSessionManagerAPI API for a session manager. + * * @{ */ typedef struct { - const char *uuid; - const char *client_name; - const char *command; - jack_session_flags_t flags; + const char *uuid; + const char *client_name; + const char *command; + jack_session_flags_t flags; } jack_session_command_t; /** - * send a save or quit event, to all clients listening for session - * callbacks. the returned strings of the clients are accumulated and - * returned as an array of jack_session_command_t. - * its terminated by ret[i].uuid == NULL - * target == NULL means send to all interested clients. otherwise a clientname + * Send an event to all clients listening for session callbacks. + * + * The returned strings of the clients are accumulated and returned as an array + * of jack_session_command_t. its terminated by ret[i].uuid == NULL target == + * NULL means send to all interested clients. otherwise a clientname */ - -jack_session_command_t *jack_session_notify (jack_client_t* client, - const char *target, - jack_session_event_type_t type, - const char *path ) JACK_WEAK_EXPORT; +jack_session_command_t *jack_session_notify ( + jack_client_t* client, + const char *target, + jack_session_event_type_t type, + const char *path) JACK_WEAK_EXPORT; /** - * free the memory allocated by a session command. + * Free the memory allocated by a session command. */ - void jack_session_commands_free (jack_session_command_t *cmds) JACK_WEAK_EXPORT; /** - * get the sessionid for a client name. - * the sessionmanager needs this to reassociate a client_name to the session_id. + * Get the session ID for a client name. + * The session manager needs this to reassociate a client name to the session_id. */ - -char *jack_get_uuid_for_client_name( jack_client_t *client, const char *client_name ) JACK_WEAK_EXPORT; +char *jack_get_uuid_for_client_name (jack_client_t *client, + const char *client_name) JACK_WEAK_EXPORT; /** - * get the client name for a session_id. - * in order to snapshot the graph connections, the sessionmanager needs to map + * Get the client name for a session_id. + * + * In order to snapshot the graph connections, the session manager needs to map * session_ids to client names. */ - -char *jack_get_client_name_by_uuid( jack_client_t *client, const char *client_uuid ) JACK_WEAK_EXPORT; +char *jack_get_client_name_by_uuid (jack_client_t *client, + const char *client_uuid ) JACK_WEAK_EXPORT; /** - * reserve a client name and associate it to a uuid. - * when a client later call jack_client_open() and specifies the uuid, - * jackd will assign the reserved name. - * this allows a session manager to know in advance under which client name - * its managed clients will appear. + * Reserve a client name and associate it with a UUID. + * + * When a client later calls jack_client_open() and specifies the UUID, jackd + * will assign the reserved name. This allows a session manager to know in + * advance under which client name its managed clients will appear. * * @return 0 on success, otherwise a non-zero error code */ +int +jack_reserve_client_name (jack_client_t *client, + const char *name, + const char *uuid) JACK_WEAK_EXPORT; +/** + * Find out whether a client has set up a session callback. + * + * @return 0 when the client has no session callback, 1 when it has one. + * -1 on error. + */ int -jack_reserve_client_name( jack_client_t *client, const char *name, const char *uuid ) JACK_WEAK_EXPORT; +jack_client_has_session_callback (jack_client_t *client, const char *client_name) JACK_WEAK_EXPORT; #ifdef __cplusplus } diff --git a/common/jack/systemdeps.h b/common/jack/systemdeps.h index eadecd40..ee79ad3f 100644 --- a/common/jack/systemdeps.h +++ b/common/jack/systemdeps.h @@ -36,15 +36,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. typedef LONGLONG int64_t; typedef ULONGLONG uint64_t; #endif - #ifndef pthread_t - typedef HANDLE pthread_t; - #endif + /** + * to make jack API independent of different thread implementations, + * we define jack_native_thread_t to HANDLE here. + */ + typedef HANDLE jack_native_thread_t; #elif __MINGW32__ /* MINGW */ #include #include - #ifndef pthread_t - typedef HANDLE pthread_t; - #endif + /** + * to make jack API independent of different thread implementations, + * we define jack_native_thread_t to HANDLE here. + */ + typedef HANDLE jack_native_thread_t; #else /* other compilers ...*/ #include #include @@ -57,6 +61,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include + + /** + * to make jack API independent of different thread implementations, + * we define jack_native_thread_t to pthread_t here. + */ + typedef pthread_t jack_native_thread_t; + #endif /* __APPLE__ || __linux__ || __sun__ || sun */ #endif diff --git a/common/jack/thread.h b/common/jack/thread.h index 5d002afa..28c8cd10 100644 --- a/common/jack/thread.h +++ b/common/jack/thread.h @@ -28,6 +28,10 @@ extern "C" #include #include +/* use 512KB stack per thread - the default is way too high to be feasible + * with mlockall() on many systems */ +#define THREAD_STACK 524288 + /** @file thread.h * * Library functions to standardize thread creation for JACK and its @@ -66,7 +70,7 @@ int jack_client_max_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPOR * @returns 0, if successful; EPERM, if the calling process lacks * required realtime privileges; otherwise some other error number. */ -int jack_acquire_real_time_scheduling (pthread_t thread, int priority) JACK_OPTIONAL_WEAK_EXPORT; +int jack_acquire_real_time_scheduling (jack_native_thread_t thread, int priority) JACK_OPTIONAL_WEAK_EXPORT; /** * Create a thread for JACK or one of its clients. The thread is @@ -85,7 +89,7 @@ int jack_acquire_real_time_scheduling (pthread_t thread, int priority) JACK_OPTI * @returns 0, if successful; otherwise some error number. */ int jack_client_create_thread (jack_client_t* client, - pthread_t *thread, + jack_native_thread_t *thread, int priority, int realtime, /* boolean */ void *(*start_routine)(void*), @@ -98,7 +102,7 @@ int jack_client_create_thread (jack_client_t* client, * * @returns 0, if successful; otherwise an error number. */ -int jack_drop_real_time_scheduling (pthread_t thread) JACK_OPTIONAL_WEAK_EXPORT; +int jack_drop_real_time_scheduling (jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; /** * Stop the thread, waiting for the thread handler to terminate. @@ -107,7 +111,7 @@ int jack_drop_real_time_scheduling (pthread_t thread) JACK_OPTIONAL_WEAK_EXPORT; * * @returns 0, if successful; otherwise an error number. */ -int jack_client_stop_thread(jack_client_t* client, pthread_t thread) JACK_OPTIONAL_WEAK_EXPORT; +int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; /** * Cancel the thread then waits for the thread handler to terminate. @@ -116,7 +120,7 @@ int jack_client_stop_thread(jack_client_t* client, pthread_t thread) JACK_OPTION * * @returns 0, if successful; otherwise an error number. */ - int jack_client_kill_thread(jack_client_t* client, pthread_t thread) JACK_OPTIONAL_WEAK_EXPORT; + int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; #ifndef WIN32 diff --git a/common/jack/types.h b/common/jack/types.h index 65c930d7..a7d06983 100644 --- a/common/jack/types.h +++ b/common/jack/types.h @@ -74,6 +74,205 @@ typedef uint32_t jack_port_id_t; typedef uint32_t jack_port_type_id_t; +/** + * @ref jack_options_t bits + */ +enum JackOptions { + + /** + * Null value to use when no option bits are needed. + */ + JackNullOption = 0x00, + + /** + * Do not automatically start the JACK server when it is not + * already running. This option is always selected if + * \$JACK_NO_START_SERVER is defined in the calling process + * environment. + */ + JackNoStartServer = 0x01, + + /** + * Use the exact client name requested. Otherwise, JACK + * automatically generates a unique one, if needed. + */ + JackUseExactName = 0x02, + + /** + * Open with optional (char *) server_name parameter. + */ + JackServerName = 0x04, + + /** + * Load internal client from optional (char *) + * load_name. Otherwise use the @a client_name. + */ + JackLoadName = 0x08, + + /** + * Pass optional (char *) load_init string to the + * jack_initialize() entry point of an internal client. + */ + JackLoadInit = 0x10, + + /** + * pass a SessionID Token this allows the sessionmanager to identify the client again. + */ + JackSessionID = 0x20 +}; + +/** Valid options for opening an external client. */ +#define JackOpenOptions (JackSessionID|JackServerName|JackNoStartServer|JackUseExactName) + +/** Valid options for loading an internal client. */ +#define JackLoadOptions (JackLoadInit|JackLoadName|JackUseExactName) + +/** + * Options for several JACK operations, formed by OR-ing together the + * relevant @ref JackOptions bits. + */ +typedef enum JackOptions jack_options_t; + +/** + * @ref jack_status_t bits + */ +enum JackStatus { + + /** + * Overall operation failed. + */ + JackFailure = 0x01, + + /** + * The operation contained an invalid or unsupported option. + */ + JackInvalidOption = 0x02, + + /** + * The desired client name was not unique. With the @ref + * JackUseExactName option this situation is fatal. Otherwise, + * the name was modified by appending a dash and a two-digit + * number in the range "-01" to "-99". The + * jack_get_client_name() function will return the exact string + * that was used. If the specified @a client_name plus these + * extra characters would be too long, the open fails instead. + */ + JackNameNotUnique = 0x04, + + /** + * The JACK server was started as a result of this operation. + * Otherwise, it was running already. In either case the caller + * is now connected to jackd, so there is no race condition. + * When the server shuts down, the client will find out. + */ + JackServerStarted = 0x08, + + /** + * Unable to connect to the JACK server. + */ + JackServerFailed = 0x10, + + /** + * Communication error with the JACK server. + */ + JackServerError = 0x20, + + /** + * Requested client does not exist. + */ + JackNoSuchClient = 0x40, + + /** + * Unable to load internal client + */ + JackLoadFailure = 0x80, + + /** + * Unable to initialize client + */ + JackInitFailure = 0x100, + + /** + * Unable to access shared memory + */ + JackShmFailure = 0x200, + + /** + * Client's protocol version does not match + */ + JackVersionError = 0x400, + + /** + * Backend error + */ + JackBackendError = 0x800, + + /** + * Client zombified failure + */ + JackClientZombie = 0x1000 +}; + +/** + * Status word returned from several JACK operations, formed by + * OR-ing together the relevant @ref JackStatus bits. + */ +typedef enum JackStatus jack_status_t; + +/** + * @ref jack_latency_callback_mode_t + */ +enum JackLatencyCallbackMode { + + /** + * Latency Callback for Capture Latency. + * Input Ports have their latency value setup. + * In the Callback the client needs to set the latency of the output ports + */ + JackCaptureLatency, + + /** + * Latency Callback for Playback Latency. + * Output Ports have their latency value setup. + * In the Callback the client needs to set the latency of the input ports + */ + JackPlaybackLatency + +}; + +/** + * Type of Latency Callback (Capture or Playback) + */ +typedef enum JackLatencyCallbackMode jack_latency_callback_mode_t; + +/** + * Prototype for the client supplied function that is called + * by the engine when port latencies need to be recalculated + * + * @param mode playback or capture latency + * @param arg pointer to a client supplied data + * + * @return zero on success, non-zero on error + */ +typedef void (*JackLatencyCallback)(jack_latency_callback_mode_t mode, void *arg); + +/** + * the new latency API operates on Ranges. + */ +struct _jack_latency_range +{ + /** + * minimum latency + */ + jack_nframes_t min; + /** + * maximum latency + */ + jack_nframes_t max; +}; + +typedef struct _jack_latency_range jack_latency_range_t; + /** * Prototype for the client supplied function that is called * by the engine anytime there is work to be done. @@ -164,9 +363,12 @@ typedef int (*JackSampleRateCallback)(jack_nframes_t nframes, void *arg); * Prototype for the client supplied function that is called * whenever a port is registered or unregistered. * - * @param arg pointer to a client supplied structure + * @param port the ID of the port + * @param arg pointer to a client supplied data + * @param register non-zero if the port is being registered, + * zero if the port is being unregistered */ -typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int, void *arg); +typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int register, void *arg); /** * Prototype for the client supplied function that is called @@ -177,7 +379,7 @@ typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int, void *arg * zero if the client is being unregistered * @param arg pointer to a client supplied structure */ -typedef void (*JackClientRegistrationCallback)(const char* name, int val, void *arg); +typedef void (*JackClientRegistrationCallback)(const char* name, int register, void *arg); /** * Prototype for the client supplied function that is called @@ -214,7 +416,7 @@ typedef void (*JackFreewheelCallback)(int starting, void *arg); /** * Prototype for the client supplied function that is called - * whenever jackd is shutdown. Note that after server shutdown, + * whenever jackd is shutdown. Note that after server shutdown, * the client pointer is *not* deallocated by libjack, * the application is responsible to properly use jack_client_close() * to release client ressources. Warning: jack_client_close() cannot be @@ -225,6 +427,21 @@ typedef void (*JackFreewheelCallback)(int starting, void *arg); */ typedef void (*JackShutdownCallback)(void *arg); +/** + * Prototype for the client supplied function that is called + * whenever jackd is shutdown. Note that after server shutdown, + * the client pointer is *not* deallocated by libjack, + * the application is responsible to properly use jack_client_close() + * to release client ressources. Warning: jack_client_close() cannot be + * safely used inside the shutdown callback and has to be called outside of + * the callback context. + + * @param code a status word, formed by OR-ing together the relevant @ref JackStatus bits. + * @param reason a string describing the shutdown reason (backend failure, server crash... etc...) + * @param arg pointer to a client supplied structure + */ +typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg); + /** * Used for the type argument of jack_port_register() for default * audio ports and midi ports. @@ -295,161 +512,9 @@ enum JackPortFlags { * their ports. */ JackPortIsTerminal = 0x10, - - /** - * JackPortIsActive means the port has been registered and the - * client is "active", that is jack_activate has been called - * - * JackPortIsActive is on between jack_activate and jack_deactivate. - */ - JackPortIsActive = 0x20 -}; - -/** - * @ref jack_options_t bits - */ -enum JackOptions { - - /** - * Null value to use when no option bits are needed. - */ - JackNullOption = 0x00, - - /** - * Do not automatically start the JACK server when it is not - * already running. This option is always selected if - * \$JACK_NO_START_SERVER is defined in the calling process - * environment. - */ - JackNoStartServer = 0x01, - - /** - * Use the exact client name requested. Otherwise, JACK - * automatically generates a unique one, if needed. - */ - JackUseExactName = 0x02, - - /** - * Open with optional (char *) server_name parameter. - */ - JackServerName = 0x04, - - /** - * Load internal client from optional (char *) - * load_name. Otherwise use the @a client_name. - */ - JackLoadName = 0x08, - - /** - * Pass optional (char *) load_init string to the - * jack_initialize() entry point of an internal client. - */ - JackLoadInit = 0x10, - - /** - * pass a SessionID Token this allows the sessionmanager to identify the client again. - */ - JackSessionID = 0x20 -}; - -/** Valid options for opening an external client. */ -#define JackOpenOptions (JackSessionID|JackServerName|JackNoStartServer|JackUseExactName) - -/** Valid options for loading an internal client. */ -#define JackLoadOptions (JackLoadInit|JackLoadName|JackUseExactName) - -/** - * Options for several JACK operations, formed by OR-ing together the - * relevant @ref JackOptions bits. - */ -typedef enum JackOptions jack_options_t; - -/** - * @ref jack_status_t bits - */ -enum JackStatus { - - /** - * Overall operation failed. - */ - JackFailure = 0x01, - - /** - * The operation contained an invalid or unsupported option. - */ - JackInvalidOption = 0x02, - - /** - * The desired client name was not unique. With the @ref - * JackUseExactName option this situation is fatal. Otherwise, - * the name was modified by appending a dash and a two-digit - * number in the range "-01" to "-99". The - * jack_get_client_name() function will return the exact string - * that was used. If the specified @a client_name plus these - * extra characters would be too long, the open fails instead. - */ - JackNameNotUnique = 0x04, - - /** - * The JACK server was started as a result of this operation. - * Otherwise, it was running already. In either case the caller - * is now connected to jackd, so there is no race condition. - * When the server shuts down, the client will find out. - */ - JackServerStarted = 0x08, - - /** - * Unable to connect to the JACK server. - */ - JackServerFailed = 0x10, - - /** - * Communication error with the JACK server. - */ - JackServerError = 0x20, - /** - * Requested client does not exist. - */ - JackNoSuchClient = 0x40, - - /** - * Unable to load internal client - */ - JackLoadFailure = 0x80, - - /** - * Unable to initialize client - */ - JackInitFailure = 0x100, - - /** - * Unable to access shared memory - */ - JackShmFailure = 0x200, - - /** - * Client's protocol version does not match - */ - JackVersionError = 0x400, - - /** - * Backend error - */ - JackBackendError = 0x800, - - /** - * Client zombified failure - */ - JackClientZombie = 0x1000 }; -/** - * Status word returned from several JACK operations, formed by - * OR-ing together the relevant @ref JackStatus bits. - */ -typedef enum JackStatus jack_status_t; - /** * Transport states. */ @@ -476,7 +541,7 @@ typedef enum { JackBBTFrameOffset = 0x40, /**< Frame offset of BBT information */ JackAudioVideoRatio = 0x80, /**< audio frames per video frame */ JackVideoFrameOffset = 0x100 /**< frame offset of first video frame */ - + } jack_position_bits_t; /** all valid position bits */ @@ -666,19 +731,5 @@ typedef struct { } jack_transport_info_t; -/** - * Prototype for the client supplied function that is called - * whenever jackd is shutdown. Note that after server shutdown, - * the client pointer is *not* deallocated by libjack, - * the application is responsible to properly use jack_client_close() - * to release client ressources. Warning: jack_client_close() cannot be - * safely used inside the shutdown callback and has to be called outside of - * the callback context. - - * @param code a status word, formed by OR-ing together the relevant @ref JackStatus bits. - * @param reason a string describing the shutdown reason (backend failure, server crash... etc...) - * @param arg pointer to a client supplied structure - */ -typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg); #endif /* __jack_types_h__ */ diff --git a/common/jack/weakjack.h b/common/jack/weakjack.h index 11d2acaa..83f05ab2 100644 --- a/common/jack/weakjack.h +++ b/common/jack/weakjack.h @@ -1,18 +1,18 @@ /* Copyright (C) 2010 Paul Davis - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software + along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -20,10 +20,63 @@ #ifndef __weakjack_h__ #define __weakjack_h__ +/** + * @defgroup WeakLinkage managing support for newer/older versions of JACK + * @{ One challenge faced by developers is that of taking advantage of new features introduced in new versions of [ JACK ] while still + * supporting older versions of the system. Normally, if an application uses a new feature in a library/API, it is unable to run on + * earlier versions of the library/API that do not support that feature. Such applications would either fail to launch or crash when + * an attempt to use the feature was made. This problem cane be solved using weakly-linked symbols. + * + * When a symbol in a framework is defined as weakly linked, the symbol does not have to be present at runtime for a process to + * continue running. The static linker identifies a weakly linked symbol as such in any code module that references the symbol. The + * dynamic linker uses this same information at runtime to determine whether a process can continue running. If a weakly linked symbol + * is not present in the framework, the code module can continue to run as long as it does not reference the symbol. However, if the + * symbol is present, the code can use it normally. + * + * (adapted from: http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html) + * + * A concrete example will help. Suppose that someone uses a version + * of a JACK client we'll call "Jill". Jill was linked against a version + * of JACK that contains a newer part of the API (say, jack_set_latency_callback()) + * and would like to use it if it is available. + * + * When Jill is run on a system that has a suitably "new" version of + * JACK, this function will be available entirely normally. But if Jill + * is run on a system with an old version of JACK, the function isn't + * available. + * + * With normal symbol linkage, this would create a startup error whenever + * someone tries to run Jill with the "old" version of JACK. However, functions + * added to JACK after version 0.116.2 are all declared to have "weak" linkage + * which means that their abscence doesn't cause an error during program + * startup. Instead, Jill can test whether or not the symbol jack_set_latency_callback + * is null or not. If its null, it means that the JACK installed on this machine + * is too old to support this function. If its not null, then Jill can use it + * just like any other function in the API. For example: + * + * \code + * if (jack_set_latency_callback) { + * jack_set_latency_callback (jill_client, jill_latency_callback, arg); + * } + * \endcode + * + * However, there are clients that may want to use this approach to parts of the + * the JACK API that predate 0.116.2. For example, they might want to see if even + * really old basic parts of the API like jack_client_open() exist at runtime. + * + * Such clients should include before any other JACK header. + * This will make the \b entire JACK API be subject to weak linkage, so that any + * and all functions can be checked for existence at runtime. It is important + * to understand that very few clients need to do this - if you use this + * feature you should have a clear reason to do so. + * + * + */ + #ifndef JACK_OPTIONAL_WEAK_EXPORT /* JACK_OPTIONAL_WEAK_EXPORT needs to be a macro which - expands into a compiler directive. If non-null, the directive - must tell the compiler to arrange for weak linkage of + expands into a compiler directive. If non-null, the directive + must tell the compiler to arrange for weak linkage of the symbol it used with. For this to work fully may require linker arguments for the client as well. */ @@ -49,4 +102,6 @@ #endif #endif +/*@}*/ + #endif /* weakjack */ diff --git a/common/jack/weakmacros.h b/common/jack/weakmacros.h index b3207f6a..d5818b34 100644 --- a/common/jack/weakmacros.h +++ b/common/jack/weakmacros.h @@ -1,18 +1,18 @@ /* Copyright (C) 2010 Paul Davis - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software + along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -23,27 +23,31 @@ /************************************************************* * NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function * added to the JACK API after the 0.116.2 release. - * - * Functions that predate this release are marked with + * + * Functions that predate this release are marked with * JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile * time in a variety of ways. The default definition is empty, * so that these symbols get normal linkage. If you wish to - * use all JACK symbols with weak linkage, include + * use all JACK symbols with weak linkage, include * before jack.h. *************************************************************/ #ifndef JACK_WEAK_EXPORT #ifdef __GNUC__ /* JACK_WEAK_EXPORT needs to be a macro which - expands into a compiler directive. If non-null, the directive - must tell the compiler to arrange for weak linkage of + expands into a compiler directive. If non-null, the directive + must tell the compiler to arrange for weak linkage of the symbol it used with. For this to work full may require linker arguments in the client as well. */ #define JACK_WEAK_EXPORT __attribute__((weak)) #else /* Add other things here for non-gcc platforms */ -#define JACK_WEAK_EXPORT + +#ifdef WIN32 +#define JACK_WEAK_EXPORT +#endif + #endif #endif @@ -54,9 +58,13 @@ #ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT #ifdef __GNUC__ #define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((__deprecated__)) -#else +#else /* Add other things here for non-gcc platforms */ -#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT + +#ifdef WIN32 +#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT +#endif + #endif /* __GNUC__ */ #endif diff --git a/common/netjack.c b/common/netjack.c index 077fad8c..ce97da5c 100644 --- a/common/netjack.c +++ b/common/netjack.c @@ -25,7 +25,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. $Id: net_driver.c,v 1.17 2006/04/16 20:16:10 torbenh Exp $ */ - #include #include #include @@ -48,8 +47,6 @@ $Id: net_driver.c,v 1.17 2006/04/16 20:16:10 torbenh Exp $ #include #endif -#include "netjack.h" - #ifdef __linux__ #include "config.h" #endif @@ -58,15 +55,11 @@ $Id: net_driver.c,v 1.17 2006/04/16 20:16:10 torbenh Exp $ #include #endif -#if HAVE_CELT -#include -#endif - #include "netjack.h" #include "netjack_packet.h" // JACK2 -#include "jack/control.h" +#include "control.h" #define MIN(x,y) ((x)<(y) ? (x) : (y)) @@ -105,8 +98,8 @@ int netjack_wait( netjack_driver_state_t *netj ) netj->expected_framecnt += 1; } else { // starting up.... lets look into the packetcache, and fetch the highest packet. - packet_cache_drain_socket( global_packcache, netj->sockfd ); - if( packet_cache_get_highest_available_framecnt( global_packcache, &next_frame_avail ) ) { + packet_cache_drain_socket( netj->packcache, netj->sockfd ); + if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail ) ) { netj->expected_framecnt = next_frame_avail; netj->expected_framecnt_valid = 1; } else { @@ -122,7 +115,7 @@ int netjack_wait( netjack_driver_state_t *netj ) // then poll (have deadline calculated) // then drain socket, rinse and repeat. while(1) { - if( packet_cache_get_next_available_framecnt( global_packcache, netj->expected_framecnt, &next_frame_avail) ) { + if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) ) { if( next_frame_avail == netj->expected_framecnt ) { we_have_the_expected_frame = 1; if( !netj->always_deadline ) @@ -133,13 +126,13 @@ int netjack_wait( netjack_driver_state_t *netj ) break; } - packet_cache_drain_socket( global_packcache, netj->sockfd ); + packet_cache_drain_socket( netj->packcache, netj->sockfd ); } // check if we know who to send our packets too. if (!netj->srcaddress_valid) - if( global_packcache->master_address_valid ) { - memcpy (&(netj->syncsource_address), &(global_packcache->master_address), sizeof( struct sockaddr_in ) ); + if( netj->packcache->master_address_valid ) { + memcpy (&(netj->syncsource_address), &(netj->packcache->master_address), sizeof( struct sockaddr_in ) ); netj->srcaddress_valid = 1; } @@ -161,7 +154,7 @@ int netjack_wait( netjack_driver_state_t *netj ) else netj->time_to_deadline = 0; - packet_cache_retreive_packet_pointer( global_packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize , &packet_recv_time_stamp); + packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize , &packet_recv_time_stamp); pkthdr = (jacknet_packet_header *) netj->rx_buf; packet_header_ntoh(pkthdr); netj->deadline_goodness = (int)pkthdr->sync_state; @@ -203,7 +196,7 @@ int netjack_wait( netjack_driver_state_t *netj ) // lets check if we have the next packets, we will just run a cycle without data. // in that case. - if( packet_cache_get_next_available_framecnt( global_packcache, netj->expected_framecnt, &next_frame_avail) ) + if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) ) { jack_nframes_t offset = next_frame_avail - netj->expected_framecnt; @@ -221,7 +214,7 @@ int netjack_wait( netjack_driver_state_t *netj ) // I also found this happening, when the packet queue, is too full. // but wtf ? use a smaller latency. this link can handle that ;S - if( packet_cache_get_fill( global_packcache, netj->expected_framecnt ) > 80.0 ) + if( packet_cache_get_fill( netj->packcache, netj->expected_framecnt ) > 80.0 ) netj->next_deadline -= netj->period_usecs/2; @@ -229,7 +222,7 @@ int netjack_wait( netjack_driver_state_t *netj ) // the diff is too high. but we have a packet in the future. // lets resync. netj->expected_framecnt = next_frame_avail; - packet_cache_retreive_packet_pointer( global_packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL ); + packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL ); pkthdr = (jacknet_packet_header *) netj->rx_buf; packet_header_ntoh(pkthdr); //netj->deadline_goodness = 0; @@ -257,7 +250,7 @@ int netjack_wait( netjack_driver_state_t *netj ) // i will make the packet cache drop redundant packets, // that have already been retreived. // - if( packet_cache_get_highest_available_framecnt( global_packcache, &next_frame_avail) ) { + if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail) ) { if( next_frame_avail == (netj->expected_framecnt - 1) ) { // Ok. the last packet is there now. // and it had not been retrieved. @@ -277,9 +270,9 @@ int netjack_wait( netjack_driver_state_t *netj ) // But now we can check for any new frame available. // - if( packet_cache_get_highest_available_framecnt( global_packcache, &next_frame_avail) ) { + if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail) ) { netj->expected_framecnt = next_frame_avail; - packet_cache_retreive_packet_pointer( global_packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL ); + packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL ); pkthdr = (jacknet_packet_header *) netj->rx_buf; packet_header_ntoh(pkthdr); netj->deadline_goodness = pkthdr->sync_state; @@ -300,7 +293,7 @@ int netjack_wait( netjack_driver_state_t *netj ) // reply address changes port. if (netj->num_lost_packets > 200 ) { netj->srcaddress_valid = 0; - packet_cache_reset_master_address( global_packcache ); + packet_cache_reset_master_address( netj->packcache ); } } } @@ -369,6 +362,21 @@ void netjack_attach( netjack_driver_state_t *netj ) int port_flags; + if( netj->bitdepth == CELT_MODE ) + { +#if HAVE_CELT +#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 + celt_int32 lookahead; + netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); +#else + celt_int32_t lookahead; + netj->celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); +#endif + celt_mode_info( netj->celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); + netj->codec_latency = 2*lookahead; +#endif + } + if (netj->handle_transport_sync) jack_set_sync_callback(netj->client, (JackSyncCallback) net_driver_sync_cb, NULL); @@ -390,17 +398,11 @@ void netjack_attach( netjack_driver_state_t *netj ) if( netj->bitdepth == CELT_MODE ) { #if HAVE_CELT -#if HAVE_CELT_API_0_7 - celt_int32 lookahead; - CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); - netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); +#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 + netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) ); #else - celt_int32_t lookahead; - CELTMode *celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); - netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( celt_mode ) ); + netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) ); #endif - celt_mode_info( celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); - netj->codec_latency = 2*lookahead; #endif } else { #if HAVE_SAMPLERATE @@ -408,6 +410,7 @@ void netjack_attach( netjack_driver_state_t *netj ) #endif } } + for (chn = netj->capture_channels_audio; chn < netj->capture_channels; chn++) { snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1); @@ -441,7 +444,7 @@ void netjack_attach( netjack_driver_state_t *netj ) jack_slist_append (netj->playback_ports, port); if( netj->bitdepth == CELT_MODE ) { #if HAVE_CELT -#if HAVE_CELT_API_0_7 +#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); #else @@ -479,7 +482,6 @@ void netjack_detach( netjack_driver_state_t *netj ) { JSList * node; - for (node = netj->capture_ports; node; node = jack_slist_next (node)) jack_port_unregister (netj->client, ((jack_port_t *) node->data)); @@ -487,12 +489,57 @@ void netjack_detach( netjack_driver_state_t *netj ) jack_slist_free (netj->capture_ports); netj->capture_ports = NULL; + for (node = netj->capture_srcs; node; node = jack_slist_next (node)) + { +#if HAVE_CELT + if( netj->bitdepth == CELT_MODE ) + { + CELTDecoder * decoder = node->data; + celt_decoder_destroy(decoder); + } + else +#endif + { +#if HAVE_SAMPLERATE + SRC_STATE * src = node->data; + src_delete(src); +#endif + } + } + jack_slist_free (netj->capture_srcs); + netj->playback_srcs = NULL; + for (node = netj->playback_ports; node; node = jack_slist_next (node)) jack_port_unregister (netj->client, ((jack_port_t *) node->data)); jack_slist_free (netj->playback_ports); netj->playback_ports = NULL; + + for (node = netj->playback_srcs; node; node = jack_slist_next (node)) + { +#if HAVE_CELT + if( netj->bitdepth == CELT_MODE ) + { + CELTEncoder * encoder = node->data; + celt_encoder_destroy(encoder); + } + else +#endif + { +#if HAVE_SAMPLERATE + SRC_STATE * src = node->data; + src_delete(src); +#endif + } + } + jack_slist_free (netj->playback_srcs); + netj->playback_srcs = NULL; + +#if HAVE_CELT + if( netj->bitdepth == CELT_MODE ) + celt_mode_destroy(netj->celt_mode); +#endif } @@ -574,8 +621,8 @@ void netjack_release( netjack_driver_state_t *netj ) close( netj->sockfd ); close( netj->outsockfd ); - packet_cache_free( global_packcache ); - global_packcache = NULL; + packet_cache_free( netj->packcache ); + netj->packcache = NULL; } int @@ -585,13 +632,7 @@ netjack_startup( netjack_driver_state_t *netj ) struct sockaddr_in address; // Now open the socket, and wait for the first packet to arrive... netj->sockfd = socket (AF_INET, SOCK_DGRAM, 0); - #ifdef WIN32 - u_long parm = 1; - DWORD bufsize = 262144; - //ioctlsocket( netj->sockfd, FIONBIO, &parm ); - setsockopt( netj->sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize) ); - setsockopt( netj->sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize) ); if (netj->sockfd == INVALID_SOCKET) #else if (netj->sockfd == -1) @@ -632,6 +673,10 @@ netjack_startup( netjack_driver_state_t *netj ) //jack_info ("*** IMPORTANT *** Dont connect a client to jackd until the driver is attached to a clock source !!!"); while(1) { + if( ! netjack_poll( netj->sockfd, 1000 ) ) { + jack_info ("Waiting aborted"); + return -1; + } first_pack_len = recvfrom (netj->sockfd, (char *)first_packet, sizeof (jacknet_packet_header), 0, (struct sockaddr*) & netj->syncsource_address, &address_size); #ifdef WIN32 if( first_pack_len == -1 ) { @@ -735,7 +780,7 @@ netjack_startup( netjack_driver_state_t *netj ) } netj->rx_bufsize = sizeof (jacknet_packet_header) + netj->net_period_down * netj->capture_channels * get_sample_size (netj->bitdepth); - global_packcache = packet_cache_new (netj->latency + 50, netj->rx_bufsize, netj->mtu); + netj->packcache = packet_cache_new (netj->latency + 50, netj->rx_bufsize, netj->mtu); netj->expected_framecnt_valid = 0; netj->num_lost_packets = 0; diff --git a/common/netjack.h b/common/netjack.h index edac28a0..2bdd092c 100644 --- a/common/netjack.h +++ b/common/netjack.h @@ -30,6 +30,10 @@ #include "jack/jslist.h" +#if HAVE_CELT +#include +#endif + //#include #ifdef __cplusplus @@ -37,6 +41,8 @@ extern "C" { #endif +struct _packet_cache; + typedef struct _netjack_driver_state netjack_driver_state_t; struct _netjack_driver_state { @@ -106,6 +112,10 @@ struct _netjack_driver_state { unsigned int resample_factor; unsigned int resample_factor_up; int jitter_val; + struct _packet_cache * packcache; +#if HAVE_CELT + CELTMode *celt_mode; +#endif }; int netjack_wait( netjack_driver_state_t *netj ); diff --git a/common/netjack_packet.c b/common/netjack_packet.c index dfe3b9e2..d03d49f0 100644 --- a/common/netjack_packet.c +++ b/common/netjack_packet.c @@ -75,7 +75,7 @@ #include "netjack_packet.h" // JACK2 specific. -#include "jack/control.h" +#include "control.h" #ifdef NO_JACK_ERROR #define jack_error printf @@ -83,8 +83,6 @@ int fraggo = 0; -packet_cache *global_packcache = NULL; - void packet_header_hton (jacknet_packet_header *pkthdr) { @@ -388,7 +386,7 @@ netjack_poll_deadline (int sockfd, jack_time_t deadline) #if HAVE_PPOLL timeout_spec.tv_nsec = (deadline - now) * 1000; #else - timeout = (deadline - now + 500) / 1000; + timeout = lrintf( (float)(deadline - now) / 1000.0 ); #endif @@ -565,7 +563,7 @@ packet_cache_drain_socket( packet_cache *pcache, int sockfd ) if( pcache->last_framecnt_retreived_valid && (framecnt <= pcache->last_framecnt_retreived )) continue; - cpack = packet_cache_get_packet (global_packcache, framecnt); + cpack = packet_cache_get_packet (pcache, framecnt); cache_packet_add_fragment (cpack, rx_packet, rcv_len); cpack->recv_timestamp = jack_get_time(); } @@ -774,61 +772,6 @@ packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecn return retval; } // fragmented packet IO -int -netjack_recvfrom (int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, size_t *addr_size, int mtu) -{ - int retval; - socklen_t from_len = *addr_size; - if (pkt_size <= mtu) { - retval = recvfrom (sockfd, packet_buf, pkt_size, flags, addr, &from_len); - *addr_size = from_len; - return retval; - } - - char *rx_packet = alloca (mtu); - jacknet_packet_header *pkthdr = (jacknet_packet_header *) rx_packet; - int rcv_len; - jack_nframes_t framecnt; - cache_packet *cpack; - do - { - rcv_len = recvfrom (sockfd, rx_packet, mtu, 0, addr, &from_len); - if (rcv_len < 0) - return rcv_len; - framecnt = ntohl (pkthdr->framecnt); - cpack = packet_cache_get_packet (global_packcache, framecnt); - cache_packet_add_fragment (cpack, rx_packet, rcv_len); - } while (!cache_packet_is_complete (cpack)); - memcpy (packet_buf, cpack->packet_buf, pkt_size); - cache_packet_reset (cpack); - *addr_size = from_len; - return pkt_size; -} - -int -netjack_recv (int sockfd, char *packet_buf, int pkt_size, int flags, int mtu) -{ - if (pkt_size <= mtu) - return recv (sockfd, packet_buf, pkt_size, flags); - char *rx_packet = alloca (mtu); - jacknet_packet_header *pkthdr = (jacknet_packet_header *) rx_packet; - int rcv_len; - jack_nframes_t framecnt; - cache_packet *cpack; - do - { - rcv_len = recv (sockfd, rx_packet, mtu, flags); - if (rcv_len < 0) - return rcv_len; - framecnt = ntohl (pkthdr->framecnt); - cpack = packet_cache_get_packet (global_packcache, framecnt); - cache_packet_add_fragment (cpack, rx_packet, rcv_len); - } while (!cache_packet_is_complete (cpack)); - memcpy (packet_buf, cpack->packet_buf, pkt_size); - cache_packet_reset (cpack); - return pkt_size; -} - void netjack_sendto (int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, int addr_size, int mtu) { @@ -1427,10 +1370,17 @@ render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_peri // audio port, decode celt data. CELTDecoder *decoder = src_node->data; +#if HAVE_CELT_API_0_8 + if( !packet_payload ) + celt_decode_float( decoder, NULL, net_period_down, buf, nframes ); + else + celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes ); +#else if( !packet_payload ) celt_decode_float( decoder, NULL, net_period_down, buf ); else celt_decode_float( decoder, packet_bufX, net_period_down, buf ); +#endif src_node = jack_slist_next (src_node); } @@ -1472,7 +1422,11 @@ render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs float *floatbuf = alloca (sizeof(float) * nframes ); memcpy( floatbuf, buf, nframes*sizeof(float) ); CELTEncoder *encoder = src_node->data; +#if HAVE_CELT_API_0_8 + encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up ); +#else encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); +#endif if( encoded_bytes != net_period_up ) printf( "something in celt changed. netjack needs to be changed to handle this.\n" ); src_node = jack_slist_next( src_node ); diff --git a/common/netjack_packet.h b/common/netjack_packet.h index 4617310e..c60f7bec 100644 --- a/common/netjack_packet.h +++ b/common/netjack_packet.h @@ -107,8 +107,6 @@ struct _packet_cache int last_framecnt_retreived_valid; }; -extern packet_cache *global_packcache; - // fragment cache function prototypes // XXX: Some of these are private. packet_cache *packet_cache_new(int num_packets, int pkt_size, int mtu); @@ -152,10 +150,6 @@ void render_jack_ports_to_payload(int bitdepth, JSList *playback_ports, JSList * // This one waits forever. an is not using ppoll int netjack_poll(int sockfd, int timeout); -// TODO: these are deprecated. -//int netjack_recvfrom(int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, socklen_t *addr_size, int mtu); -//int netjack_recv(int sockfd, char *packet_buf, int pkt_size, int flags, int mtu); - void decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf); void encode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf); #ifdef __cplusplus diff --git a/common/timestamps.c b/common/timestamps.c index 7a48e8a9..d8a2cda9 100644 --- a/common/timestamps.c +++ b/common/timestamps.c @@ -1,24 +1,25 @@ /* Copyright (C) 2002-2003 Paul Davis - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software + along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include +#include #include "timestamps.h" #include "JackTime.h" @@ -60,7 +61,7 @@ jack_dump_timestamps (FILE *out) unsigned long i; for (i = 0; i < timestamp_index; ++i) { - fprintf (out, "%-.32s %" PRIu64 " %" PRIu64, + fprintf (out, "%-.32s %" PRIu64 " %" PRIu64, timestamps[i].what, timestamps[i].when, timestamps[i].when - timestamps[0].when); if (i > 0) { diff --git a/example-clients/alsa_in.c b/example-clients/alsa_in.c index 85259cde..7007fffd 100644 --- a/example-clients/alsa_in.c +++ b/example-clients/alsa_in.c @@ -11,12 +11,11 @@ #include #include -#include #include #include #include -#include +#include #include "alsa/asoundlib.h" @@ -77,6 +76,12 @@ volatile float output_diff = 0.0; snd_pcm_uframes_t real_buffer_size; snd_pcm_uframes_t real_period_size; +// buffers + +char *tmpbuf; +char *outbuf; +float *resampbuf; + // format selection, and corresponding functions from memops in a nice set of structs. typedef struct alsa_format { @@ -307,8 +312,6 @@ double hann( double x ) */ int process (jack_nframes_t nframes, void *arg) { - char *outbuf; - float *resampbuf; int rlen; int err; snd_pcm_sframes_t delay = target_delay; @@ -322,10 +325,15 @@ int process (jack_nframes_t nframes, void *arg) { // this is for compensating xruns etc... if( delay > (target_delay+max_diff) ) { - char *tmp = alloca( (delay-target_delay) * formats[format].sample_size * num_channels ); - snd_pcm_readi( alsa_handle, tmp, delay-target_delay ); + output_new_delay = (int) delay; + while ((delay-target_delay) > 0) { + snd_pcm_uframes_t to_read = ((delay-target_delay) > 512) ? 512 : (delay-target_delay); + snd_pcm_readi( alsa_handle, tmpbuf, to_read ); + delay -= to_read; + } + delay = target_delay; // Set the resample_rate... we need to adjust the offset integral, to do this. @@ -399,13 +407,6 @@ int process (jack_nframes_t nframes, void *arg) { // Calculate resample_mean so we can init ourselves to saner values. resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor; - /* - * now this should do it... - */ - - outbuf = alloca( rlen * formats[format].sample_size * num_channels ); - - resampbuf = alloca( rlen * sizeof( float ) ); // get the data... again: @@ -465,6 +466,32 @@ again: return 0; } +/** + * the latency callback. + * sets up the latencies on the ports. + */ + +void +latency_cb (jack_latency_callback_mode_t mode, void *arg) +{ + jack_latency_range_t range; + JSList *node; + + range.min = range.max = target_delay; + + if (mode == JackCaptureLatency) { + for (node = capture_ports; node; node = jack_slist_next (node)) { + jack_port_t *port = node->data; + jack_port_set_latency_range (port, mode, &range); + } + } else { + for (node = playback_ports; node; node = jack_slist_next (node)) { + jack_port_t *port = node->data; + jack_port_set_latency_range (port, mode, &range); + } + } +} + /** * Allocate the necessary jack ports... @@ -661,6 +688,8 @@ int main (int argc, char *argv[]) { jack_on_shutdown (client, jack_shutdown, 0); + if (jack_set_latency_callback) + jack_set_latency_callback (client, latency_cb, 0); // get jack sample_rate @@ -716,6 +745,17 @@ int main (int argc, char *argv[]) { // alloc input ports, which are blasted out to alsa... alloc_ports( num_channels, 0 ); + outbuf = malloc( num_periods * period_size * formats[format].sample_size * num_channels ); + resampbuf = malloc( num_periods * period_size * sizeof( float ) ); + tmpbuf = malloc( 512 * formats[format].sample_size * num_channels ); + + if ((outbuf == NULL) || (resampbuf == NULL) || (tmpbuf == NULL)) + { + fprintf( stderr, "no memory for buffers.\n" ); + exit(20); + } + + memset( tmpbuf, 0, 512 * formats[format].sample_size * num_channels); /* tell the JACK server that we are ready to roll */ diff --git a/example-clients/alsa_out.c b/example-clients/alsa_out.c index 85b00e12..0dfb839f 100644 --- a/example-clients/alsa_out.c +++ b/example-clients/alsa_out.c @@ -11,12 +11,11 @@ #include #include -#include #include #include #include -#include +#include #include "alsa/asoundlib.h" @@ -35,6 +34,7 @@ snd_pcm_t *alsa_handle; int jack_sample_rate; int jack_buffer_size; +int quit = 0; double resample_mean = 1.0; double static_resample_factor = 1.0; double resample_lower_limit = 0.25; @@ -45,7 +45,6 @@ double *window_array; int offset_differential_index = 0; double offset_integral = 0; -int quit = 0; // ------------------------------------------------------ commandline parameters @@ -77,6 +76,12 @@ volatile float output_diff = 0.0; snd_pcm_uframes_t real_buffer_size; snd_pcm_uframes_t real_period_size; +// buffers + +char *tmpbuf; +char *outbuf; +float *resampbuf; + // format selection, and corresponding functions from memops in a nice set of structs. typedef struct alsa_format { @@ -90,6 +95,7 @@ typedef struct alsa_format { alsa_format_t formats[] = { { SND_PCM_FORMAT_FLOAT_LE, 4, sample_move_dS_floatLE, sample_move_floatLE_sSs, "float" }, { SND_PCM_FORMAT_S32, 4, sample_move_d32u24_sS, sample_move_dS_s32u24, "32bit" }, + { SND_PCM_FORMAT_S24_3LE, 3, sample_move_d24_sS, sample_move_dS_s24, "24bit - real" }, { SND_PCM_FORMAT_S24, 4, sample_move_d24_sS, sample_move_dS_s24, "24bit" }, { SND_PCM_FORMAT_S16, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit" } }; @@ -311,8 +317,6 @@ double hann( double x ) */ int process (jack_nframes_t nframes, void *arg) { - char *outbuf; - float *resampbuf; int rlen; int err; snd_pcm_sframes_t delay = target_delay; @@ -321,7 +325,6 @@ int process (jack_nframes_t nframes, void *arg) { delay = (num_periods*period_size)-snd_pcm_avail( alsa_handle ) ; delay -= jack_frames_since_cycle_start( client ); - delay += jack_get_buffer_size( client ) / 2; // Do it the hard way. // this is for compensating xruns etc... @@ -340,12 +343,15 @@ int process (jack_nframes_t nframes, void *arg) { offset_array[i] = 0.0; } if( delay < (target_delay-max_diff) ) { - char *tmp = alloca( (target_delay-delay) * formats[format].sample_size * num_channels ); - memset( tmp, 0, formats[format].sample_size * num_channels * (target_delay-delay) ); - snd_pcm_writei( alsa_handle, tmp, target_delay-delay ); output_new_delay = (int) delay; + while ((target_delay-delay) > 0) { + snd_pcm_uframes_t to_write = ((target_delay-delay) > 512) ? 512 : (target_delay-delay); + snd_pcm_writei( alsa_handle, tmpbuf, to_write ); + delay += to_write; + } + delay = target_delay; // Set the resample_rate... we need to adjust the offset integral, to do this. @@ -463,6 +469,32 @@ again: return 0; } +/** + * the latency callback. + * sets up the latencies on the ports. + */ + +void +latency_cb (jack_latency_callback_mode_t mode, void *arg) +{ + jack_latency_range_t range; + JSList *node; + + range.min = range.max = target_delay; + + if (mode == JackCaptureLatency) { + for (node = capture_ports; node; node = jack_slist_next (node)) { + jack_port_t *port = node->data; + jack_port_set_latency_range (port, mode, &range); + } + } else { + for (node = playback_ports; node; node = jack_slist_next (node)) { + jack_port_t *port = node->data; + jack_port_set_latency_range (port, mode, &range); + } + } +} + /** * Allocate the necessary jack ports... @@ -659,6 +691,8 @@ int main (int argc, char *argv[]) { jack_on_shutdown (client, jack_shutdown, 0); + if (jack_set_latency_callback) + jack_set_latency_callback (client, latency_cb, 0); // get jack sample_rate @@ -714,6 +748,16 @@ int main (int argc, char *argv[]) { // alloc input ports, which are blasted out to alsa... alloc_ports( 0, num_channels ); + outbuf = malloc( num_periods * period_size * formats[format].sample_size * num_channels ); + resampbuf = malloc( num_periods * period_size * sizeof( float ) ); + tmpbuf = malloc( 512 * formats[format].sample_size * num_channels ); + + if ((outbuf == NULL) || (resampbuf == NULL) || (tmpbuf == NULL)) + { + fprintf( stderr, "no memory for buffers.\n" ); + exit(20); + } + /* tell the JACK server that we are ready to roll */ diff --git a/example-clients/bufsize.c b/example-clients/bufsize.c index 72a0f9e8..09567f6c 100644 --- a/example-clients/bufsize.c +++ b/example-clients/bufsize.c @@ -2,7 +2,7 @@ * bufsize.c -- change JACK buffer size. * * Copyright (C) 2003 Jack O'Quin. - * + * * 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 @@ -64,12 +64,23 @@ void parse_arguments(int argc, char *argv[]) exit(9); } + if (strspn (argv[1], "0123456789") != strlen (argv[1])) { + fprintf(stderr, "usage: %s \n", package); + exit(8); + } + nframes = strtoul(argv[1], NULL, 0); if (errno == ERANGE) { - fprintf(stderr, "%s: invalid buffer size: %s\n", + fprintf(stderr, "%s: invalid buffer size: %s (range is 1-8182)\n", package, argv[1]); exit(2); } + + if (nframes < 1 || nframes > 8182) { + fprintf(stderr, "%s: invalid buffer size: %s (range is 1-8182)\n", + package, argv[1]); + exit(3); + } } int main(int argc, char *argv[]) diff --git a/example-clients/connect.c b/example-clients/connect.c index 635b2361..a4132cea 100644 --- a/example-clients/connect.c +++ b/example-clients/connect.c @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include jack_port_t *input_port; jack_port_t *output_port; @@ -33,17 +35,84 @@ int done = 0; #define TRUE 1 #define FALSE 0 - void port_connect_callback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg) { done = 1; } +void +show_version (char *my_name) +{ + //fprintf (stderr, "%s: JACK Audio Connection Kit version " VERSION "\n", my_name); +} + +void +show_usage (char *my_name) +{ + show_version (my_name); + fprintf (stderr, "\nusage: %s [options] port1 port2\n", my_name); + fprintf (stderr, "Connects two JACK ports together.\n\n"); + fprintf (stderr, " -s, --server Connect to the jack server named \n"); + fprintf (stderr, " -v, --version Output version information and exit\n"); + fprintf (stderr, " -h, --help Display this help message\n\n"); + fprintf (stderr, "For more information see http://jackaudio.org/\n"); +} + + int main (int argc, char *argv[]) { - jack_client_t* client = NULL; + jack_client_t *client; + jack_status_t status; + char *server_name = NULL; + int c; + int option_index; + jack_options_t options = JackNoStartServer; char *my_name = strrchr(argv[0], '/'); + jack_port_t *src_port = 0; + jack_port_t *dst_port = 0; + jack_port_t *port1 = 0; + jack_port_t *port2 = 0; + char portA[300]; + char portB[300]; + int use_uuid=0; + int connecting, disconnecting; + int port1_flags, port2_flags; + int rc = 1; + + struct option long_options[] = { + { "server", 1, 0, 's' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "uuid", 0, 0, 'u' }, + { 0, 0, 0, 0 } + }; + + while ((c = getopt_long (argc, argv, "s:hvu", long_options, &option_index)) >= 0) { + switch (c) { + case 's': + server_name = (char *) malloc (sizeof (char) * strlen(optarg)); + strcpy (server_name, optarg); + options |= JackServerName; + break; + case 'u': + use_uuid = 1; + break; + case 'h': + show_usage (my_name); + return 1; + break; + case 'v': + show_version (my_name); + return 1; + break; + default: + show_usage (my_name); + return 1; + break; + } + } + connecting = disconnecting = FALSE; if (my_name == 0) { my_name = argv[0]; @@ -51,90 +120,121 @@ main (int argc, char *argv[]) my_name ++; } - printf("name %s\n", my_name); - - if (strstr(my_name, "jack_disconnect")) { - disconnecting = TRUE; - } else - if (strstr(my_name, "jack_connect")) { - connecting = TRUE; + if (strstr(my_name, "disconnect")) { + disconnecting = 1; + } else if (strstr(my_name, "connect")) { + connecting = 1; } else { fprintf(stderr, "ERROR! client should be called jack_connect or jack_disconnect. client is called %s\n", my_name); return 1; } - if (argc != 3) { - fprintf (stderr, "usage: %s \n", my_name); - fprintf(stderr, "The source port must be an output port of the source client.\n"); - fprintf (stderr, "The destination port must be an input port of the destination client.\n"); - return 1; - } + if (argc < 3) show_usage(my_name); /* try to become a client of the JACK server */ - if ((client = jack_client_open (my_name, JackNullOption, NULL)) == 0) { + if ((client = jack_client_open (my_name, options, &status, server_name)) == 0) { fprintf (stderr, "jack server not running?\n"); return 1; } jack_set_port_connect_callback(client, port_connect_callback, NULL); - /* display the current sample rate. once the client is activated - (see below), you should rely on your own sample rate - callback (see above) for this value. - */ - /* find the two ports */ - if ((input_port = jack_port_by_name(client, argv[1])) == 0) { - fprintf (stderr, "ERROR %s not a valid port\n", argv[1]); - goto error; + if( use_uuid ) { + char *tmpname; + char *clientname; + char *portname; + tmpname = strdup( argv[argc-1] ); + portname = strchr( tmpname, ':' ); + portname[0] = '\0'; + portname+=1; + clientname = jack_get_client_name_by_uuid( client, tmpname ); + if( clientname ) { + + snprintf( portA, sizeof(portA), "%s:%s", clientname, portname ); + jack_free( clientname ); + } else { + snprintf( portA, sizeof(portA), "%s", argv[argc-1] ); + } + free( tmpname ); + + tmpname = strdup( argv[argc-2] ); + portname = strchr( tmpname, ':' ); + portname[0] = '\0'; + portname+=1; + clientname = jack_get_client_name_by_uuid( client, tmpname ); + if( clientname ) { + snprintf( portB, sizeof(portB), "%s:%s", clientname, portname ); + jack_free( clientname ); + } else { + snprintf( portB, sizeof(portB), "%s", argv[argc-2] ); + } + + free( tmpname ); + + } else { + snprintf( portA, sizeof(portA), "%s", argv[argc-1] ); + snprintf( portB, sizeof(portB), "%s", argv[argc-2] ); } - if ((output_port = jack_port_by_name(client, argv[2])) == 0) { - fprintf (stderr, "ERROR %s not a valid port\n", argv[2]); - goto error; + if ((port1 = jack_port_by_name(client, portA)) == 0) { + fprintf (stderr, "ERROR %s not a valid port\n", portA); + goto exit; + } + if ((port2 = jack_port_by_name(client, portB)) == 0) { + fprintf (stderr, "ERROR %s not a valid port\n", portB); + goto exit; + } + + port1_flags = jack_port_flags (port1); + port2_flags = jack_port_flags (port2); + + if (port1_flags & JackPortIsInput) { + if (port2_flags & JackPortIsOutput) { + src_port = port2; + dst_port = port1; + } + } else { + if (port2_flags & JackPortIsInput) { + src_port = port1; + dst_port = port2; + } } - /* tell the JACK server that we are ready to roll */ - - if (jack_activate (client)) { - fprintf (stderr, "cannot activate client"); - goto error; + if (!src_port || !dst_port) { + fprintf (stderr, "arguments must include 1 input port and 1 output port\n"); + goto exit; } /* connect the ports. Note: you can't do this before the client is activated (this may change in the future). */ - if (connecting) { - if (jack_connect(client, jack_port_name(input_port), jack_port_name(output_port))) { - fprintf (stderr, "cannot connect ports\n"); - goto error; - } + if (connecting) { + if (jack_connect(client, jack_port_name(src_port), jack_port_name(dst_port))) { + goto exit; + } } if (disconnecting) { - if (jack_disconnect(client, jack_port_name(input_port), jack_port_name(output_port))) { - fprintf (stderr, "cannot disconnect ports\n"); - goto error; - } + if (jack_disconnect(client, jack_port_name(src_port), jack_port_name(dst_port))) { + goto exit; + } } // Wait for connection/disconnection to be effective - while(!done) { - #ifdef WIN32 - Sleep(10); - #else - usleep(10000); - #endif + while(!done) { + #ifdef WIN32 + Sleep(10); + #else + usleep(10000); + #endif } - jack_deactivate (client); - jack_client_close (client); - return 0; + /* everything was ok, so setting exitcode to 0 */ + rc = 0; -error: - if (client) - jack_client_close (client); - return 1; +exit: + jack_client_close (client); + exit (rc); } - diff --git a/example-clients/latent_client.c b/example-clients/latent_client.c new file mode 100644 index 00000000..67217832 --- /dev/null +++ b/example-clients/latent_client.c @@ -0,0 +1,215 @@ +/** @file simple_client.c + * + * @brief This simple client demonstrates the most basic features of JACK + * as they would be used by many applications. + */ + +#include +#include +#include +#include +#include +#include + +#include + +jack_port_t *input_port; +jack_port_t *output_port; +jack_client_t *client; + +jack_default_audio_sample_t *delay_line; +jack_nframes_t delay_index; +jack_nframes_t latency = 1024; + +#ifdef WIN32 +#define jack_sleep(val) Sleep((val)) +#else +#define jack_sleep(val) usleep((val) * 1000) +#endif + +/** + * The process callback for this JACK application is called in a + * special realtime thread once for each audio cycle. + * + * This client does nothing more than copy data from its input + * port to its output port. It will exit when stopped by + * the user (e.g. using Ctrl-C on a unix-ish operating system) + */ +int +process (jack_nframes_t nframes, void *arg) +{ + jack_default_audio_sample_t *in, *out; + int k; + + in = jack_port_get_buffer (input_port, nframes); + out = jack_port_get_buffer (output_port, nframes); + + for (k=0; k #endif #include -#include +#include +#include #include char * my_name; @@ -39,6 +40,7 @@ show_usage (void) fprintf (stderr, "List active Jack ports, and optionally display extra information.\n"); fprintf (stderr, "Optionally filter ports which match ALL strings provided after any options.\n\n"); fprintf (stderr, "Display options:\n"); + fprintf (stderr, " -s, --server Connect to the jack server named \n"); fprintf (stderr, " -A, --aliases List aliases for each port\n"); fprintf (stderr, " -c, --connections List connections to/from each port\n"); fprintf (stderr, " -l, --latency Display per-port latency in frames at each port\n"); @@ -56,6 +58,7 @@ main (int argc, char *argv[]) { jack_client_t *client; jack_status_t status; + jack_options_t options = JackNoStartServer; const char **ports, **connections; unsigned int i, j, k; int skip_port; @@ -68,9 +71,11 @@ main (int argc, char *argv[]) int c; int option_index; char* aliases[2]; + char *server_name = NULL; jack_port_t *port; - + struct option long_options[] = { + { "server", 1, 0, 's' }, { "aliases", 0, 0, 'A' }, { "connections", 0, 0, 'c' }, { "port-latency", 0, 0, 'l' }, @@ -89,8 +94,13 @@ main (int argc, char *argv[]) my_name ++; } - while ((c = getopt_long (argc, argv, "AclLphvt", long_options, &option_index)) >= 0) { + while ((c = getopt_long (argc, argv, "s:AclLphvt", long_options, &option_index)) >= 0) { switch (c) { + case 's': + server_name = (char *) malloc (sizeof (char) * strlen(optarg)); + strcpy (server_name, optarg); + options |= JackServerName; + break; case 'A': aliases[0] = (char *) malloc (jack_port_name_size()); aliases[1] = (char *) malloc (jack_port_name_size()); @@ -131,7 +141,7 @@ main (int argc, char *argv[]) * specify JackNoStartServer. */ //JOQ: need a new server name option - client = jack_client_open ("lsp", JackNoStartServer, &status); + client = jack_client_open ("lsp", options, &status, server_name); if (client == NULL) { if (status & JackServerFailed) { fprintf (stderr, "JACK server not running\n"); @@ -143,7 +153,7 @@ main (int argc, char *argv[]) } ports = jack_get_ports (client, NULL, NULL, 0); - if (!ports) + if (!ports) goto error; for (i = 0; ports && ports[i]; ++i) { @@ -168,19 +178,28 @@ main (int argc, char *argv[]) printf (" %s\n", aliases[i]); } } - + if (show_con) { if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) { for (j = 0; connections[j]; j++) { printf (" %s\n", connections[j]); } free (connections); - } + } } if (show_port_latency) { if (port) { - printf (" port latency = %d frames\n", + jack_latency_range_t range; + printf (" port latency = %" PRIu32 " frames\n", jack_port_get_latency (port)); + + jack_port_get_latency_range (port, JackPlaybackLatency, &range); + printf (" port playback latency = [ %" PRIu32 " %" PRIu32 " ] frames\n", + range.min, range.max); + + jack_port_get_latency_range (port, JackCaptureLatency, &range); + printf (" port capture latency = [ %" PRIu32 " %" PRIu32 " ] frames\n", + range.min, range.max); } } if (show_total_latency) { @@ -208,12 +227,7 @@ main (int argc, char *argv[]) if (flags & JackPortIsTerminal) { fputs ("terminal,", stdout); } - - if (flags & JackPortIsActive) { - fputs ("active,", stdout); - } else { - fputs ("non-active,", stdout); - } + putc ('\n', stdout); } } @@ -225,7 +239,7 @@ main (int argc, char *argv[]) } } } - + error: if (ports) jack_free (ports); diff --git a/example-clients/midi_dump.c b/example-clients/midi_dump.c new file mode 100644 index 00000000..81926283 --- /dev/null +++ b/example-clients/midi_dump.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include + +static jack_port_t* port; + +static void +describe (jack_midi_event_t* event, char* buffer, size_t buflen) +{ + assert (buflen > 0); + + buffer[0] = '\0'; + + if (event->size == 0) { + return; + } + + int type = event->buffer[0] & 0xf0; + int channel = event->buffer[0] & 0xf; + + switch (type) { + case 0x90: + assert (event->size == 3); + snprintf (buffer, buflen, "note on (channel %d): pitch %d, velocity %d", channel, event->buffer[1], event->buffer[2]); + break; + case 0x80: + assert (event->size == 3); + snprintf (buffer, buflen, "note off (channel %d): pitch %d, velocity %d", channel, event->buffer[1], event->buffer[2]); + break; + case 0xb0: + assert (event->size == 3); + snprintf (buffer, buflen, "control change (channel %d): controller %d, value %d", channel, event->buffer[1], event->buffer[2]); + break; + default: + break; + } +} + +int +process (jack_nframes_t frames, void* arg) +{ + void* buffer; + jack_nframes_t N; + jack_nframes_t i; + char description[256]; + + buffer = jack_port_get_buffer (port, frames); + assert (buffer); + + N = jack_midi_get_event_count (buffer); + for (i = 0; i < N; ++i) { + jack_midi_event_t event; + int r; + + r = jack_midi_event_get (&event, buffer, i); + if (r == 0) { + size_t j; + + printf ("%d:", event.time); + for (j = 0; j < event.size; ++j) { + printf (" %x", event.buffer[j]); + } + + describe (&event, description, sizeof (description)); + printf (" %s", description); + + printf ("\n"); + } + } + + return 0; +} + + +int +main (int argc, char* argv[]) +{ + jack_client_t* client; + char const default_name[] = "midi-monitor"; + char const * client_name; + int r; + + if (argc == 2) { + client_name = argv[1]; + } else { + client_name = default_name; + } + + client = jack_client_open (client_name, JackNullOption, NULL); + if (client == NULL) { + fprintf (stderr, "Could not create JACK client.\n"); + exit (EXIT_FAILURE); + } + + jack_set_process_callback (client, process, 0); + + port = jack_port_register (client, "input", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); + if (port == NULL) { + fprintf (stderr, "Could not register port.\n"); + exit (EXIT_FAILURE); + } + + r = jack_activate (client); + if (r != 0) { + fprintf (stderr, "Could not activate client.\n"); + exit (EXIT_FAILURE); + } + + sleep (-1); + + return 0; +} diff --git a/example-clients/netsource.c b/example-clients/netsource.c index 9f995406..f3cd8274 100644 --- a/example-clients/netsource.c +++ b/example-clients/netsource.c @@ -86,6 +86,7 @@ int reply_port = 0; int bind_port = 0; int redundancy = 1; jack_client_t *client; +packet_cache * packcache = 0; int state_connected = 0; int state_latency = 0; @@ -140,7 +141,7 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int } if( bitdepth == 1000 ) { #if HAVE_CELT -#if HAVE_CELT_API_0_7 +#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); #else @@ -183,7 +184,7 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int } if( bitdepth == 1000 ) { #if HAVE_CELT -#if HAVE_CELT_API_0_7 +#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); #else @@ -224,6 +225,9 @@ sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) static int latency_count = 0; int retval = sync_state; + if (! state_connected) { + return 1; + } if (latency_count) { latency_count--; retval = 0; @@ -329,7 +333,7 @@ process (jack_nframes_t nframes, void *arg) else if (cont_miss > 50+5*latency) { state_connected = 0; - packet_cache_reset_master_address( global_packcache ); + packet_cache_reset_master_address( packcache ); //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); cont_miss = 0; } @@ -355,19 +359,19 @@ process (jack_nframes_t nframes, void *arg) if ( ! netjack_poll_deadline( input_fd, deadline ) ) break; - packet_cache_drain_socket(global_packcache, input_fd); + packet_cache_drain_socket(packcache, input_fd); - if (packet_cache_get_next_available_framecnt( global_packcache, framecnt - latency, &got_frame )) + if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame )) if( got_frame == (framecnt - latency) ) break; } } else { // normally: // only drain socket. - packet_cache_drain_socket(global_packcache, input_fd); + packet_cache_drain_socket(packcache, input_fd); } - size = packet_cache_retreive_packet_pointer( global_packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp ); + size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp ); /* First alternative : we received what we expected. Render the data * to the JACK ports so it can be played. */ if (size == rx_bufsize) @@ -394,7 +398,7 @@ process (jack_nframes_t nframes, void *arg) state_recv_packet_queue_time = recv_time_offset; state_connected = 1; sync_state = pkthdr_rx->sync_state; - packet_cache_release_packet( global_packcache, framecnt - latency ); + packet_cache_release_packet( packcache, framecnt - latency ); } /* Second alternative : we've received something that's not * as big as expected or we missed a packet. We render silence @@ -402,7 +406,7 @@ process (jack_nframes_t nframes, void *arg) else { jack_nframes_t latency_estimate; - if( packet_cache_find_latency( global_packcache, framecnt, &latency_estimate ) ) + if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) //if( (state_latency == 0) || (latency_estimate < state_latency) ) state_latency = latency_estimate; @@ -468,7 +472,7 @@ process (jack_nframes_t nframes, void *arg) else if (cont_miss > 50+5*latency) { state_connected = 0; - packet_cache_reset_master_address( global_packcache ); + packet_cache_reset_master_address( packcache ); //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); cont_miss = 0; } @@ -501,12 +505,11 @@ init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t por if (hostinfo == NULL) { fprintf (stderr, "init_sockaddr_in: unknown host: %s.\n", hostname); fflush( stderr ); - return; } #ifdef WIN32 - name->sin_addr.s_addr = inet_addr( hostname ); + name->sin_addr.s_addr = inet_addr( hostname ); #else - name->sin_addr = *(struct in_addr *) hostinfo->h_addr ; + name->sin_addr = *(struct in_addr *) hostinfo->h_addr ; #endif } else @@ -621,15 +624,15 @@ main (int argc, char *argv[]) case 'b': bitdepth = atoi (optarg); break; - case 'c': - #if HAVE_CELT - bitdepth = 1000; + case 'c': +#if HAVE_CELT + bitdepth = 1000; factor = atoi (optarg); - #else +#else printf( "not built with celt supprt\n" ); exit(10); - #endif - break; +#endif + break; case 'm': mtu = atoi (optarg); break; @@ -676,17 +679,18 @@ main (int argc, char *argv[]) } init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_port); - if (bind_port) { + if(bind_port) { init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, bind_port); if( bind (outsockfd, &bindaddr, sizeof (bindaddr)) ) { - fprintf (stderr, "bind failure\n" ); - } + fprintf (stderr, "bind failure\n" ); + } } - if (reply_port) { + if(reply_port) + { init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port); if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) { - fprintf (stderr, "bind failure\n" ); - } + fprintf (stderr, "bind failure\n" ); + } } /* try to become a client of the JACK server */ @@ -712,7 +716,7 @@ main (int argc, char *argv[]) net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor); int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); - global_packcache = packet_cache_new (latency + 50, rx_bufsize, mtu); + packcache = packet_cache_new (latency + 50, rx_bufsize, mtu); /* tell the JACK server that we are ready to roll */ if (jack_activate (client)) @@ -778,6 +782,6 @@ main (int argc, char *argv[]) } jack_client_close (client); - packet_cache_free (global_packcache); + packet_cache_free (packcache); exit (0); } diff --git a/example-clients/session_notify.c b/example-clients/session_notify.c index e8a6d517..9cb3f894 100644 --- a/example-clients/session_notify.c +++ b/example-clients/session_notify.c @@ -25,12 +25,11 @@ #include #include #include -#include #include #include #include -char *package; /* program name */ +char *package; /* program name */ jack_client_t *client; jack_session_event_type_t notify_type; @@ -38,147 +37,145 @@ char *save_path = NULL; void jack_shutdown(void *arg) { - fprintf(stderr, "JACK shut down, exiting ...\n"); - exit(1); + fprintf(stderr, "JACK shut down, exiting ...\n"); + exit(1); } void signal_handler(int sig) { - jack_client_close(client); - fprintf(stderr, "signal received, exiting ...\n"); - exit(0); + jack_client_close(client); + fprintf(stderr, "signal received, exiting ...\n"); + exit(0); } void parse_arguments(int argc, char *argv[]) { - /* basename $0 */ - package = strrchr(argv[0], '/'); - if (package == 0) - package = argv[0]; - else - package++; - - if (argc==2) { - if( !strcmp( argv[1], "quit" ) ) { - notify_type = JackSessionSaveAndQuit; - return; - } - } - if (argc==3) { - if( !strcmp( argv[1], "save" ) ) { - notify_type = JackSessionSave; - save_path = argv[2]; - return; - } - - } - fprintf(stderr, "usage: %s quit|save [path]\n", package); - exit(9); + /* basename $0 */ + package = strrchr(argv[0], '/'); + if (package == 0) + package = argv[0]; + else + package++; + + if (argc==2) { + if( !strcmp( argv[1], "quit" ) ) { + notify_type = JackSessionSaveAndQuit; + return; + } + } + if (argc==3) { + if( !strcmp( argv[1], "save" ) ) { + notify_type = JackSessionSave; + save_path = argv[2]; + return; + } + + } + fprintf(stderr, "usage: %s quit|save [path]\n", package); + exit(9); } typedef struct { - char name[32]; - char uuid[16]; + char name[32]; + char uuid[16]; } uuid_map_t; JSList *uuid_map = NULL; void add_uuid_mapping( const char *uuid ) { - char *clientname = jack_get_client_name_by_uuid( client, uuid ); - if( !clientname ) { - printf( "error... cant find client for uuid %s", uuid ); - - return; - } - - uuid_map_t *mapping = malloc( sizeof(uuid_map_t) ); - snprintf( mapping->uuid, sizeof(mapping->uuid), "%s", uuid ); - snprintf( mapping->name, sizeof(mapping->name), "%s", clientname ); - uuid_map = jack_slist_append( uuid_map, mapping ); + char *clientname = jack_get_client_name_by_uuid( client, uuid ); + if( !clientname ) { + printf( "error... cant find client for uuid" ); + return; + } + + uuid_map_t *mapping = malloc( sizeof(uuid_map_t) ); + snprintf( mapping->uuid, sizeof(mapping->uuid), "%s", uuid ); + snprintf( mapping->name, sizeof(mapping->name), "%s", clientname ); + uuid_map = jack_slist_append( uuid_map, mapping ); } char *map_port_name_to_uuid_port( const char *port_name ) { - JSList *node; - char retval[300]; - char *port_component = strchr( port_name,':' ); - char *client_component = strdup( port_name ); - strchr( client_component, ':' )[0] = '\0'; - - sprintf( retval, "%s", port_name ); - - for( node=uuid_map; node; node=jack_slist_next(node) ) { - uuid_map_t *mapping = node->data; - if( !strcmp( mapping->name, client_component ) ) { - sprintf( retval, "%s%s", mapping->uuid, port_component ); - break; - } - } - - return strdup(retval); + JSList *node; + char retval[300]; + char *port_component = strchr( port_name,':' ); + char *client_component = strdup( port_name ); + strchr( client_component, ':' )[0] = '\0'; + + sprintf( retval, "%s", port_name ); + + for( node=uuid_map; node; node=jack_slist_next(node) ) { + uuid_map_t *mapping = node->data; + if( !strcmp( mapping->name, client_component ) ) { + sprintf( retval, "%s%s", mapping->uuid, port_component ); + break; + } + } + + return strdup(retval); } int main(int argc, char *argv[]) { - parse_arguments(argc, argv); - jack_session_command_t *retval; - int k,i,j; - - - /* become a JACK client */ - if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) { - fprintf(stderr, "JACK server not running?\n"); - exit(1); - } - - signal(SIGQUIT, signal_handler); - signal(SIGTERM, signal_handler); - signal(SIGHUP, signal_handler); - signal(SIGINT, signal_handler); - - jack_on_shutdown(client, jack_shutdown, 0); - - jack_activate(client); - - - retval = jack_session_notify( client, NULL, notify_type, save_path ); - printf( "retval = %p\n", retval ); - for(i=0; retval[i].uuid; i++ ) { - printf( "export SESSION_DIR=\"%s%s/\"\n", save_path, retval[i].client_name ); - printf( "%s &\n", retval[i].command ); - add_uuid_mapping(retval[i].uuid); - } - - printf( "sleep 10\n" ); - - for(k=0; retval[k].uuid; k++ ) { - - char* port_regexp = alloca( jack_client_name_size()+3 ); - char* client_name = jack_get_client_name_by_uuid( client, retval[k].uuid ); - snprintf( port_regexp, jack_client_name_size()+3, "%s:.*", client_name ); - jack_free(client_name); - const char **ports = jack_get_ports( client, port_regexp, NULL, 0 ); - if( !ports ) { - continue; - } - for (i = 0; ports[i]; ++i) { - const char **connections; - if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) { - for (j = 0; connections[j]; j++) { - char *src = map_port_name_to_uuid_port( ports[i] ); - char *dst = map_port_name_to_uuid_port( connections[j] ); - printf( "jack_connect -u \"%s\" \"%s\"\n", src, dst ); - } - jack_free (connections); - } - } - jack_free(ports); - - } - jack_session_commands_free(retval); - - jack_client_close(client); - - return 0; + parse_arguments(argc, argv); + jack_session_command_t *retval; + int k,i,j; + + + /* become a JACK client */ + if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) { + fprintf(stderr, "JACK server not running?\n"); + exit(1); + } + + signal(SIGQUIT, signal_handler); + signal(SIGTERM, signal_handler); + signal(SIGHUP, signal_handler); + signal(SIGINT, signal_handler); + + jack_on_shutdown(client, jack_shutdown, 0); + + jack_activate(client); + + + retval = jack_session_notify( client, NULL, notify_type, save_path ); + for(i=0; retval[i].uuid; i++ ) { + printf( "export SESSION_DIR=\"%s%s/\"\n", save_path, retval[i].client_name ); + printf( "%s &\n", retval[i].command ); + add_uuid_mapping(retval[i].uuid); + } + + printf( "sleep 10\n" ); + + for(k=0; retval[k].uuid; k++ ) { + + char* port_regexp = alloca( jack_client_name_size()+3 ); + char* client_name = jack_get_client_name_by_uuid( client, retval[k].uuid ); + snprintf( port_regexp, jack_client_name_size()+3, "%s:.*", client_name ); + jack_free(client_name); + const char **ports = jack_get_ports( client, port_regexp, NULL, 0 ); + if( !ports ) { + continue; + } + for (i = 0; ports[i]; ++i) { + const char **connections; + if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) { + for (j = 0; connections[j]; j++) { + char *src = map_port_name_to_uuid_port( ports[i] ); + char *dst = map_port_name_to_uuid_port( connections[j] ); + printf( "jack_connect -u \"%s\" \"%s\"\n", src, dst ); + } + jack_free (connections); + } + } + jack_free(ports); + + } + jack_session_commands_free(retval); + + jack_client_close(client); + + return 0; } diff --git a/example-clients/wscript b/example-clients/wscript index 1b07b0b1..54a6a599 100644 --- a/example-clients/wscript +++ b/example-clients/wscript @@ -27,6 +27,8 @@ example_programs = { 'jack_server_control' : 'server_control.cpp', 'jack_net_slave' : 'netslave.c', 'jack_net_master' : 'netmaster.c', + 'jack_latent_client' : 'latent_client.c', + 'jack_midi_dump' : 'midi_dump.c', } example_libs = { @@ -130,12 +132,6 @@ def build(bld): prog.includes = os_incdir + ['../common/jack', '../common'] prog.source = ['netsource.c', '../common/netjack_packet.c'] prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR") - # Seems uneeded here... - #if bld.env['HAVE_CELT']: - #if bld.env['HAVE_CELT_API_0_5']: - # prog.defines = ['HAVE_CELT', 'HAVE_CELT_API_0_5'] - #elif bld.env['HAVE_CELT_API_0_7']: - # prog.defines = ['HAVE_CELT', 'HAVE_CELT_API_0_7'] prog.uselib = 'CELT SAMPLERATE' prog.uselib_local = 'clientlib' prog.target = 'jack_netsource' diff --git a/linux/JackAtomic_os.h b/linux/JackAtomic_os.h index 37181e04..e201d0d6 100644 --- a/linux/JackAtomic_os.h +++ b/linux/JackAtomic_os.h @@ -69,12 +69,15 @@ static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* ad #endif + + + #if !defined(__i386__) && !defined(__x86_64__) && !defined(__PPC__) -#warning using builtin gcc (version > 4.1) atomic + static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) { - return __sync_bool_compare_and_swap (&addr, value, newvalue); + return __sync_bool_compare_and_swap ((UInt32*)addr, value, newvalue); } #endif diff --git a/linux/JackLinuxTime.c b/linux/JackLinuxTime.c index 37ae9fb0..d8b474eb 100644 --- a/linux/JackLinuxTime.c +++ b/linux/JackLinuxTime.c @@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include +#include static jack_time_t __jack_cpu_mhz = 0; jack_time_t (*_jack_get_microseconds)(void) = 0; diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index efcc1f94..fdf5a0cb 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -276,7 +276,7 @@ JackAlsaDriver::alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) } else { driver->channel_copy = memcpy_fake; } - + switch (driver->dither) { case Rectangular: jack_info("Rectangular dithering at 16 bits"); @@ -284,42 +284,42 @@ JackAlsaDriver::alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) sample_move_dither_rect_d16_sSs: sample_move_dither_rect_d16_sS; break; - + case Triangular: jack_info("Triangular dithering at 16 bits"); driver->write_via_copy = driver->quirk_bswap? sample_move_dither_tri_d16_sSs: sample_move_dither_tri_d16_sS; break; - + case Shaped: jack_info("Noise-shaped dithering at 16 bits"); driver->write_via_copy = driver->quirk_bswap? sample_move_dither_shaped_d16_sSs: sample_move_dither_shaped_d16_sS; break; - + default: driver->write_via_copy = driver->quirk_bswap? - sample_move_d16_sSs : + sample_move_d16_sSs : sample_move_d16_sS; break; } break; - + case 3: /* NO DITHER */ if (driver->playback_interleaved) { driver->channel_copy = memcpy_interleave_d24_s24; } else { driver->channel_copy = memcpy_fake; } - + driver->write_via_copy = driver->quirk_bswap? - sample_move_d24_sSs: + sample_move_d24_sSs: sample_move_d24_sS; break; - + case 4: /* NO DITHER */ if (driver->playback_interleaved) { driver->channel_copy = memcpy_interleave_d32_s32; @@ -328,7 +328,7 @@ JackAlsaDriver::alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) } driver->write_via_copy = driver->quirk_bswap? - sample_move_d32u24_sSs: + sample_move_d32u24_sSs: sample_move_d32u24_sS; break; @@ -339,27 +339,27 @@ JackAlsaDriver::alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) } } } - + if (driver->capture_handle) { switch (driver->capture_sample_bytes) { case 2: driver->read_via_copy = driver->quirk_bswap? - sample_move_dS_s16s: + sample_move_dS_s16s: sample_move_dS_s16; break; case 3: driver->read_via_copy = driver->quirk_bswap? - sample_move_dS_s24s: + sample_move_dS_s24s: sample_move_dS_s24; break; case 4: driver->read_via_copy = driver->quirk_bswap? - sample_move_dS_s32u24s: + sample_move_dS_s32u24s: sample_move_dS_s32u24; break; } } - + return 0; } @@ -418,7 +418,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic } } } - + format = (sample_width == 4) ? 0 : NUMFORMATS - 1; while (1) { @@ -444,7 +444,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic jack_info ("ALSA: final selected sample format for %s: %s", stream_name, formats[format].Name); break; } - } + } frame_rate = driver->frame_rate ; err = snd_pcm_hw_params_set_rate_near (handle, hw_params, @@ -464,7 +464,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic &channels_max); *nchns = channels_max ; - if (*nchns > 1024) { + if (*nchns > 1024) { /* the hapless user is an unwitting victim of the "default" ALSA PCM device, which can @@ -481,9 +481,9 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic "instead rather than using the plug layer. Usually the name of the\n" "hardware device that corresponds to the first sound card is hw:0\n" ); - *nchns = 2; + *nchns = 2; } - } + } if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, *nchns)) < 0) { @@ -491,7 +491,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic *nchns, stream_name); return -1; } - + if ((err = snd_pcm_hw_params_set_period_size (handle, hw_params, driver->frames_per_cycle, 0)) @@ -520,7 +520,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic return -1; } jack_info ("ALSA: use %d periods for %s", *nperiodsp, stream_name); -#if 0 +#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"); @@ -557,7 +557,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic if (driver->soft_mode) { stop_th = (snd_pcm_uframes_t)-1; } - + if ((err = snd_pcm_sw_params_set_stop_threshold ( handle, sw_params, stop_th)) < 0) { jack_error ("ALSA: cannot set stop mode for %s", @@ -594,7 +594,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic else err = snd_pcm_sw_params_set_avail_min ( handle, sw_params, driver->frames_per_cycle); - + if (err < 0) { jack_error ("ALSA: cannot set avail min for %s", stream_name); return -1; @@ -1158,7 +1158,7 @@ int JackAlsaDriver::alsa_driver_restart (alsa_driver_t *driver) { int res; - + driver->xrun_recovery = 1; if ((res = Stop()) == 0) res = Start(); @@ -1189,11 +1189,24 @@ JackAlsaDriver::alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed } } + if (snd_pcm_status_get_state(status) == SND_PCM_STATE_SUSPENDED) { + jack_error("**** alsa_pcm: pcm in suspended state, resuming it" ); + if (driver->capture_handle) { + if ((res = snd_pcm_prepare(driver->capture_handle)) < 0) { + jack_error("error preparing after suspend: %s", snd_strerror(res)); + } + } else { + if ((res = snd_pcm_prepare(driver->playback_handle)) < 0) { + jack_error("error preparing after suspend: %s", snd_strerror(res)); + } + } + } + if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN && driver->process_count > XRUN_REPORT_DELAY) { struct timeval now, diff, tstamp; driver->xrun_count++; - snd_pcm_status_get_tstamp(status,&now); + snd_pcm_status_get_tstamp(status,&now); snd_pcm_status_get_trigger_tstamp(status, &tstamp); timersub(&now, &tstamp, &diff); *delayed_usecs = diff.tv_sec * 1000000.0 + diff.tv_usec; @@ -1253,7 +1266,7 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat } again: - + while (need_playback || need_capture) { int poll_result; @@ -1269,7 +1282,7 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat driver->playback_nfds); nfds += driver->playback_nfds; } - + if (need_capture) { snd_pcm_poll_descriptors (driver->capture_handle, &driver->pfd[nfds], @@ -1279,7 +1292,7 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat } /* ALSA doesn't set POLLERR in some versions of 0.9.X */ - + for (i = 0; i < nfds; i++) { driver->pfd[i].events |= POLLERR; } @@ -1316,12 +1329,12 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat *status = -2; return 0; } - + jack_error ("ALSA: poll call failed (%s)", strerror (errno)); *status = -3; return 0; - + } poll_ret = jack_get_microseconds (); @@ -1332,12 +1345,12 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat if (extra_fd < 0) { if (driver->poll_next && poll_ret > driver->poll_next) { *delayed_usecs = poll_ret - driver->poll_next; - } + } driver->poll_last = poll_ret; driver->poll_next = poll_ret + driver->period_usecs; // steph /* - driver->engine->transport_cycle_start (driver->engine, + driver->engine->transport_cycle_start (driver->engine, poll_ret); */ } @@ -1358,7 +1371,7 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat *status = -4; return -1; - } + } /* if POLLIN was the only bit set, we're OK */ @@ -1414,14 +1427,14 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat #endif } } - + if (poll_result == 0) { jack_error ("ALSA: poll time out, polled for %" PRIu64 " usecs", poll_ret - poll_enter); *status = -5; return 0; - } + } } @@ -1437,7 +1450,7 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat } } else { /* odd, but see min() computation below */ - capture_avail = INT_MAX; + capture_avail = INT_MAX; } if (driver->playback_handle) { @@ -1452,7 +1465,7 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat } } else { /* odd, but see min() computation below */ - playback_avail = INT_MAX; + playback_avail = INT_MAX; } if (xrun_detected) { @@ -1531,7 +1544,7 @@ JackAlsaDriver::alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes) if (!driver->capture_handle) { return 0; } - + nread = 0; contiguous = 0; orig_nframes = nframes; @@ -1559,11 +1572,11 @@ JackAlsaDriver::alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes) /* // steph for (chn = 0, node = driver->capture_ports; node; node = jack_slist_next (node), chn++) { - + port = (jack_port_t *) node->data; - + if (!jack_port_connected (port)) { - // no-copy optimization + // no-copy optimization continue; } buf = jack_port_get_buffer (port, orig_nframes); @@ -1574,7 +1587,7 @@ JackAlsaDriver::alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes) if ((err = snd_pcm_mmap_commit (driver->capture_handle, offset, contiguous)) < 0) { - + jack_error ("ALSA: could not complete read of %" PRIu32 " frames: error = %d\n", contiguous, err); return -1; @@ -1702,7 +1715,7 @@ JackAlsaDriver::alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes } monbuf = jack_port_get_buffer (port, orig_nframes); memcpy (monbuf + nwritten, buf + nwritten, contiguous * sizeof(jack_default_audio_sample_t)); - mon_node = jack_slist_next (mon_node); + mon_node = jack_slist_next (mon_node); } } */ @@ -1716,7 +1729,7 @@ JackAlsaDriver::alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes offset, contiguous)) < 0) { jack_error ("ALSA: could not complete playback of %" PRIu32 " frames: error = %d", contiguous, err); - if (err != EPIPE && err != ESTRPIPE) + if (err != -EPIPE && err != -ESTRPIPE) return -1; } @@ -1739,11 +1752,11 @@ JackAlsaDriver::alsa_driver_delete (alsa_driver_t *driver) free (node->data); } jack_slist_free (driver->clock_sync_listeners); - + if (driver->ctl_handle) { snd_ctl_close (driver->ctl_handle); driver->ctl_handle = 0; - } + } if (driver->capture_handle) { snd_pcm_close (driver->capture_handle); @@ -1821,14 +1834,14 @@ JackAlsaDriver::alsa_driver_new (const char *name, char *playback_alsa_device, jack_info ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32 "|%" PRIu32"|%" PRIu32"|%" PRIu32 "|%s|%s|%s|%s", playing ? playback_alsa_device : "-", - capturing ? capture_alsa_device : "-", + capturing ? capture_alsa_device : "-", frames_per_cycle, user_nperiods, rate, user_capture_nchnls,user_playback_nchnls, hw_monitoring ? "hwmon": "nomon", hw_metering ? "hwmeter":"swmeter", soft_mode ? "soft-mode":"-", shorts_first ? "16bit":"32bit"); - + driver = (alsa_driver_t *) calloc (1, sizeof (alsa_driver_t)); jack_driver_nt_init ((jack_driver_nt_t *) driver); @@ -1862,8 +1875,8 @@ JackAlsaDriver::alsa_driver_new (const char *name, char *playback_alsa_device, driver->playback_addr = 0; driver->capture_addr = 0; - driver->playback_interleave_skip = NULL; - driver->capture_interleave_skip = NULL; + driver->playback_interleave_skip = NULL; + driver->capture_interleave_skip = NULL; driver->silent = 0; driver->all_monitor_in = FALSE; @@ -2071,6 +2084,7 @@ int JackAlsaDriver::Attach() unsigned long port_flags; char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + jack_latency_range_t range; assert(fCaptureChannels < DRIVER_PORT_NUM); assert(fPlaybackChannels < DRIVER_PORT_NUM); @@ -2097,7 +2111,8 @@ int JackAlsaDriver::Attach() } port = fGraphManager->GetPort(port_index); port->SetAlias(alias); - port->SetLatency(alsa_driver->frames_per_cycle + alsa_driver->capture_frame_latency); + range.min = range.max = alsa_driver->frames_per_cycle + alsa_driver->capture_frame_latency; + port->SetLatencyRange(JackCaptureLatency, &range); fCapturePortList[i] = port_index; jack_log("JackAudioDriver::Attach fCapturePortList[i] %ld ", port_index); } @@ -2114,8 +2129,10 @@ int JackAlsaDriver::Attach() port = fGraphManager->GetPort(port_index); port->SetAlias(alias); // Add one buffer more latency if "async" mode is used... - port->SetLatency((alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) + - ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + alsa_driver->playback_frame_latency); + range.min = range.max = (alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) + + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + alsa_driver->playback_frame_latency; + + port->SetLatencyRange(JackPlaybackLatency, &range); fPlaybackPortList[i] = port_index; jack_log("JackAudioDriver::Attach fPlaybackPortList[i] %ld ", port_index); @@ -2127,7 +2144,8 @@ int JackAlsaDriver::Attach() jack_error ("ALSA: cannot register monitor port for %s", name); } else { port = fGraphManager->GetPort(port_index); - port->SetLatency(alsa_driver->frames_per_cycle); + range.min = range.max = alsa_driver->frames_per_cycle; + port->SetLatencyRange(JackCaptureLatency, &range); fMonitorPortList[i] = port_index; } } @@ -2151,7 +2169,7 @@ int JackAlsaDriver::Detach() return JackAudioDriver::Detach(); } -static int card_to_num(const char* device) +static int card_to_num(const char* device) { int err; char* ctl_name; @@ -2316,13 +2334,13 @@ int JackAlsaDriver::Read() retry: nframes = alsa_driver_wait((alsa_driver_t *)fDriver, -1, &wait_status, &fDelayedUsecs); - + if (wait_status < 0) return -1; /* driver failed */ if (nframes == 0) { /* we detected an xrun and restarted: notify - * clients about the delay. + * clients about the delay. */ jack_log("ALSA XRun wait_status = %d", wait_status); NotifyXRun(fBeginDateUst, fDelayedUsecs); @@ -2331,7 +2349,7 @@ retry: if (nframes != fEngineControl->fBufferSize) jack_log("JackAlsaDriver::Read warning nframes = %ld", nframes); - + // Has to be done before read JackDriver::CycleIncTime(); @@ -2619,7 +2637,7 @@ get_dither_constraint() } static int -dither_opt (char c, DitherAlgorithm* dither) +dither_opt (char c, DitherAlgorithm* dither) { switch (c) { case '-': @@ -2646,17 +2664,17 @@ dither_opt (char c, DitherAlgorithm* dither) return 0; } -SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () +SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () { jack_driver_desc_t * desc; jack_driver_param_desc_t * params; unsigned int i; desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); - + strcpy(desc->name, "alsa"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 strcpy(desc->desc, "Linux ALSA API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 - + desc->nparams = 18; params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); @@ -2825,7 +2843,7 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () return desc; } -SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) +SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) { jack_nframes_t srate = 48000; jack_nframes_t frames_per_interrupt = 1024; diff --git a/linux/alsa/alsa_rawmidi.c b/linux/alsa/alsa_rawmidi.c index 62e18cd7..ba378c4e 100644 --- a/linux/alsa/alsa_rawmidi.c +++ b/linux/alsa/alsa_rawmidi.c @@ -104,7 +104,7 @@ typedef struct input_port_t { // jack midi_unpack_t unpack; - + // midi int overruns; } input_port_t; @@ -114,7 +114,7 @@ typedef struct output_port_t { // jack midi_pack_t packer; - + // midi event_head_t next_event; int todo; @@ -425,16 +425,16 @@ static inline int midi_port_open_jack(alsa_rawmidi_t *midi, midi_port_t *port, int type, const char *alias) { char name[128]; - + if (type & JackPortIsOutput) snprintf(name, sizeof(name) - 1, "system:midi_capture_%d", ++midi->midi_in_cnt); - else + else snprintf(name, sizeof(name) - 1, "system:midi_playback_%d", ++midi->midi_out_cnt); port->jack = jack_port_register(midi->client, name, JACK_DEFAULT_MIDI_TYPE, - type | JackPortIsPhysical | JackPortIsTerminal | JackPortIsActive, 0); - - if (port->jack) + type | JackPortIsPhysical | JackPortIsTerminal, 0); + + if (port->jack) jack_port_set_alias(port->jack, alias); return port->jack == NULL; } @@ -455,7 +455,7 @@ int midi_port_open(alsa_rawmidi_t *midi, midi_port_t *port) out = &port->rawmidi; type = JackPortIsInput; } - + if ((err = snd_rawmidi_open(in, out, port->dev, SND_RAWMIDI_NONBLOCK))<0) return err; @@ -749,7 +749,7 @@ void* scan_thread(void *arg) return NULL; } -/* +/* * ------------------------------- Input/Output ------------------------------ */ @@ -836,7 +836,7 @@ void *midi_thread(void *arg) npfds = 1; if (jack_is_realtime(midi->client)) - set_threaded_log_function(); + set_threaded_log_function(); //debug_log("midi_thread(%s): enter", str->name); @@ -978,7 +978,7 @@ int midi_update_pfds(process_midi_t *proc) return 1; } -/* +/* * ------------------------------------ Input ------------------------------ */ @@ -1083,7 +1083,7 @@ int do_midi_input(process_midi_t *proc) return 1; } -/* +/* * ------------------------------------ Output ------------------------------ */ @@ -1149,7 +1149,7 @@ int do_midi_output(process_midi_t *proc) } else debug_log("midi_out: at %ld got %d bytes for %ld", (long)proc->cur_time, (int)port->next_event.size, (long)port->next_event.time); } - + if (port->todo) debug_log("midi_out: todo = %d at %ld", (int)port->todo, (long)proc->cur_time); diff --git a/linux/alsa/alsa_seqmidi.c b/linux/alsa/alsa_seqmidi.c index 0abc52a9..c3d8239f 100644 --- a/linux/alsa/alsa_seqmidi.c +++ b/linux/alsa/alsa_seqmidi.c @@ -285,7 +285,7 @@ int alsa_seqmidi_attach(alsa_midi_t *m) self->client_id = snd_seq_client_id(self->seq); self->queue = snd_seq_alloc_queue(self->seq); - snd_seq_start_queue(self->seq, self->queue, 0); + snd_seq_start_queue(self->seq, self->queue, 0); stream_attach(self, PORT_INPUT); stream_attach(self, PORT_OUTPUT); @@ -488,14 +488,14 @@ port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const s /* mark anything that looks like a hardware port as physical&terminal */ if (snd_seq_port_info_get_type (info) & (SND_SEQ_PORT_TYPE_HARDWARE|SND_SEQ_PORT_TYPE_PORT|SND_SEQ_PORT_TYPE_SPECIFIC)) { - jack_caps |= (JackPortIsPhysical | JackPortIsTerminal | JackPortIsActive); + jack_caps |= (JackPortIsPhysical | JackPortIsTerminal); } if (jack_caps & JackPortIsOutput) snprintf(name, sizeof(name) - 1, "system:midi_capture_%d", ++self->midi_in_cnt); - else + else snprintf(name, sizeof(name) - 1, "system:midi_playback_%d", ++self->midi_out_cnt); - + port->jack_port = jack_port_register(self->jack, name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0); if (!port->jack_port) @@ -588,7 +588,7 @@ void update_ports(alsa_seqmidi_t *self) snd_seq_port_info_alloca(&info); while ((size = jack_ringbuffer_read(self->port_add, (char*)&addr, sizeof(addr)))) { - + int err; assert (size == sizeof(addr)); @@ -666,7 +666,7 @@ void set_process_info(struct process_info *info, alsa_seqmidi_t *self, int dir, info->alsa_time = alsa_time->tv_sec * NSEC_PER_SEC + alsa_time->tv_nsec; if (info->period_start + info->nframes < info->cur_frames) { - int periods_lost = (info->cur_frames - info->period_start) / info->nframes; + int periods_lost = (info->cur_frames - info->period_start) / info->nframes; info->period_start += periods_lost * info->nframes; debug_log("xrun detected: %d periods lost\n", periods_lost); } @@ -805,7 +805,7 @@ void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct proce ev.size = size; jack_ringbuffer_write(port->early_events, (char*)&ev, sizeof(ev)); jack_ringbuffer_write(port->early_events, (char*)data, size); - debug_log("postponed to next frame +%d", (int) (event_frame - info->nframes)); + debug_log("postponed to next frame +%d", (int) (event_frame - info->nframes)); return; } @@ -829,7 +829,7 @@ void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes) return; set_process_info(&info, self, PORT_INPUT, nframes); - jack_process(self, &info); + jack_process(self, &info); while ((res = snd_seq_event_input(self->seq, &event))>0) { if (event->source.client == SND_SEQ_CLIENT_SYSTEM) diff --git a/linux/alsa/usx2y.c b/linux/alsa/usx2y.c index 92236925..a6b696dd 100644 --- a/linux/alsa/usx2y.c +++ b/linux/alsa/usx2y.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2001 Paul Davis + Copyright (C) 2001 Paul Davis Copyright (C) 2005 Karsten Wiese, Rui Nuno Capela This program is free software; you can redistribute it and/or modify @@ -33,14 +33,14 @@ int dbg_offset; char dbg_buffer[8096]; #endif -static +static int usx2y_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) { return -1; } static -int usx2y_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode) +int usx2y_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode) { return -1; } @@ -52,7 +52,7 @@ usx2y_release (jack_hardware_t *hw) if (h == 0) return; - + if (h->hwdep_handle) snd_hwdep_close(h->hwdep_handle); @@ -622,7 +622,7 @@ usx2y_driver_write (alsa_driver_t* driver, jack_nframes_t nframes) offset, nframes_)) < 0) { jack_error ("ALSA/USX2Y: could not complete playback of %" PRIu32 " frames: error = %d", nframes_, err); - if (err != EPIPE && err != ESTRPIPE) + if (err != -EPIPE && err != -ESTRPIPE) return -1; } diff --git a/linux/cycles.h b/linux/cycles.h index 20477a2e..d96b7b5e 100644 --- a/linux/cycles.h +++ b/linux/cycles.h @@ -37,8 +37,6 @@ * regardless of how fast the machine is. */ -#ifdef __linux__ - #ifdef __x86_64__ typedef unsigned long cycles_t; @@ -127,21 +125,5 @@ static inline cycles_t get_cycles(void) #endif /* everything else but x86, amd64, sparcv9 or ppc */ -#endif /* __linux__ */ - - -#if defined(__FreeBSD_kernel__) - -#warning No suitable get_cycles() implementation. Returning 0 instead - -typedef unsigned long long cycles_t; - -static inline cycles_t get_cycles(void) -{ - return 0; -} - -#endif /* __FreeBSD_kernel__ */ - #endif /* __jack_cycles_h__ */ diff --git a/linux/firewire/JackFFADODriver.cpp b/linux/firewire/JackFFADODriver.cpp index 5400df76..486c3794 100644 --- a/linux/firewire/JackFFADODriver.cpp +++ b/linux/firewire/JackFFADODriver.cpp @@ -272,7 +272,7 @@ JackFFADODriver::SetBufferSize (jack_nframes_t nframes) printError("Buffer size change requested but not supported!!!"); /* - driver->period_size = nframes; + driver->period_size = nframes; driver->period_usecs = (jack_time_t) floor ((((float) nframes) / driver->sample_rate) * 1000000.0f); @@ -362,6 +362,7 @@ int JackFFADODriver::Attach() int port_index; char buf[JACK_PORT_NAME_SIZE]; char portname[JACK_PORT_NAME_SIZE]; + jack_latency_range_t range; ffado_driver_t* driver = (ffado_driver_t*)fDriver; @@ -447,7 +448,8 @@ int JackFFADODriver::Attach() ffado_streaming_capture_stream_onoff(driver->dev, chn, 0); port = fGraphManager->GetPort(port_index); - port->SetLatency(driver->period_size + driver->capture_frame_latency); + range.min = range.max = driver->period_size + driver->capture_frame_latency; + port->SetLatencyRange(JackCaptureLatency, &range); // capture port aliases (jackd1 style port names) snprintf(buf, sizeof(buf) - 1, "%s:capture_%i", fClientControl.fName, (int) chn + 1); port->SetAlias(buf); @@ -479,7 +481,8 @@ int JackFFADODriver::Attach() driver->capture_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t)); port = fGraphManager->GetPort(port_index); - port->SetLatency(driver->period_size + driver->capture_frame_latency); + range.min = range.max = driver->period_size + driver->capture_frame_latency; + port->SetLatencyRange(JackCaptureLatency, &range); fCapturePortList[chn] = port_index; jack_log("JackFFADODriver::Attach fCapturePortList[i] %ld ", port_index); fCaptureChannels++; @@ -523,7 +526,8 @@ int JackFFADODriver::Attach() port = fGraphManager->GetPort(port_index); // Add one buffer more latency if "async" mode is used... - port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency); + range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency + port->SetLatencyRange(JackPlaybackLatency, &range); // playback port aliases (jackd1 style port names) snprintf(buf, sizeof(buf) - 1, "%s:playback_%i", fClientControl.fName, (int) chn + 1); port->SetAlias(buf); @@ -549,7 +553,7 @@ int JackFFADODriver::Attach() printError(" cannot enable port %s", buf); } // setup the midi buffer - + // This constructor optionally accepts arguments for the // non-realtime buffer size and the realtime buffer size. Ideally, // these would become command-line options for the FFADO driver. @@ -558,7 +562,8 @@ int JackFFADODriver::Attach() driver->playback_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t)); port = fGraphManager->GetPort(port_index); - port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + driver->playback_frame_latency); + range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + driver->playback_frame_latency; + port->SetLatencyRange(JackPlaybackLatency, &range); fPlaybackPortList[chn] = port_index; jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index); fPlaybackChannels++; @@ -676,7 +681,7 @@ retry: if (nframes == 0) { /* we detected an xrun and restarted: notify - * clients about the delay. + * clients about the delay. */ jack_log("FFADO XRun"); NotifyXRun(fBeginDateUst, fDelayedUsecs); @@ -685,7 +690,7 @@ retry: if (nframes != fEngineControl->fBufferSize) jack_log("JackFFADODriver::Read warning nframes = %ld", nframes); - + // Has to be done before read JackDriver::CycleIncTime(); @@ -755,7 +760,7 @@ extern "C" strcpy (desc->name, "firewire"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 strcpy(desc->desc, "Linux FFADO API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 - + desc->nparams = 13; params = (jack_driver_param_desc_t *)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); diff --git a/linux/freebob/JackFreebobDriver.cpp b/linux/freebob/JackFreebobDriver.cpp index 47860f21..552e9927 100644 --- a/linux/freebob/JackFreebobDriver.cpp +++ b/linux/freebob/JackFreebobDriver.cpp @@ -260,7 +260,7 @@ JackFreebobDriver::SetBufferSize (jack_nframes_t nframes) printError("Buffer size change requested but not supported!!!"); /* - driver->period_size = nframes; + driver->period_size = nframes; driver->period_usecs = (jack_time_t) floor ((((float) nframes) / driver->sample_rate) * 1000000.0f); @@ -667,9 +667,10 @@ int JackFreebobDriver::Attach() { JackPort* port; int port_index; - + char buf[JACK_PORT_NAME_SIZE]; char portname[JACK_PORT_NAME_SIZE]; + jack_latency_range_t range; freebob_driver_t* driver = (freebob_driver_t*)fDriver; @@ -737,7 +738,8 @@ int JackFreebobDriver::Attach() return -1; } port = fGraphManager->GetPort(port_index); - port->SetLatency(driver->period_size + driver->capture_frame_latency); + range.min = range.max = driver->period_size + driver->capture_frame_latency; + port->SetLatencyRange(JackCaptureLatency, &range); fCapturePortList[i] = port_index; jack_log("JackFreebobDriver::Attach fCapturePortList[i] %ld ", port_index); driver->capture_nchannels_audio++; @@ -766,7 +768,8 @@ int JackFreebobDriver::Attach() } port = fGraphManager->GetPort(port_index); // Add one buffer more latency if "async" mode is used... - port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency); + range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency); + port->SetLatencyRange(JackPlaybackLatency, &range); fPlaybackPortList[i] = port_index; jack_log("JackFreebobDriver::Attach fPlaybackPortList[i] %ld ", port_index); driver->playback_nchannels_audio++; @@ -866,7 +869,7 @@ retry: if (nframes == 0) { /* we detected an xrun and restarted: notify - * clients about the delay. + * clients about the delay. */ jack_log("FreeBoB XRun"); NotifyXRun(fBeginDateUst, fDelayedUsecs); @@ -878,7 +881,7 @@ retry: // Has to be done before read JackDriver::CycleIncTime(); - + printExit(); return freebob_driver_read((freebob_driver_t *)fDriver, fEngineControl->fBufferSize); } @@ -944,7 +947,7 @@ extern "C" strcpy (desc->name, "freebob"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 strcpy(desc->desc, "Linux FreeBob API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 - + desc->nparams = 11; params = (jack_driver_param_desc_t *)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); diff --git a/macosx/Jack-Info.plist b/macosx/Jack-Info.plist index ef3f8b07..0d714313 100644 --- a/macosx/Jack-Info.plist +++ b/macosx/Jack-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable Jackservermp CFBundleGetInfoString - Jackdmp 1.9.7, @03-10 Paul Davis, Grame + Jackdmp 1.9.7, @03-11 Paul Davis, Grame CFBundleIdentifier com.grame.Jackmp CFBundleInfoDictionaryVersion diff --git a/macosx/JackMachThread.cpp b/macosx/JackMachThread.cpp index 0faaf941..19f99b54 100644 --- a/macosx/JackMachThread.cpp +++ b/macosx/JackMachThread.cpp @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. namespace Jack { -int JackMachThread::SetThreadToPriority(pthread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint) +int JackMachThread::SetThreadToPriority(jack_native_thread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint) { if (inPriority == 96) { // REAL-TIME / TIME-CONSTRAINT THREAD @@ -73,18 +73,18 @@ int JackMachThread::SetThreadToPriority(pthread_t thread, UInt32 inPriority, Boo } // returns the thread's priority as it was last set by the API -UInt32 JackMachThread::GetThreadSetPriority(pthread_t thread) +UInt32 JackMachThread::GetThreadSetPriority(jack_native_thread_t thread) { return GetThreadPriority(thread, THREAD_SET_PRIORITY); } // returns the thread's priority as it was last scheduled by the Kernel -UInt32 JackMachThread::GetThreadScheduledPriority(pthread_t thread) +UInt32 JackMachThread::GetThreadScheduledPriority(jack_native_thread_t thread) { return GetThreadPriority(thread, THREAD_SCHEDULED_PRIORITY); } -UInt32 JackMachThread::GetThreadPriority(pthread_t thread, int inWhichPriority) +UInt32 JackMachThread::GetThreadPriority(jack_native_thread_t thread, int inWhichPriority) { thread_basic_info_data_t threadInfo; policy_info_data_t thePolicyInfo; @@ -127,7 +127,7 @@ UInt32 JackMachThread::GetThreadPriority(pthread_t thread, int inWhichPriority) return 0; } -int JackMachThread::GetParams(pthread_t thread, UInt64* period, UInt64* computation, UInt64* constraint) +int JackMachThread::GetParams(jack_native_thread_t thread, UInt64* period, UInt64* computation, UInt64* constraint) { thread_time_constraint_policy_data_t theTCPolicy; mach_msg_type_number_t count = THREAD_TIME_CONSTRAINT_POLICY_COUNT; @@ -160,11 +160,11 @@ int JackMachThread::Kill() { // pthread_cancel still not yet implemented in Darwin (TO CHECK ON TIGER) jack_log("JackMachThread::Kill"); - - if (fThread != (pthread_t)NULL) { // If thread has been started + + if (fThread != (jack_native_thread_t)NULL) { // If thread has been started mach_port_t machThread = pthread_mach_thread_np(fThread); int res = (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1; - fThread = (pthread_t)NULL; + fThread = (jack_native_thread_t)NULL; return res; } else { return -1; @@ -175,7 +175,7 @@ int JackMachThread::AcquireRealTime() { jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld", long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); - return (fThread != (pthread_t)NULL) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1; + return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1; } int JackMachThread::AcquireSelfRealTime() @@ -197,7 +197,7 @@ int JackMachThread::AcquireSelfRealTime(int priority) return AcquireSelfRealTime(); } -int JackMachThread::AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint) +int JackMachThread::AcquireRealTimeImp(jack_native_thread_t thread, UInt64 period, UInt64 computation, UInt64 constraint) { SetThreadToPriority(thread, 96, true, period, computation, constraint); return 0; @@ -205,7 +205,7 @@ int JackMachThread::AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 c int JackMachThread::DropRealTime() { - return (fThread != (pthread_t)NULL) ? DropRealTimeImp(fThread) : -1; + return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1; } int JackMachThread::DropSelfRealTime() @@ -213,7 +213,7 @@ int JackMachThread::DropSelfRealTime() return DropRealTimeImp(pthread_self()); } -int JackMachThread::DropRealTimeImp(pthread_t thread) +int JackMachThread::DropRealTimeImp(jack_native_thread_t thread) { SetThreadToPriority(thread, 63, false, 0, 0, 0); return 0; diff --git a/macosx/JackMachThread.h b/macosx/JackMachThread.h index d25331d2..eae474f2 100644 --- a/macosx/JackMachThread.h +++ b/macosx/JackMachThread.h @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -98,9 +98,9 @@ class SERVER_EXPORT JackMachThread : public JackPosixThread UInt64 fComputation; UInt64 fConstraint; - static UInt32 GetThreadSetPriority(pthread_t thread); - static UInt32 GetThreadScheduledPriority(pthread_t thread); - static UInt32 GetThreadPriority(pthread_t thread, int inWhichPriority); + static UInt32 GetThreadSetPriority(jack_native_thread_t thread); + static UInt32 GetThreadScheduledPriority(jack_native_thread_t thread); + static UInt32 GetThreadPriority(jack_native_thread_t thread, int inWhichPriority); public: @@ -116,23 +116,23 @@ class SERVER_EXPORT JackMachThread : public JackPosixThread int AcquireRealTime(); // Used when called from another thread int AcquireSelfRealTime(); // Used when called from thread itself - + int AcquireRealTime(int priority); // Used when called from another thread int AcquireSelfRealTime(int priority); // Used when called from thread itself - + int DropRealTime(); // Used when called from another thread int DropSelfRealTime(); // Used when called from thread itself - + void SetParams(UInt64 period, UInt64 computation, UInt64 constraint); - static int GetParams(pthread_t thread, UInt64* period, UInt64* computation, UInt64* constraint); - static int SetThreadToPriority(pthread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint); + static int GetParams(jack_native_thread_t thread, UInt64* period, UInt64* computation, UInt64* constraint); + static int SetThreadToPriority(jack_native_thread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint); - static int AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint); - static int AcquireRealTimeImp(pthread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint) - { - return JackMachThread::AcquireRealTimeImp(thread, period, computation, constraint); + static int AcquireRealTimeImp(jack_native_thread_t thread, UInt64 period, UInt64 computation, UInt64 constraint); + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint) + { + return JackMachThread::AcquireRealTimeImp(thread, period, computation, constraint); } - static int DropRealTimeImp(pthread_t thread); + static int DropRealTimeImp(jack_native_thread_t thread); }; } // end of namespace diff --git a/macosx/Jackdmp.xcodeproj/project.pbxproj b/macosx/Jackdmp.xcodeproj/project.pbxproj index 8c457330..1c3370aa 100644 --- a/macosx/Jackdmp.xcodeproj/project.pbxproj +++ b/macosx/Jackdmp.xcodeproj/project.pbxproj @@ -48,6 +48,8 @@ 4BFA833C0DF6AB540087B4E1 /* PBXTargetDependency */, 4B32258F10A31AB400838A8E /* PBXTargetDependency */, 4B66550E127C356E00753A79 /* PBXTargetDependency */, + 4B38120313269CCB00C61B14 /* PBXTargetDependency */, + 4B8F16FC1329169F0002AD73 /* PBXTargetDependency */, ); name = "All Universal 32/64 bits"; productName = All; @@ -94,6 +96,8 @@ 4B363F530DEB0CFE001F72D9 /* PBXTargetDependency */, 4B363F780DEB0D85001F72D9 /* PBXTargetDependency */, 4B32258B10A31A9000838A8E /* PBXTargetDependency */, + 4B38120113269CB600C61B14 /* PBXTargetDependency */, + 4B8F16FA132916910002AD73 /* PBXTargetDependency */, ); name = "All Universal 32 bits"; productName = All; @@ -110,6 +114,18 @@ 4B19B31B0E2362E800DD4A82 /* JackLibSampleRateResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B30E0E2362E700DD4A82 /* JackLibSampleRateResampler.cpp */; }; 4B19B31C0E2362E800DD4A82 /* JackLibSampleRateResampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19B30F0E2362E700DD4A82 /* JackLibSampleRateResampler.h */; }; 4B19B31F0E2362E800DD4A82 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B3120E2362E700DD4A82 /* JackResampler.cpp */; }; + 4B2209E112F6BBF300E5DC26 /* JackSocketServerChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B30E703B8D0066E42F /* JackSocketServerChannel.cpp */; }; + 4B2209E212F6BBF400E5DC26 /* JackSocketServerChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B40E703B8D0066E42F /* JackSocketServerChannel.h */; }; + 4B2209E312F6BBF500E5DC26 /* JackSocketServerNotifyChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B50E703B8D0066E42F /* JackSocketServerNotifyChannel.cpp */; }; + 4B2209E412F6BBF600E5DC26 /* JackSocketServerNotifyChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B60E703B8D0066E42F /* JackSocketServerNotifyChannel.h */; }; + 4B2209E612F6BC0200E5DC26 /* JackSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6AD0E703B8D0066E42F /* JackSocket.cpp */; }; + 4B2209E712F6BC0300E5DC26 /* JackSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6AE0E703B8D0066E42F /* JackSocket.h */; }; + 4B2209E912F6BC1500E5DC26 /* JackSocketNotifyChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B10E703B8D0066E42F /* JackSocketNotifyChannel.cpp */; }; + 4B2209EA12F6BC1600E5DC26 /* JackSocketNotifyChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B20E703B8D0066E42F /* JackSocketNotifyChannel.h */; }; + 4B2209EC12F6BC2100E5DC26 /* JackSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6AD0E703B8D0066E42F /* JackSocket.cpp */; }; + 4B2209ED12F6BC2200E5DC26 /* JackSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6AE0E703B8D0066E42F /* JackSocket.h */; }; + 4B2209EE12F6BC2300E5DC26 /* JackSocketClientChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6AF0E703B8D0066E42F /* JackSocketClientChannel.cpp */; }; + 4B2209EF12F6BC2500E5DC26 /* JackSocketClientChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B00E703B8D0066E42F /* JackSocketClientChannel.h */; }; 4B3224EA10A315B100838A8E /* JackNetOneDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3224E810A315B100838A8E /* JackNetOneDriver.cpp */; }; 4B3224EB10A315B100838A8E /* JackNetOneDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3224E910A315B100838A8E /* JackNetOneDriver.h */; }; 4B3224F010A315C400838A8E /* netjack_packet.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3224EC10A315C400838A8E /* netjack_packet.c */; }; @@ -277,7 +293,6 @@ 4B35C53D0D4731D1000DE7AE /* connect.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B60CE480AAABA31004956AA /* connect.c */; }; 4B35C5490D4731D1000DE7AE /* connect.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B60CE480AAABA31004956AA /* connect.c */; }; 4B35C5570D4731D2000DE7AE /* freewheel.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8D1710834EE0F00C94B91 /* freewheel.c */; }; - 4B35C5630D4731D2000DE7AE /* jdelay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFA99A90AAAF40C009E916C /* jdelay.cpp */; }; 4B35C57D0D4731D2000DE7AE /* testAtomic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8D23E0834F1C300C94B91 /* testAtomic.cpp */; }; 4B35C58D0D4731D2000DE7AE /* testSem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8D2470834F20600C94B91 /* testSem.cpp */; }; 4B35C59F0D4731D2000DE7AE /* zombie.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8D1670834EDD900C94B91 /* zombie.c */; }; @@ -302,6 +317,10 @@ 4B363F230DEB0AB0001F72D9 /* monitor_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F220DEB0AB0001F72D9 /* monitor_client.c */; }; 4B363F3E0DEB0C31001F72D9 /* showtime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F3D0DEB0C31001F72D9 /* showtime.c */; }; 4B363F760DEB0D7D001F72D9 /* impulse_grabber.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F750DEB0D7D001F72D9 /* impulse_grabber.c */; }; + 4B3811FB13269C8300C61B14 /* latent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3811FA13269C8300C61B14 /* latent_client.c */; }; + 4B3811FC13269C8300C61B14 /* latent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3811FA13269C8300C61B14 /* latent_client.c */; }; + 4B3814201327AA6800C61B14 /* iodelay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B38141F1327AA6800C61B14 /* iodelay.cpp */; }; + 4B3814211327AA6800C61B14 /* iodelay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B38141F1327AA6800C61B14 /* iodelay.cpp */; }; 4B3F49080AD8503300491C6E /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3F49070AD8503300491C6E /* cpu.c */; }; 4B43A8CA1014605000E52943 /* JackLoopbackDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B43A8C81014605000E52943 /* JackLoopbackDriver.cpp */; }; 4B43A8CB1014605000E52943 /* JackLoopbackDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B43A8C91014605000E52943 /* JackLoopbackDriver.h */; }; @@ -396,6 +415,10 @@ 4B4F9C930DC20C0400706CB0 /* JackMessageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4F9C8B0DC20C0400706CB0 /* JackMessageBuffer.h */; }; 4B4F9D820DC2178E00706CB0 /* JackMessageBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4F9C8A0DC20C0400706CB0 /* JackMessageBuffer.cpp */; }; 4B4F9D830DC2178F00706CB0 /* JackMessageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4F9C8B0DC20C0400706CB0 /* JackMessageBuffer.h */; }; + 4B5160A813215E8B00BB7DCB /* systemdeps.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B94334910A5E666002A187F /* systemdeps.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B5160A913215EBF00BB7DCB /* systemdeps.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B94334910A5E666002A187F /* systemdeps.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B5160AA13215ED900BB7DCB /* systemdeps.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B94334910A5E666002A187F /* systemdeps.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B5160AE13215EF900BB7DCB /* systemdeps.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B94334910A5E666002A187F /* systemdeps.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B5A1BBE0CD1CC110005BF74 /* midiseq.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B5A1BBD0CD1CC110005BF74 /* midiseq.c */; }; 4B5A1BDD0CD1CD420005BF74 /* midisine.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B5A1BDC0CD1CD420005BF74 /* midisine.c */; }; 4B5DB9830CD2429A00EBA5EE /* JackDebugClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B98AE000931D30C0091932A /* JackDebugClient.cpp */; }; @@ -560,6 +583,8 @@ 4B8A38F1117B827E00664E07 /* JackSocketClientChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6AF0E703B8D0066E42F /* JackSocketClientChannel.cpp */; }; 4B8A38F6117B82AB00664E07 /* JackSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6AD0E703B8D0066E42F /* JackSocket.cpp */; }; 4B8A38F7117B82B200664E07 /* JackSocketClientChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B00E703B8D0066E42F /* JackSocketClientChannel.h */; }; + 4B8F16F51329161E0002AD73 /* midi_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B8F16F41329161E0002AD73 /* midi_dump.c */; }; + 4B8F16F61329161E0002AD73 /* midi_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B8F16F41329161E0002AD73 /* midi_dump.c */; }; 4B93F1990E87992100E4ECCD /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6A20E703B2E0066E42F /* JackPosixThread.cpp */; }; 4B93F19A0E87992200E4ECCD /* JackPosixThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6A30E703B2E0066E42F /* JackPosixThread.h */; }; 4B93F19C0E87998200E4ECCD /* JackPosixServerLaunch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF5FBBA0E878B9C003D2374 /* JackPosixServerLaunch.cpp */; }; @@ -819,7 +844,6 @@ 4BFA82B00DF6A9E40087B4E1 /* monitor_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F220DEB0AB0001F72D9 /* monitor_client.c */; }; 4BFA82BC0DF6A9E40087B4E1 /* showtime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F3D0DEB0C31001F72D9 /* showtime.c */; }; 4BFA82C80DF6A9E40087B4E1 /* impulse_grabber.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F750DEB0D7D001F72D9 /* impulse_grabber.c */; }; - 4BFA99AA0AAAF40C009E916C /* jdelay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFA99A90AAAF40C009E916C /* jdelay.cpp */; }; BA047C760E14E79D0041F3B6 /* JackNetSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = BA047C710E14E7540041F3B6 /* JackNetSocket.h */; }; BA222AD80DC88268001A17F4 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BA222AD60DC88268001A17F4 /* JackNetTool.cpp */; }; BA222AD90DC88269001A17F4 /* JackNetTool.h in Headers */ = {isa = PBXBuildFile; fileRef = BA222AD70DC88268001A17F4 /* JackNetTool.h */; }; @@ -1084,6 +1108,20 @@ remoteGlobalIDString = 4B363F680DEB0D4E001F72D9; remoteInfo = "jack_impulse_grabber Universal"; }; + 4B38120013269CB600C61B14 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4B3811551326878E00C61B14; + remoteInfo = "jack_latent_client Universal"; + }; + 4B38120213269CCB00C61B14 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4B38118D1326884E00C61B14; + remoteInfo = "jack_latent_client 64 bits"; + }; 4B43A8CC1014607100E52943 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; @@ -1161,6 +1199,20 @@ remoteGlobalIDString = 4B699D03097D421600A18468; remoteInfo = "jack_external_metro Universal"; }; + 4B8F16F9132916910002AD73 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4B8F16DB13290DC80002AD73; + remoteInfo = "jack_midi_dump Universal"; + }; + 4B8F16FB1329169F0002AD73 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4B8F16E813290E0E0002AD73; + remoteInfo = "jack_midi_dump 64 bits"; + }; 4BA693E80CBE5BBA00EAD520 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; @@ -1436,7 +1488,7 @@ 4B35C5440D4731D1000DE7AE /* jack_connect */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_connect; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C5500D4731D1000DE7AE /* jack_disconnect */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_disconnect; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C55E0D4731D2000DE7AE /* jack_freewheel */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_freewheel; sourceTree = BUILT_PRODUCTS_DIR; }; - 4B35C56A0D4731D2000DE7AE /* jdelay */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jdelay; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B35C56A0D4731D2000DE7AE /* jack_iodelay */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_iodelay; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C5760D4731D2000DE7AE /* jack_external_metro */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_external_metro; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C5860D4731D2000DE7AE /* testAtomic */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testAtomic; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C59A0D4731D2000DE7AE /* testSem */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testSem; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1469,6 +1521,10 @@ 4B37C20306DF1FBE0016E567 /* CALatencyLog.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CALatencyLog.cpp; path = /Developer/Examples/CoreAudio/PublicUtility/CALatencyLog.cpp; sourceTree = ""; }; 4B37C20406DF1FBE0016E567 /* CALatencyLog.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CALatencyLog.h; path = /Developer/Examples/CoreAudio/PublicUtility/CALatencyLog.h; sourceTree = ""; }; 4B37C20906DF1FE20016E567 /* latency.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = latency.c; path = /Developer/Examples/CoreAudio/PublicUtility/latency.c; sourceTree = ""; }; + 4B38115F1326878E00C61B14 /* jack_latent_client */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_latent_client; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B3811971326884E00C61B14 /* jack_latent_client */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_latent_client; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B3811FA13269C8300C61B14 /* latent_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = latent_client.c; path = "../example-clients/latent_client.c"; sourceTree = SOURCE_ROOT; }; + 4B38141F1327AA6800C61B14 /* iodelay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = iodelay.cpp; path = ../tests/iodelay.cpp; sourceTree = SOURCE_ROOT; }; 4B3F49070AD8503300491C6E /* cpu.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = cpu.c; path = ../tests/cpu.c; sourceTree = SOURCE_ROOT; }; 4B43A8BA10145F6F00E52943 /* jack_loopback.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = jack_loopback.so; sourceTree = BUILT_PRODUCTS_DIR; }; 4B43A8C81014605000E52943 /* JackLoopbackDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackLoopbackDriver.cpp; path = ../common/JackLoopbackDriver.cpp; sourceTree = SOURCE_ROOT; }; @@ -1531,6 +1587,9 @@ 4B869D7F08C9CB00001CF041 /* JackDriverLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackDriverLoader.cpp; path = ../common/JackDriverLoader.cpp; sourceTree = SOURCE_ROOT; }; 4B88D03911298BEE007A87C1 /* weakjack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = weakjack.h; path = ../common/jack/weakjack.h; sourceTree = SOURCE_ROOT; }; 4B88D03A11298BEE007A87C1 /* weakmacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = weakmacros.h; path = ../common/jack/weakmacros.h; sourceTree = SOURCE_ROOT; }; + 4B8F16E513290DC80002AD73 /* jack_midi_dump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midi_dump; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B8F16F213290E0E0002AD73 /* jack_midi_dump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midi_dump; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B8F16F41329161E0002AD73 /* midi_dump.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = midi_dump.c; path = "../example-clients/midi_dump.c"; sourceTree = SOURCE_ROOT; }; 4B940B9B06DDDE5B00D77F60 /* AudioHardware.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AudioHardware.h; path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/AudioHardware.h; sourceTree = ""; }; 4B94334910A5E666002A187F /* systemdeps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = systemdeps.h; path = ../common/jack/systemdeps.h; sourceTree = SOURCE_ROOT; }; 4B95BCAD0D913073000F7695 /* control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = control.h; path = ../common/jack/control.h; sourceTree = SOURCE_ROOT; }; @@ -1685,8 +1744,7 @@ 4BFA82B70DF6A9E40087B4E1 /* jack_monitor_client */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_monitor_client; sourceTree = BUILT_PRODUCTS_DIR; }; 4BFA82C30DF6A9E40087B4E1 /* jack_showtime */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_showtime; sourceTree = BUILT_PRODUCTS_DIR; }; 4BFA82CF0DF6A9E40087B4E1 /* jack_impulse_grabber */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_impulse_grabber; sourceTree = BUILT_PRODUCTS_DIR; }; - 4BFA99A20AAAF3B0009E916C /* jdelay */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jdelay; sourceTree = BUILT_PRODUCTS_DIR; }; - 4BFA99A90AAAF40C009E916C /* jdelay.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = jdelay.cpp; path = ../tests/jdelay.cpp; sourceTree = SOURCE_ROOT; }; + 4BFA99A20AAAF3B0009E916C /* jack_iodelay */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_iodelay; sourceTree = BUILT_PRODUCTS_DIR; }; 4BFB73F608AD291A00DB99B8 /* JackGlobals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackGlobals.h; path = ../common/JackGlobals.h; sourceTree = SOURCE_ROOT; }; 4BFB741E08AD2B9900DB99B8 /* JackMachThread.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JackMachThread.cpp; sourceTree = SOURCE_ROOT; }; 4BFB741F08AD2B9900DB99B8 /* JackMachThread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JackMachThread.h; sourceTree = SOURCE_ROOT; }; @@ -1990,6 +2048,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4B3811591326878E00C61B14 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B3811911326884E00C61B14 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B43A8B510145F6F00E52943 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2161,6 +2233,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4B8F16DF13290DC80002AD73 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B8F16EC13290E0E0002AD73 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B978DB60A31CF4A009E2DD1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2397,7 +2483,7 @@ 4B699DB0097D421700A18468 /* jack_dummy.so */, 4B978DBB0A31CF4A009E2DD1 /* jack_portaudio.so */, 4BE6C6A30A3E096F005A203A /* jack_test */, - 4BFA99A20AAAF3B0009E916C /* jdelay */, + 4BFA99A20AAAF3B0009E916C /* jack_iodelay */, 4BE99D300AD7A04800C59091 /* jack_cpu */, 4BD623F70CBCF0F000DE782F /* inprocess.so */, 4BA692B00CBE4BC700EAD520 /* jack_load */, @@ -2414,7 +2500,7 @@ 4B35C5440D4731D1000DE7AE /* jack_connect */, 4B35C5500D4731D1000DE7AE /* jack_disconnect */, 4B35C55E0D4731D2000DE7AE /* jack_freewheel */, - 4B35C56A0D4731D2000DE7AE /* jdelay */, + 4B35C56A0D4731D2000DE7AE /* jack_iodelay */, 4B35C5760D4731D2000DE7AE /* jack_external_metro */, 4B35C5860D4731D2000DE7AE /* testAtomic */, 4B35C59A0D4731D2000DE7AE /* testSem */, @@ -2468,6 +2554,10 @@ 4BA339AC10B2E36800190E3B /* Jackservermp.framework */, 4B47ACD710B5890100469C67 /* Jackmp.framework */, 4B6654F7127C34AE00753A79 /* jack_server_control */, + 4B38115F1326878E00C61B14 /* jack_latent_client */, + 4B3811971326884E00C61B14 /* jack_latent_client */, + 4B8F16E513290DC80002AD73 /* jack_midi_dump */, + 4B8F16F213290E0E0002AD73 /* jack_midi_dump */, ); name = Products; sourceTree = ""; @@ -2475,6 +2565,8 @@ 4B03383E0797E19900686131 /* Simple clients */ = { isa = PBXGroup; children = ( + 4B8F16F41329161E0002AD73 /* midi_dump.c */, + 4B3811FA13269C8300C61B14 /* latent_client.c */, 4B6654FB127C350100753A79 /* server_control.cpp */, 4B363F750DEB0D7D001F72D9 /* impulse_grabber.c */, 4B363F220DEB0AB0001F72D9 /* monitor_client.c */, @@ -2628,8 +2720,8 @@ 4B6BEB4A07A6CCDC00A5DBDA /* Tests */ = { isa = PBXGroup; children = ( + 4B38141F1327AA6800C61B14 /* iodelay.cpp */, 4B3F49070AD8503300491C6E /* cpu.c */, - 4BFA99A90AAAF40C009E916C /* jdelay.cpp */, 4BF8D23E0834F1C300C94B91 /* testAtomic.cpp */, 4BF8D2470834F20600C94B91 /* testSem.cpp */, 4BA577BC08BF8BE200F82DE1 /* testSynchroClient.cpp */, @@ -3086,6 +3178,7 @@ 4B88D04011298BEE007A87C1 /* weakmacros.h in Headers */, 4B8A38F0117B827900664E07 /* JackSocket.h in Headers */, 4B8A38F7117B82B200664E07 /* JackSocketClientChannel.h in Headers */, + 4B5160A813215E8B00BB7DCB /* systemdeps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3158,6 +3251,7 @@ 4B8A38AD117B810A00664E07 /* JackSocketNotifyChannel.h in Headers */, 4B8A38B0117B812500664E07 /* JackSocketServerChannel.h in Headers */, 4B8A38C4117B814000664E07 /* JackSocketServerNotifyChannel.h in Headers */, + 4B5160AA13215ED900BB7DCB /* systemdeps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3376,6 +3470,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4B3811561326878E00C61B14 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B38118E1326884E00C61B14 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B43A8B110145F6F00E52943 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -3438,6 +3546,7 @@ 4B47ACAB10B5890100469C67 /* JackProcessSync.h in Headers */, 4B88D04111298BEE007A87C1 /* weakjack.h in Headers */, 4B88D04211298BEE007A87C1 /* weakmacros.h in Headers */, + 4B5160A913215EBF00BB7DCB /* systemdeps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3527,6 +3636,8 @@ 4B94334A10A5E666002A187F /* systemdeps.h in Headers */, 4B88D03B11298BEE007A87C1 /* weakjack.h in Headers */, 4B88D03C11298BEE007A87C1 /* weakmacros.h in Headers */, + 4B2209ED12F6BC2200E5DC26 /* JackSocket.h in Headers */, + 4B2209EF12F6BC2500E5DC26 /* JackSocketClientChannel.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3599,6 +3710,10 @@ 4B88D03E11298BEE007A87C1 /* weakmacros.h in Headers */, 4BC2CA56113C6C940076717C /* JackNetInterface.h in Headers */, 4BC2CA58113C6C9C0076717C /* JackNetUnixSocket.h in Headers */, + 4B2209E212F6BBF400E5DC26 /* JackSocketServerChannel.h in Headers */, + 4B2209E412F6BBF600E5DC26 /* JackSocketServerNotifyChannel.h in Headers */, + 4B2209E712F6BC0300E5DC26 /* JackSocket.h in Headers */, + 4B2209EA12F6BC1600E5DC26 /* JackSocketNotifyChannel.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3702,6 +3817,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4B8F16DC13290DC80002AD73 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B8F16E913290E0E0002AD73 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B978DB20A31CF4A009E2DD1 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -3776,6 +3905,7 @@ 4B88D04611298BEE007A87C1 /* weakmacros.h in Headers */, 4BC2CA5E113C6CCA0076717C /* JackNetInterface.h in Headers */, 4BC2CA60113C6CD20076717C /* JackNetUnixSocket.h in Headers */, + 4B5160AE13215EF900BB7DCB /* systemdeps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4268,9 +4398,9 @@ productReference = 4B35C55E0D4731D2000DE7AE /* jack_freewheel */; productType = "com.apple.product-type.tool"; }; - 4B35C5600D4731D2000DE7AE /* jdelay 64 bits */ = { + 4B35C5600D4731D2000DE7AE /* jack_iodelay 64 bits */ = { isa = PBXNativeTarget; - buildConfigurationList = 4B35C5660D4731D2000DE7AE /* Build configuration list for PBXNativeTarget "jdelay 64 bits" */; + buildConfigurationList = 4B35C5660D4731D2000DE7AE /* Build configuration list for PBXNativeTarget "jack_iodelay 64 bits" */; buildPhases = ( 4B35C5610D4731D2000DE7AE /* Headers */, 4B35C5620D4731D2000DE7AE /* Sources */, @@ -4281,10 +4411,10 @@ ); dependencies = ( ); - name = "jdelay 64 bits"; + name = "jack_iodelay 64 bits"; productInstallPath = /usr/local/bin; productName = jack_lsp; - productReference = 4B35C56A0D4731D2000DE7AE /* jdelay */; + productReference = 4B35C56A0D4731D2000DE7AE /* jack_iodelay */; productType = "com.apple.product-type.tool"; }; 4B35C56C0D4731D2000DE7AE /* jack_external_metro 64 bits */ = { @@ -4697,6 +4827,44 @@ productReference = 4B363F720DEB0D4E001F72D9 /* jack_impulse_grabber */; productType = "com.apple.product-type.tool"; }; + 4B3811551326878E00C61B14 /* jack_latent_client Universal */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B38115B1326878E00C61B14 /* Build configuration list for PBXNativeTarget "jack_latent_client Universal" */; + buildPhases = ( + 4B3811561326878E00C61B14 /* Headers */, + 4B3811571326878E00C61B14 /* Sources */, + 4B3811591326878E00C61B14 /* Frameworks */, + 4B38115A1326878E00C61B14 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "jack_latent_client Universal"; + productInstallPath = /usr/local/bin; + productName = jack_metro; + productReference = 4B38115F1326878E00C61B14 /* jack_latent_client */; + productType = "com.apple.product-type.tool"; + }; + 4B38118D1326884E00C61B14 /* jack_latent_client 64 bits */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B3811931326884E00C61B14 /* Build configuration list for PBXNativeTarget "jack_latent_client 64 bits" */; + buildPhases = ( + 4B38118E1326884E00C61B14 /* Headers */, + 4B38118F1326884E00C61B14 /* Sources */, + 4B3811911326884E00C61B14 /* Frameworks */, + 4B3811921326884E00C61B14 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "jack_latent_client 64 bits"; + productInstallPath = /usr/local/bin; + productName = jack_metro; + productReference = 4B3811971326884E00C61B14 /* jack_latent_client */; + productType = "com.apple.product-type.tool"; + }; 4B43A8B010145F6F00E52943 /* jack_loopback Universal */ = { isa = PBXNativeTarget; buildConfigurationList = 4B43A8B610145F6F00E52943 /* Build configuration list for PBXNativeTarget "jack_loopback Universal" */; @@ -5144,6 +5312,44 @@ productReference = 4B699DB0097D421700A18468 /* jack_dummy.so */; productType = "com.apple.product-type.library.dynamic"; }; + 4B8F16DB13290DC80002AD73 /* jack_midi_dump Universal */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B8F16E113290DC80002AD73 /* Build configuration list for PBXNativeTarget "jack_midi_dump Universal" */; + buildPhases = ( + 4B8F16DC13290DC80002AD73 /* Headers */, + 4B8F16DD13290DC80002AD73 /* Sources */, + 4B8F16DF13290DC80002AD73 /* Frameworks */, + 4B8F16E013290DC80002AD73 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "jack_midi_dump Universal"; + productInstallPath = /usr/local/bin; + productName = jack_metro; + productReference = 4B8F16E513290DC80002AD73 /* jack_midi_dump */; + productType = "com.apple.product-type.tool"; + }; + 4B8F16E813290E0E0002AD73 /* jack_midi_dump 64 bits */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B8F16EE13290E0E0002AD73 /* Build configuration list for PBXNativeTarget "jack_midi_dump 64 bits" */; + buildPhases = ( + 4B8F16E913290E0E0002AD73 /* Headers */, + 4B8F16EA13290E0E0002AD73 /* Sources */, + 4B8F16EC13290E0E0002AD73 /* Frameworks */, + 4B8F16ED13290E0E0002AD73 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "jack_midi_dump 64 bits"; + productInstallPath = /usr/local/bin; + productName = jack_metro; + productReference = 4B8F16F213290E0E0002AD73 /* jack_midi_dump */; + productType = "com.apple.product-type.tool"; + }; 4B978DB10A31CF4A009E2DD1 /* jack_portaudio Universal */ = { isa = PBXNativeTarget; buildConfigurationList = 4B978DB70A31CF4A009E2DD1 /* Build configuration list for PBXNativeTarget "jack_portaudio Universal" */; @@ -5527,9 +5733,9 @@ productReference = 4BFA82CF0DF6A9E40087B4E1 /* jack_impulse_grabber */; productType = "com.apple.product-type.tool"; }; - 4BFA99980AAAF3B0009E916C /* jdelay Universal */ = { + 4BFA99980AAAF3B0009E916C /* jack_iodelay Universal */ = { isa = PBXNativeTarget; - buildConfigurationList = 4BFA999E0AAAF3B0009E916C /* Build configuration list for PBXNativeTarget "jdelay Universal" */; + buildConfigurationList = 4BFA999E0AAAF3B0009E916C /* Build configuration list for PBXNativeTarget "jack_iodelay Universal" */; buildPhases = ( 4BFA99990AAAF3B0009E916C /* Headers */, 4BFA999A0AAAF3B0009E916C /* Sources */, @@ -5540,10 +5746,10 @@ ); dependencies = ( ); - name = "jdelay Universal"; + name = "jack_iodelay Universal"; productInstallPath = /usr/local/bin; productName = jack_lsp; - productReference = 4BFA99A20AAAF3B0009E916C /* jdelay */; + productReference = 4BFA99A20AAAF3B0009E916C /* jack_iodelay */; productType = "com.apple.product-type.tool"; }; BA222AC50DC88132001A17F4 /* jack_net Universal */ = { @@ -5607,13 +5813,14 @@ 4B699C4C097D421600A18468 /* Jackservermp.framework Universal */, 4B5A1BB10CD1CB9E0005BF74 /* jack_midiseq Universal */, 4B5A1BD00CD1CCE10005BF74 /* jack_midisine Universal */, + 4B8F16DB13290DC80002AD73 /* jack_midi_dump Universal */, 4B363DCE0DEB02F6001F72D9 /* jack_alias Universal */, 4B699CB1097D421600A18468 /* jack_metro Universal */, 4B699CC1097D421600A18468 /* jack_lsp Universal */, 4B699CD1097D421600A18468 /* jack_connect Universal */, 4B699CE1097D421600A18468 /* jack_disconnect Universal */, 4B699CF1097D421600A18468 /* jack_freewheel Universal */, - 4BFA99980AAAF3B0009E916C /* jdelay Universal */, + 4BFA99980AAAF3B0009E916C /* jack_iodelay Universal */, 4B699D03097D421600A18468 /* jack_external_metro Universal */, 4B699D13097D421600A18468 /* testAtomic Universal */, 4B699D27097D421600A18468 /* testSem Universal */, @@ -5628,6 +5835,7 @@ 4B363E100DEB03C5001F72D9 /* jack_evmon Universal */, 4B363E440DEB0775001F72D9 /* jack_bufsize Universal */, 4B363EDF0DEB091C001F72D9 /* jack_rec Universal */, + 4B3811551326878E00C61B14 /* jack_latent_client Universal */, 4B363F140DEB0A6A001F72D9 /* jack_monitor_client Universal */, 4B363F2B0DEB0BD1001F72D9 /* jack_showtime Universal */, 4B363F680DEB0D4E001F72D9 /* jack_impulse_grabber Universal */, @@ -5653,12 +5861,13 @@ 4BA3393310B2E36800190E3B /* Jackservermp.framework 64 bits profiling */, 4B35C50A0D4731D1000DE7AE /* jack_midiseq 64 bits */, 4B35C5160D4731D1000DE7AE /* jack_midisine 64 bits */, + 4B8F16E813290E0E0002AD73 /* jack_midi_dump 64 bits */, 4B35C5220D4731D1000DE7AE /* jack_metro 64 bits */, 4B35C52E0D4731D1000DE7AE /* jack_lsp 64 bits */, 4B35C53A0D4731D1000DE7AE /* jack_connect 64 bits */, 4B35C5460D4731D1000DE7AE /* jack_disconnect 64 bits */, 4B35C5520D4731D2000DE7AE /* jack_freewheel 64 bits */, - 4B35C5600D4731D2000DE7AE /* jdelay 64 bits */, + 4B35C5600D4731D2000DE7AE /* jack_iodelay 64 bits */, 4B35C56C0D4731D2000DE7AE /* jack_external_metro 64 bits */, 4B35C5780D4731D2000DE7AE /* testAtomic 64 bits */, 4B35C5880D4731D2000DE7AE /* testSem 64 bits */, @@ -5671,6 +5880,7 @@ 4BFA82820DF6A9E40087B4E1 /* jack_evmon 64 bits */, 4BFA82950DF6A9E40087B4E1 /* jack_bufsize 64 bits */, 4BFA82A10DF6A9E40087B4E1 /* jack_rec 64 bits */, + 4B38118D1326884E00C61B14 /* jack_latent_client 64 bits */, 4BFA82AD0DF6A9E40087B4E1 /* jack_monitor_client 64 bits */, 4BFA82B90DF6A9E40087B4E1 /* jack_showtime 64 bits */, 4BFA82C50DF6A9E40087B4E1 /* jack_impulse_grabber 64 bits */, @@ -5971,6 +6181,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4B38115A1326878E00C61B14 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B3811921326884E00C61B14 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B47ACD010B5890100469C67 /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; @@ -6104,6 +6328,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4B8F16E013290DC80002AD73 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B8F16ED13290E0E0002AD73 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4BA339A510B2E36800190E3B /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; @@ -6441,7 +6679,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4B35C5630D4731D2000DE7AE /* jdelay.cpp in Sources */, + 4B3814211327AA6800C61B14 /* iodelay.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6623,6 +6861,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4B3811571326878E00C61B14 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B3811FC13269C8300C61B14 /* latent_client.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B38118F1326884E00C61B14 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B3811FB13269C8300C61B14 /* latent_client.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B43A8B310145F6F00E52943 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -6754,6 +7008,8 @@ 4BF5FBBC0E878B9C003D2374 /* JackPosixServerLaunch.cpp in Sources */, 4BF5FBCB0E878D24003D2374 /* JackMachTime.c in Sources */, 4BECB2F70F4451C10091B70A /* JackProcessSync.cpp in Sources */, + 4B2209EC12F6BC2100E5DC26 /* JackSocket.cpp in Sources */, + 4B2209EE12F6BC2300E5DC26 /* JackSocketClientChannel.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6810,6 +7066,10 @@ 4BCBCE5F10C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp in Sources */, 4BC2CA55113C6C930076717C /* JackNetInterface.cpp in Sources */, 4BC2CA57113C6C9B0076717C /* JackNetUnixSocket.cpp in Sources */, + 4B2209E112F6BBF300E5DC26 /* JackSocketServerChannel.cpp in Sources */, + 4B2209E312F6BBF500E5DC26 /* JackSocketServerNotifyChannel.cpp in Sources */, + 4B2209E612F6BC0200E5DC26 /* JackSocket.cpp in Sources */, + 4B2209E912F6BC1500E5DC26 /* JackSocketNotifyChannel.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6924,6 +7184,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4B8F16DD13290DC80002AD73 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B8F16F51329161E0002AD73 /* midi_dump.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B8F16EA13290E0E0002AD73 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B8F16F61329161E0002AD73 /* midi_dump.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B978DB40A31CF4A009E2DD1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -7154,7 +7430,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4BFA99AA0AAAF40C009E916C /* jdelay.cpp in Sources */, + 4B3814201327AA6800C61B14 /* iodelay.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7279,7 +7555,7 @@ }; 4B35C6940D4733B9000DE7AE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 4B35C5600D4731D2000DE7AE /* jdelay 64 bits */; + target = 4B35C5600D4731D2000DE7AE /* jack_iodelay 64 bits */; targetProxy = 4B35C6930D4733B9000DE7AE /* PBXContainerItemProxy */; }; 4B35C6960D4733B9000DE7AE /* PBXTargetDependency */ = { @@ -7357,6 +7633,16 @@ target = 4B363F680DEB0D4E001F72D9 /* jack_impulse_grabber Universal */; targetProxy = 4B363F770DEB0D85001F72D9 /* PBXContainerItemProxy */; }; + 4B38120113269CB600C61B14 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4B3811551326878E00C61B14 /* jack_latent_client Universal */; + targetProxy = 4B38120013269CB600C61B14 /* PBXContainerItemProxy */; + }; + 4B38120313269CCB00C61B14 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4B38118D1326884E00C61B14 /* jack_latent_client 64 bits */; + targetProxy = 4B38120213269CCB00C61B14 /* PBXContainerItemProxy */; + }; 4B43A8CD1014607100E52943 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4B43A8B010145F6F00E52943 /* jack_loopback Universal */; @@ -7412,6 +7698,16 @@ target = 4B699D03097D421600A18468 /* jack_external_metro Universal */; targetProxy = 4B699DBF097D421700A18468 /* PBXContainerItemProxy */; }; + 4B8F16FA132916910002AD73 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4B8F16DB13290DC80002AD73 /* jack_midi_dump Universal */; + targetProxy = 4B8F16F9132916910002AD73 /* PBXContainerItemProxy */; + }; + 4B8F16FC1329169F0002AD73 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4B8F16E813290E0E0002AD73 /* jack_midi_dump 64 bits */; + targetProxy = 4B8F16FB1329169F0002AD73 /* PBXContainerItemProxy */; + }; 4BA693E90CBE5BBA00EAD520 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4BA692A60CBE4BC700EAD520 /* jack_load Universal */; @@ -7534,7 +7830,7 @@ }; 4BFA99AC0AAAF41D009E916C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 4BFA99980AAAF3B0009E916C /* jdelay Universal */; + target = 4BFA99980AAAF3B0009E916C /* jack_iodelay Universal */; targetProxy = 4BFA99AB0AAAF41D009E916C /* PBXContainerItemProxy */; }; BA222AF00DC883EF001A17F4 /* PBXTargetDependency */ = { @@ -7744,6 +8040,7 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ""; HEADER_SEARCH_PATHS = ( + /opt/local/include, ., ../posix, ../common/jack, @@ -7767,7 +8064,7 @@ ); OTHER_REZFLAGS = ""; PREBINDING = NO; - PRODUCT_NAME = netmanager; + PRODUCT_NAME = audioadapter; SDKROOT = ""; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( @@ -7793,6 +8090,7 @@ GCC_MODEL_TUNING = G4; GCC_PREPROCESSOR_DEFINITIONS = ""; HEADER_SEARCH_PATHS = ( + /opt/local/include, ., ../posix, ../common/jack, @@ -9613,7 +9911,7 @@ Jackmp, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jdelay; + PRODUCT_NAME = jack_iodelay; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -9642,7 +9940,7 @@ Jackmp, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jdelay; + PRODUCT_NAME = jack_iodelay; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -11442,7 +11740,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_alias; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -11539,7 +11837,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_evmon; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -11636,7 +11934,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_bufsize; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -11738,7 +12036,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_rec; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -11840,7 +12138,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_monitor_client; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -12034,7 +12332,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_impulse_grabber; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -12109,7 +12407,7 @@ }; name = Default; }; - 4B43A8B710145F6F00E52943 /* Development */ = { + 4B38115C1326878E00C61B14 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( @@ -12117,39 +12415,23 @@ ppc, ); COPY_PHASE_STRIP = NO; - DEBUGGING_SYMBOLS = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - EXECUTABLE_EXTENSION = so; + FRAMEWORK_SEARCH_PATHS = ""; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - GCC_MODEL_TUNING = G4; GCC_OPTIMIZATION_LEVEL = 0; - HEADER_SEARCH_PATHS = ( - ../common, - ../common/jack, - ., - ../posix, - ); - INSTALL_PATH = /usr/local/lib; - LIBRARY_STYLE = DYNAMIC; - MACH_O_TYPE = mh_dylib; + HEADER_SEARCH_PATHS = ../common; + LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = ""; - OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; OTHER_LDFLAGS = ( "-framework", - Jackservermp, - "-framework", - CoreAudio, - "-framework", - CoreServices, + Jackmp, "-framework", - AudioUnit, + CoreFoundation, ); OTHER_REZFLAGS = ""; - PREBINDING = NO; - PRODUCT_NAME = jack_dummy; + PRODUCT_NAME = jack_latent_client; + REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( @@ -12161,7 +12443,7 @@ }; name = Development; }; - 4B43A8B810145F6F00E52943 /* Deployment */ = { + 4B38115D1326878E00C61B14 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( @@ -12169,33 +12451,21 @@ ppc, ); COPY_PHASE_STRIP = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - EXECUTABLE_EXTENSION = so; + FRAMEWORK_SEARCH_PATHS = ""; GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_MODEL_TUNING = G4; - HEADER_SEARCH_PATHS = ( - ../common, - ../common/jack, - ., - ../posix, - ); - INSTALL_PATH = /usr/local/lib; - LIBRARY_STYLE = DYNAMIC; - MACH_O_TYPE = mh_dylib; + HEADER_SEARCH_PATHS = ../common; + LIBRARY_SEARCH_PATHS = ""; MACOSX_DEPLOYMENT_TARGET = 10.4; OTHER_CFLAGS = ""; - OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; OTHER_LDFLAGS = ( "-framework", - Jackservermp, + Jackmp, "-framework", - CoreServices, + CoreFoundation, ); OTHER_REZFLAGS = ""; - PREBINDING = NO; - PRODUCT_NAME = jack_loopback; + PRODUCT_NAME = jack_latent_client; + REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( @@ -12207,32 +12477,252 @@ }; name = Deployment; }; - 4B43A8B910145F6F00E52943 /* Default */ = { + 4B38115E1326878E00C61B14 /* Default */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( i386, ppc, ); - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - EXECUTABLE_EXTENSION = so; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_MODEL_TUNING = G4; - INSTALL_PATH = /usr/local/lib; - LIBRARY_STYLE = DYNAMIC; - MACH_O_TYPE = mh_dylib; + FRAMEWORK_SEARCH_PATHS = ""; + HEADER_SEARCH_PATHS = ../common; OTHER_CFLAGS = ""; - OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; OTHER_LDFLAGS = ( "-framework", - Jackdmp, - "-framework", - AudioToolBox, - "-framework", - CoreAudio, - "-framework", - CoreServices, + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_midiseq; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; + 4B3811941326884E00C61B14 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_latent_client; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + 4B3811951326884E00C61B14 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + HEADER_SEARCH_PATHS = ../common; + MACOSX_DEPLOYMENT_TARGET = 10.4; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_latent_client; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + 4B3811961326884E00C61B14 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + FRAMEWORK_SEARCH_PATHS = ""; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_midiseq; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; + 4B43A8B710145F6F00E52943 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + COPY_PHASE_STRIP = NO; + DEBUGGING_SYMBOLS = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + EXECUTABLE_EXTENSION = so; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G4; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ( + ../common, + ../common/jack, + ., + ../posix, + ); + INSTALL_PATH = /usr/local/lib; + LIBRARY_STYLE = DYNAMIC; + MACH_O_TYPE = mh_dylib; + OTHER_CFLAGS = ""; + OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; + OTHER_LDFLAGS = ( + "-framework", + Jackservermp, + "-framework", + CoreAudio, + "-framework", + CoreServices, + "-framework", + AudioUnit, + ); + OTHER_REZFLAGS = ""; + PREBINDING = NO; + PRODUCT_NAME = jack_loopback; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + 4B43A8B810145F6F00E52943 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + COPY_PHASE_STRIP = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + EXECUTABLE_EXTENSION = so; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G4; + HEADER_SEARCH_PATHS = ( + ../common, + ../common/jack, + ., + ../posix, + ); + INSTALL_PATH = /usr/local/lib; + LIBRARY_STYLE = DYNAMIC; + MACH_O_TYPE = mh_dylib; + MACOSX_DEPLOYMENT_TARGET = 10.4; + OTHER_CFLAGS = ""; + OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; + OTHER_LDFLAGS = ( + "-framework", + Jackservermp, + "-framework", + CoreServices, + ); + OTHER_REZFLAGS = ""; + PREBINDING = NO; + PRODUCT_NAME = jack_loopback; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + 4B43A8B910145F6F00E52943 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + EXECUTABLE_EXTENSION = so; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G4; + INSTALL_PATH = /usr/local/lib; + LIBRARY_STYLE = DYNAMIC; + MACH_O_TYPE = mh_dylib; + OTHER_CFLAGS = ""; + OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; + OTHER_LDFLAGS = ( + "-framework", + Jackdmp, + "-framework", + AudioToolBox, + "-framework", + CoreAudio, + "-framework", + CoreServices, "-framework", AudioUnit, ); @@ -12287,7 +12777,7 @@ ); OTHER_REZFLAGS = ""; PREBINDING = NO; - PRODUCT_NAME = jack_dummy; + PRODUCT_NAME = jack_loopback; SDKROOT = ""; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( @@ -12792,6 +13282,7 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ""; HEADER_SEARCH_PATHS = ( + /opt/local/include, ., ../posix, ../common/jack, @@ -12815,7 +13306,7 @@ ); OTHER_REZFLAGS = ""; PREBINDING = NO; - PRODUCT_NAME = netmanager; + PRODUCT_NAME = netadapter; SDKROOT = ""; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( @@ -12841,6 +13332,7 @@ GCC_MODEL_TUNING = G4; GCC_PREPROCESSOR_DEFINITIONS = ""; HEADER_SEARCH_PATHS = ( + /opt/local/include, ., ../posix, ../common, @@ -12938,7 +13430,7 @@ Jackservermp, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_test; + PRODUCT_NAME = jack_server_control; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -15173,6 +15665,198 @@ }; name = Default; }; + 4B8F16E213290DC80002AD73 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_midi_dump; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + 4B8F16E313290DC80002AD73 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + HEADER_SEARCH_PATHS = ../common; + MACOSX_DEPLOYMENT_TARGET = 10.4; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_midi_dump; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + 4B8F16E413290DC80002AD73 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + FRAMEWORK_SEARCH_PATHS = ""; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_midisine; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; + 4B8F16EF13290E0E0002AD73 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_midi_dump; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + 4B8F16F013290E0E0002AD73 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + HEADER_SEARCH_PATHS = ../common; + MACOSX_DEPLOYMENT_TARGET = 10.4; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_midi_dump; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + 4B8F16F113290E0E0002AD73 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc64, + ppc, + i386, + x86_64, + ); + FRAMEWORK_SEARCH_PATHS = ""; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + "-framework", + CoreFoundation, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_midisine; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; 4B978DB80A31CF4A009E2DD1 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { @@ -15716,7 +16400,7 @@ Jackmp, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_lsp; + PRODUCT_NAME = jack_server_control; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -16375,6 +17059,7 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ""; HEADER_SEARCH_PATHS = ( + /opt/local/include, ., ../posix, ../common/jack, @@ -16398,7 +17083,7 @@ ); OTHER_REZFLAGS = ""; PREBINDING = NO; - PRODUCT_NAME = netmanager; + PRODUCT_NAME = audioadapter; SDKROOT = ""; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( @@ -16423,6 +17108,7 @@ GCC_MODEL_TUNING = G4; GCC_PREPROCESSOR_DEFINITIONS = ""; HEADER_SEARCH_PATHS = ( + /opt/local/include, ., ../posix, ../common/jack, @@ -16522,6 +17208,7 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ""; HEADER_SEARCH_PATHS = ( + /opt/local/include, ., ../posix, ../common/jack, @@ -16545,7 +17232,7 @@ ); OTHER_REZFLAGS = ""; PREBINDING = NO; - PRODUCT_NAME = netmanager; + PRODUCT_NAME = netadapter; SDKROOT = ""; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( @@ -16570,6 +17257,7 @@ GCC_MODEL_TUNING = G4; GCC_PREPROCESSOR_DEFINITIONS = ""; HEADER_SEARCH_PATHS = ( + /opt/local/include, ., ../posix, ../common, @@ -17117,7 +17805,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_evmon; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -17212,7 +17900,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_bufsize; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -17310,7 +17998,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_rec; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -17408,7 +18096,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_monitor_client; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -17594,7 +18282,7 @@ CoreFoundation, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jack_midiseq; + PRODUCT_NAME = jack_impulse_grabber; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -17687,7 +18375,7 @@ Jackmp, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jdelay; + PRODUCT_NAME = jack_iodelay; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -17718,7 +18406,7 @@ Jackmp, ); OTHER_REZFLAGS = ""; - PRODUCT_NAME = jdelay; + PRODUCT_NAME = jack_iodelay; REZ_EXECUTABLE = YES; SDKROOT = ""; SECTORDER_FLAGS = ""; @@ -18219,7 +18907,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; - 4B35C5660D4731D2000DE7AE /* Build configuration list for PBXNativeTarget "jdelay 64 bits" */ = { + 4B35C5660D4731D2000DE7AE /* Build configuration list for PBXNativeTarget "jack_iodelay 64 bits" */ = { isa = XCConfigurationList; buildConfigurations = ( 4B35C5670D4731D2000DE7AE /* Development */, @@ -18459,6 +19147,26 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; + 4B38115B1326878E00C61B14 /* Build configuration list for PBXNativeTarget "jack_latent_client Universal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B38115C1326878E00C61B14 /* Development */, + 4B38115D1326878E00C61B14 /* Deployment */, + 4B38115E1326878E00C61B14 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 4B3811931326884E00C61B14 /* Build configuration list for PBXNativeTarget "jack_latent_client 64 bits" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B3811941326884E00C61B14 /* Development */, + 4B3811951326884E00C61B14 /* Deployment */, + 4B3811961326884E00C61B14 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; 4B43A8B610145F6F00E52943 /* Build configuration list for PBXNativeTarget "jack_loopback Universal" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -18719,6 +19427,26 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; + 4B8F16E113290DC80002AD73 /* Build configuration list for PBXNativeTarget "jack_midi_dump Universal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B8F16E213290DC80002AD73 /* Development */, + 4B8F16E313290DC80002AD73 /* Deployment */, + 4B8F16E413290DC80002AD73 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 4B8F16EE13290E0E0002AD73 /* Build configuration list for PBXNativeTarget "jack_midi_dump 64 bits" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B8F16EF13290E0E0002AD73 /* Development */, + 4B8F16F013290E0E0002AD73 /* Deployment */, + 4B8F16F113290E0E0002AD73 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; 4B978DB70A31CF4A009E2DD1 /* Build configuration list for PBXNativeTarget "jack_portaudio Universal" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -18929,7 +19657,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; - 4BFA999E0AAAF3B0009E916C /* Build configuration list for PBXNativeTarget "jdelay Universal" */ = { + 4BFA999E0AAAF3B0009E916C /* Build configuration list for PBXNativeTarget "jack_iodelay Universal" */ = { isa = XCConfigurationList; buildConfigurations = ( 4BFA999F0AAAF3B0009E916C /* Development */, diff --git a/macosx/coreaudio/JackCoreAudioAdapter.cpp b/macosx/coreaudio/JackCoreAudioAdapter.cpp index 8e25b58d..d7e5edea 100644 --- a/macosx/coreaudio/JackCoreAudioAdapter.cpp +++ b/macosx/coreaudio/JackCoreAudioAdapter.cpp @@ -184,9 +184,9 @@ OSStatus JackCoreAudioAdapter::DeviceNotificationCallback(AudioDeviceID inDevice AudioDevicePropertyID inPropertyID, void* inClientData) { - + switch (inPropertyID) { - + case kAudioDeviceProcessorOverload: { jack_error("JackCoreAudioAdapter::DeviceNotificationCallback kAudioDeviceProcessorOverload"); break; @@ -196,12 +196,12 @@ OSStatus JackCoreAudioAdapter::DeviceNotificationCallback(AudioDeviceID inDevice jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration"); return kAudioHardwareUnsupportedOperationError; } - + case kAudioDevicePropertyNominalSampleRate: { jack_error("Cannot handle kAudioDevicePropertyNominalSampleRate"); return kAudioHardwareUnsupportedOperationError; } - + } return noErr; } @@ -217,7 +217,7 @@ int JackCoreAudioAdapter::AddListeners() printError(err); return -1; } - + err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this); if (err != noErr) { jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices"); @@ -275,17 +275,17 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon, { JackCoreAudioAdapter* adapter = static_cast(inRefCon); AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); - + float* inputBuffer[adapter->fCaptureChannels]; float* outputBuffer[adapter->fPlaybackChannels]; - + for (int i = 0; i < adapter->fCaptureChannels; i++) { inputBuffer[i] = (float*)adapter->fInputData->mBuffers[i].mData; } for (int i = 0; i < adapter->fPlaybackChannels; i++) { outputBuffer[i] = (float*)ioData->mBuffers[i].mData; } - + adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, inNumberFrames); return noErr; } @@ -302,16 +302,16 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra fCaptureUID[0] = 0; fPlaybackUID[0] = 0; fClockDriftCompensate = false; - + // Default values fCaptureChannels = -1; fPlaybackChannels = -1; - + SInt32 major; SInt32 minor; Gestalt(gestaltSystemVersionMajor, &major); Gestalt(gestaltSystemVersionMinor, &minor); - + // Starting with 10.6 systems, the HAL notification thread is created internally if (major == 10 && minor >= 6) { CFRunLoopRef theRunLoop = NULL; @@ -321,7 +321,7 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra jack_error("JackCoreAudioAdapter::Open kAudioHardwarePropertyRunLoop error"); } } - + for (node = params; node; node = jack_slist_next(node)) { param = (const jack_driver_param_t*) node->data; @@ -348,7 +348,7 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra fPlaying = true; strncpy(fPlaybackUID, param->value.str, 256); break; - + case 'd': strncpy(fCaptureUID, param->value.str, 256); strncpy(fPlaybackUID, param->value.str, 256); @@ -365,51 +365,51 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra case 'p': SetAdaptedBufferSize(param->value.ui); break; - + case 'l': DisplayDeviceNames(); break; - + case 'q': fQuality = param->value.ui; break; - + case 'g': fRingbufferCurSize = param->value.ui; fAdaptative = false; break; - + case 's': fClockDriftCompensate = true; break; } } - + /* duplex is the default */ if (!fCapturing && !fPlaying) { fCapturing = true; fPlaying = true; } - + if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0) throw -1; - + if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0) throw -1; - + if (SetupBufferSize(fAdaptedBufferSize) < 0) throw -1; - + if (SetupSampleRate(fAdaptedSampleRate) < 0) throw -1; - - if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) + + if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) throw -1; - + if (fCapturing && fCaptureChannels > 0) if (SetupBuffers(fCaptureChannels) < 0) throw -1; - + if (AddListeners() < 0) throw -1; } @@ -488,6 +488,10 @@ OSStatus JackCoreAudioAdapter::GetDefaultInputDevice(AudioDeviceID* id) if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) return res; + if (inDefault == 0) { + jack_error("Error : input device is 0, please select a correct one !!"); + return -1; + } jack_log("GetDefaultInputDevice: input = %ld ", inDefault); *id = inDefault; return noErr; @@ -502,6 +506,10 @@ OSStatus JackCoreAudioAdapter::GetDefaultOutputDevice(AudioDeviceID* id) if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) return res; + if (outDefault == 0) { + jack_error("Error : output device is 0, please select a correct one !!"); + return -1; + } jack_log("GetDefaultOutputDevice: output = %ld", outDefault); *id = outDefault; return noErr; @@ -525,10 +533,10 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, // Duplex if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) { - + // Same device for capture and playback... if (strcmp(capture_driver_uid, playback_driver_uid) == 0) { - + if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) { jack_log("Will take default in/out"); if (GetDefaultDevice(&fDeviceID) != noErr) { @@ -540,12 +548,12 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, jack_error("Cannot get device name from device ID"); return -1; } - + } else { - + // Creates aggregate device AudioDeviceID captureID, playbackID; - + if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { jack_log("Will take default input"); if (GetDefaultInputDevice(&captureID) != noErr) { @@ -553,7 +561,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, return -1; } } - + if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) { jack_log("Will take default output"); if (GetDefaultOutputDevice(&playbackID) != noErr) { @@ -561,7 +569,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, return -1; } } - + if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) return -1; } @@ -599,10 +607,10 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, jack_log("JackCoreAudioDriver::Open default driver"); if (GetDefaultDevice(&fDeviceID) != noErr) { jack_error("Cannot open default device in duplex mode, so aggregate default input and default output"); - + // Creates aggregate device AudioDeviceID captureID, playbackID; - + if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { jack_log("Will take default input"); if (GetDefaultInputDevice(&captureID) != noErr) { @@ -610,7 +618,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, return -1; } } - + if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) { jack_log("Will take default output"); if (GetDefaultOutputDevice(&playbackID) != noErr) { @@ -618,7 +626,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, return -1; } } - + if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) return -1; } @@ -680,7 +688,7 @@ int JackCoreAudioAdapter::SetupChannels(bool capturing, jack_log("Setup max out channels = %ld", out_nChannels); outchannels = out_nChannels; } - + return 0; } @@ -694,7 +702,7 @@ int JackCoreAudioAdapter::SetupBufferSize(jack_nframes_t buffer_size) printError(err); return -1; } - + return 0; } @@ -708,7 +716,7 @@ int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframe OSStatus err = noErr; UInt32 outSize; Float64 sampleRate; - + // Get sample rate outSize = sizeof(Float64); err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); @@ -716,12 +724,14 @@ int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframe jack_error("Cannot get current sample rate"); printError(err); return -1; + } else { + jack_log("Current sample rate = %f", sampleRate); } - + // If needed, set new sample rate if (samplerate != (jack_nframes_t)sampleRate) { sampleRate = (Float64)samplerate; - + // To get SR change notification err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this); if (err != noErr) { @@ -735,18 +745,18 @@ int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframe printError(err); return -1; } - + // Waiting for SR change notification int count = 0; while (!fState && count++ < WAIT_COUNTER) { usleep(100000); jack_log("Wait count = %d", count); } - + // Remove SR change notification AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback); } - + return 0; } @@ -796,7 +806,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, jack_error("No input and output channels..."); return -1; } - + // AUHAL ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; Component HALOutput = FindNextComponent(NULL, &cd); @@ -823,7 +833,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, enableIO = 0; jack_log("Setup AUHAL input off"); } - + err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input"); @@ -838,14 +848,14 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, enableIO = 0; jack_log("Setup AUHAL output off"); } - + err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output"); printError(err1); goto error; } - + size = sizeof(AudioDeviceID); err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size); if (err1 != noErr) { @@ -863,7 +873,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, printError(err1); goto error; } - + // Set buffer size if (capturing && inchannels > 0) { err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32)); @@ -918,7 +928,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, // Setup stream converters if (capturing && inchannels > 0) { - + size = sizeof(AudioStreamBasicDescription); err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &srcFormat, &size); if (err1 != noErr) { @@ -927,7 +937,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, goto error; } PrintStreamDesc(&srcFormat); - + jack_log("Setup AUHAL input stream converter SR = %ld", samplerate); srcFormat.mSampleRate = samplerate; srcFormat.mFormatID = kAudioFormatLinearPCM; @@ -938,9 +948,9 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, srcFormat.mChannelsPerFrame = inchannels; srcFormat.mBitsPerChannel = 32; PrintStreamDesc(&srcFormat); - + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); - + if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); printError(err1); @@ -949,7 +959,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, } if (playing && outchannels > 0) { - + size = sizeof(AudioStreamBasicDescription); err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &dstFormat, &size); if (err1 != noErr) { @@ -958,7 +968,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, goto error; } PrintStreamDesc(&dstFormat); - + jack_log("Setup AUHAL output stream converter SR = %ld", samplerate); dstFormat.mSampleRate = samplerate; dstFormat.mFormatID = kAudioFormatLinearPCM; @@ -969,9 +979,9 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, dstFormat.mChannelsPerFrame = outchannels; dstFormat.mBitsPerChannel = 32; PrintStreamDesc(&dstFormat); - + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); - + if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); printError(err1); @@ -1003,13 +1013,13 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, } return 0; - + error: CloseAUHAL(); return -1; } -OSStatus JackCoreAudioAdapter::DestroyAggregateDevice() +OSStatus JackCoreAudioAdapter::DestroyAggregateDevice() { OSStatus osErr = noErr; AudioObjectPropertyAddress pluginAOPA; @@ -1017,21 +1027,21 @@ OSStatus JackCoreAudioAdapter::DestroyAggregateDevice() pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; pluginAOPA.mElement = kAudioObjectPropertyElementMaster; UInt32 outDataSize; - + osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); if (osErr != noErr) { jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error"); printError(osErr); return osErr; } - + osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID); if (osErr != noErr) { jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error"); printError(osErr); return osErr; } - + return noErr; } @@ -1043,15 +1053,15 @@ static CFStringRef GetDeviceName(AudioDeviceID id) return (err == noErr) ? UIname : NULL; } -OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) +OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) { OSStatus err = noErr; AudioObjectID sub_device[32]; UInt32 outSize = sizeof(sub_device); - + err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); vector captureDeviceIDArray; - + if (err != noErr) { jack_log("Input device does not have subdevices"); captureDeviceIDArray.push_back(captureDeviceID); @@ -1062,10 +1072,10 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDevice captureDeviceIDArray.push_back(sub_device[i]); } } - - err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); + + err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); vector playbackDeviceIDArray; - + if (err != noErr) { jack_log("Output device does not have subdevices"); playbackDeviceIDArray.push_back(playbackDeviceID); @@ -1076,16 +1086,16 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDevice playbackDeviceIDArray.push_back(sub_device[i]); } } - + return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice); } - -OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector captureDeviceID, vector playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) + +OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector captureDeviceID, vector playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) { OSStatus osErr = noErr; UInt32 outSize; Boolean outWritable; - + // Prepare sub-devices for clock drift compensation // Workaround for bug in the HAL : until 10.6.2 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; @@ -1094,7 +1104,7 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca AudioClassID inClass = kAudioSubDeviceClassID; void* theQualifierData = &inClass; UInt32 subDevicesNum = 0; - + //--------------------------------------------------------------------------- // Setup SR of both devices otherwise creating AD may fail... //--------------------------------------------------------------------------- @@ -1102,18 +1112,18 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca UInt32 clockdomain = 0; outSize = sizeof(UInt32); bool need_clock_drift_compensation = false; - + for (UInt32 i = 0; i < captureDeviceID.size(); i++) { if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device"); } else { // Check clock domain - osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); + osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); if (osErr != 0) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error"); printError(osErr); } else { - keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; + keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain); if (clockdomain != 0 && clockdomain != keptclockdomain) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed..."); @@ -1122,18 +1132,18 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca } } } - + for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device"); } else { // Check clock domain - osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); + osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); if (osErr != 0) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error"); printError(osErr); } else { - keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; + keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain); if (clockdomain != 0 && clockdomain != keptclockdomain) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed..."); @@ -1142,74 +1152,74 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca } } } - + // If no valid clock domain was found, then assume we have to compensate... if (keptclockdomain == 0) { need_clock_drift_compensation = true; } - + //--------------------------------------------------------------------------- // Start to create a new aggregate by getting the base audio hardware plugin //--------------------------------------------------------------------------- - + char device_name[256]; for (UInt32 i = 0; i < captureDeviceID.size(); i++) { GetDeviceNameFromID(captureDeviceID[i], device_name); jack_info("Separated input = '%s' ", device_name); } - + for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { GetDeviceNameFromID(playbackDeviceID[i], device_name); jack_info("Separated output = '%s' ", device_name); } - + osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error"); printError(osErr); return osErr; } - + AudioValueTranslation pluginAVT; - + CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio"); - + pluginAVT.mInputData = &inBundleRef; pluginAVT.mInputDataSize = sizeof(inBundleRef); pluginAVT.mOutputData = &fPluginID; pluginAVT.mOutputDataSize = sizeof(fPluginID); - + osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error"); printError(osErr); return osErr; } - + //------------------------------------------------- // Create a CFDictionary for our aggregate device //------------------------------------------------- - + CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - + CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex"); CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex"); - + // add the name of the device to the dictionary CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef); - + // add our choice of UID for the aggregate device to the dictionary CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef); - + // add a "private aggregate key" to the dictionary int value = 1; CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value); - + SInt32 system; Gestalt(gestaltSystemVersion, &system); - + jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054); - + // Starting with 10.5.4 systems, the AD can be internal... (better) if (system < 0x00001054) { jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device...."); @@ -1217,16 +1227,16 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device...."); CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef); } - + // Prepare sub-devices for clock drift compensation CFMutableArrayRef subDevicesArrayClock = NULL; - + /* if (fClockDriftCompensate) { if (need_clock_drift_compensation) { jack_info("Clock drift compensation activated..."); subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - + for (UInt32 i = 0; i < captureDeviceID.size(); i++) { CFStringRef UID = GetDeviceName(captureDeviceID[i]); if (UID) { @@ -1237,7 +1247,7 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); } } - + for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { CFStringRef UID = GetDeviceName(playbackDeviceID[i]); if (UID) { @@ -1248,7 +1258,7 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); } } - + // add sub-device clock array for the aggregate device to the dictionary CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock); } else { @@ -1256,14 +1266,14 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca } } */ - + //------------------------------------------------- // Create a CFMutableArray for our sub-device list //------------------------------------------------- - + // we need to append the UID for each device to a CFMutableArray, so create one here CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - + vector captureDeviceUID; for (UInt32 i = 0; i < captureDeviceID.size(); i++) { CFStringRef ref = GetDeviceName(captureDeviceID[i]); @@ -1273,7 +1283,7 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca // input sub-devices in this example, so append the sub-device's UID to the CFArray CFArrayAppendValue(subDevicesArray, ref); } - + vector playbackDeviceUID; for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { CFStringRef ref = GetDeviceName(playbackDeviceID[i]); @@ -1283,39 +1293,39 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca // output sub-devices in this example, so append the sub-device's UID to the CFArray CFArrayAppendValue(subDevicesArray, ref); } - + //----------------------------------------------------------------------- // Feed the dictionary to the plugin, to create a blank aggregate device //----------------------------------------------------------------------- - + AudioObjectPropertyAddress pluginAOPA; pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice; pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; pluginAOPA.mElement = kAudioObjectPropertyElementMaster; UInt32 outDataSize; - + osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error"); printError(osErr); goto error; } - + osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error"); printError(osErr); goto error; } - + // pause for a bit to make sure that everything completed correctly // this is to work around a bug in the HAL where a new aggregate device seems to disappear briefly after it is created CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - + //------------------------- // Set the sub-device list //------------------------- - + pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList; pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; pluginAOPA.mElement = kAudioObjectPropertyElementMaster; @@ -1326,14 +1336,14 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca printError(osErr); goto error; } - + // pause again to give the changes time to take effect CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - + //----------------------- // Set the master device //----------------------- - + // set the master device manually (this is the device which will act as the master clock for the aggregate device) // pass in the UID of the device you want to use pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice; @@ -1346,36 +1356,36 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca printError(osErr); goto error; } - + // pause again to give the changes time to take effect CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - + // Prepare sub-devices for clock drift compensation // Workaround for bug in the HAL : until 10.6.2 - + if (fClockDriftCompensate) { if (need_clock_drift_compensation) { jack_info("Clock drift compensation activated..."); - + // Get the property data size osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error"); printError(osErr); } - + // Calculate the number of object IDs subDevicesNum = outSize / sizeof(AudioObjectID); jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum); AudioObjectID subDevices[subDevicesNum]; outSize = sizeof(subDevices); - + osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error"); printError(osErr); } - + // Set kAudioSubDevicePropertyDriftCompensation property... for (UInt32 index = 0; index < subDevicesNum; ++index) { UInt32 theDriftCompensationValue = 1; @@ -1388,50 +1398,50 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector ca } else { jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)"); } - } - + } + // pause again to give the changes time to take effect CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - + //---------- // Clean up //---------- - + // release the private AD key CFRelease(AggregateDeviceNumberRef); - + // release the CF objects we have created - we don't need them any more CFRelease(aggDeviceDict); CFRelease(subDevicesArray); - + if (subDevicesArrayClock) CFRelease(subDevicesArrayClock); - + // release the device UID for (UInt32 i = 0; i < captureDeviceUID.size(); i++) { CFRelease(captureDeviceUID[i]); } - + for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) { CFRelease(playbackDeviceUID[i]); } - + jack_log("New aggregate device %ld", *outAggregateDevice); return noErr; - + error: DestroyAggregateDevice(); return -1; } - - + + bool JackCoreAudioAdapter::IsAggregateDevice(AudioDeviceID device) { OSStatus err = noErr; AudioObjectID sub_device[32]; UInt32 outSize = sizeof(sub_device); err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); - + if (err != noErr) { jack_log("Device does not have subdevices"); return false; @@ -1494,7 +1504,7 @@ extern "C" strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 - + desc->nparams = 13; desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); @@ -1574,7 +1584,7 @@ extern "C" desc->params[i].value.i = TRUE; strcpy(desc->params[i].short_desc, "Display available CoreAudio devices"); strcpy(desc->params[i].long_desc, desc->params[i].short_desc); - + i++; strcpy(desc->params[i].name, "quality"); desc->params[i].character = 'q'; @@ -1582,7 +1592,7 @@ extern "C" desc->params[i].value.ui = 0; strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); strcpy(desc->params[i].long_desc, desc->params[i].short_desc); - + i++; strcpy(desc->params[i].name, "ring-buffer"); desc->params[i].character = 'g'; @@ -1590,7 +1600,7 @@ extern "C" desc->params[i].value.ui = 32768; strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); - + i++; strcpy(desc->params[i].name, "clock-drift"); desc->params[i].character = 's'; @@ -1598,7 +1608,7 @@ extern "C" desc->params[i].value.i = FALSE; strcpy(desc->params[i].short_desc, "Clock drift compensation"); strcpy(desc->params[i].long_desc, "Whether to compensate clock drift in dynamically created aggregate device"); - + return desc; } diff --git a/macosx/coreaudio/JackCoreAudioDriver.cpp b/macosx/coreaudio/JackCoreAudioDriver.cpp index 3b02ae9c..03e22adf 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.cpp +++ b/macosx/coreaudio/JackCoreAudioDriver.cpp @@ -39,7 +39,7 @@ static void Print4CharCode(const char* msg, long c) { UInt32 __4CC_number = (c); char __4CC_string[5]; - *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number); + *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number); __4CC_string[4] = 0; jack_log("%s'%s'", (msg), __4CC_string); } @@ -194,22 +194,22 @@ OSStatus JackCoreAudioDriver::Render(void *inRefCon, driver->fActionFags = ioActionFlags; driver->fCurrentTime = (AudioTimeStamp *)inTimeStamp; driver->fDriverOutputData = ioData; - + // Setup threadded based log function once... if (set_threaded_log_function()) { - + jack_log("set_threaded_log_function"); JackMachThread::GetParams(pthread_self(), &driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint); - + if (driver->fComputationGrain > 0) { jack_log("JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period", int(driver->fComputationGrain * 100)); driver->fEngineControl->fComputation = driver->fEngineControl->fPeriod * driver->fComputationGrain; } - + // Signal waiting start function... driver->fState = true; } - + driver->CycleTakeBeginTime(); return driver->Process(); } @@ -276,9 +276,9 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, void* inClientData) { JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData; - + switch (inPropertyID) { - + case kAudioDevicePropertyDeviceIsRunning: { UInt32 isrunning = 0; UInt32 outsize = sizeof(UInt32); @@ -287,14 +287,14 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, } break; } - + case kAudioDeviceProcessorOverload: { jack_error("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload"); jack_time_t cur_time = GetMicroSeconds(); - driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing... + driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing... break; } - + case kAudioDevicePropertyStreamConfiguration: { jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit..."); driver->NotifyFailure(JackBackendError, "Another application has changed the device configuration."); // Message length limited to JACK_MESSAGE_SIZE @@ -302,25 +302,25 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, kill(JackTools::GetPID(), SIGINT); return kAudioHardwareUnsupportedOperationError; } - + case kAudioDevicePropertyNominalSampleRate: { Float64 sampleRate = 0; UInt32 outsize = sizeof(Float64); OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate); if (err != noErr) return kAudioHardwareUnsupportedOperationError; - + char device_name[256]; const char* digidesign_name = "Digidesign"; driver->GetDeviceNameFromID(driver->fDeviceID, device_name); - + if (sampleRate != driver->fEngineControl->fSampleRate) { - + // Digidesign hardware, so "special" code : change the SR again here if (strncmp(device_name, digidesign_name, sizeof(digidesign_name)) == 0) { - + jack_log("Digidesign HW = %s", device_name); - + // Set sample rate again... sampleRate = driver->fEngineControl->fSampleRate; err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sampleRate); @@ -330,7 +330,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, } else { jack_log("Set sample rate = %f", sampleRate); } - + // Check new sample rate again... outsize = sizeof(Float64); err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate); @@ -341,7 +341,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, jack_log("Checked sample rate = %f", sampleRate); } return noErr; - + } else { driver->NotifyFailure(JackBackendError, "Another application has changed the sample rate."); // Message length limited to JACK_MESSAGE_SIZE driver->CloseAUHAL(); @@ -350,7 +350,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, } } } - + } return noErr; } @@ -405,6 +405,10 @@ OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id) if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) return res; + if (inDefault == 0) { + jack_error("Error : input device is 0, please select a correct one !!"); + return -1; + } jack_log("GetDefaultInputDevice: input = %ld ", inDefault); *id = inDefault; return noErr; @@ -419,6 +423,10 @@ OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id) if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) return res; + if (outDefault == 0) { + jack_error("Error : output device is 0, please select a correct one !!"); + return -1; + } jack_log("GetDefaultOutputDevice: output = %ld", outDefault); *id = outDefault; return noErr; @@ -435,7 +443,7 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channe OSStatus err = noErr; UInt32 outSize; Boolean outWritable; - + channelCount = 0; err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable); if (err == noErr) { @@ -450,11 +458,11 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channe } JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) - : JackAudioDriver(name, alias, engine, table), - fJackInputData(NULL), - fDriverOutputData(NULL), - fPluginID(0), - fState(false), + : JackAudioDriver(name, alias, engine, table), + fJackInputData(NULL), + fDriverOutputData(NULL), + fPluginID(0), + fState(false), fHogged(false), fIOUsage(1.f), fComputationGrain(-1.f), @@ -464,7 +472,7 @@ JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, Ja JackCoreAudioDriver::~JackCoreAudioDriver() {} -OSStatus JackCoreAudioDriver::DestroyAggregateDevice() +OSStatus JackCoreAudioDriver::DestroyAggregateDevice() { OSStatus osErr = noErr; AudioObjectPropertyAddress pluginAOPA; @@ -472,37 +480,37 @@ OSStatus JackCoreAudioDriver::DestroyAggregateDevice() pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; pluginAOPA.mElement = kAudioObjectPropertyElementMaster; UInt32 outDataSize; - + if (fPluginID > 0) { - + osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); if (osErr != noErr) { jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error"); printError(osErr); return osErr; } - + osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID); if (osErr != noErr) { jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error"); printError(osErr); return osErr; } - + } - + return noErr; } - -OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) + +OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) { OSStatus err = noErr; AudioObjectID sub_device[32]; UInt32 outSize = sizeof(sub_device); - + err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); vector captureDeviceIDArray; - + if (err != noErr) { jack_log("Input device does not have subdevices"); captureDeviceIDArray.push_back(captureDeviceID); @@ -513,10 +521,10 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI captureDeviceIDArray.push_back(sub_device[i]); } } - - err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); + + err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); vector playbackDeviceIDArray; - + if (err != noErr) { jack_log("Output device does not have subdevices"); playbackDeviceIDArray.push_back(playbackDeviceID); @@ -527,16 +535,16 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI playbackDeviceIDArray.push_back(sub_device[i]); } } - + return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice); } -OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector captureDeviceID, vector playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) +OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector captureDeviceID, vector playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) { OSStatus osErr = noErr; UInt32 outSize; Boolean outWritable; - + // Prepare sub-devices for clock drift compensation // Workaround for bug in the HAL : until 10.6.2 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; @@ -545,7 +553,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap AudioClassID inClass = kAudioSubDeviceClassID; void* theQualifierData = &inClass; UInt32 subDevicesNum = 0; - + //--------------------------------------------------------------------------- // Setup SR of both devices otherwise creating AD may fail... //--------------------------------------------------------------------------- @@ -553,18 +561,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap UInt32 clockdomain = 0; outSize = sizeof(UInt32); bool need_clock_drift_compensation = false; - + for (UInt32 i = 0; i < captureDeviceID.size(); i++) { if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device"); } else { // Check clock domain - osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); + osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); if (osErr != 0) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error"); printError(osErr); } else { - keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; + keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain); if (clockdomain != 0 && clockdomain != keptclockdomain) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed..."); @@ -573,18 +581,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap } } } - + for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device"); } else { // Check clock domain - osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); + osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); if (osErr != 0) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error"); printError(osErr); } else { - keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; + keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain); if (clockdomain != 0 && clockdomain != keptclockdomain) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed..."); @@ -593,7 +601,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap } } } - + // If no valid clock domain was found, then assume we have to compensate... if (keptclockdomain == 0) { need_clock_drift_compensation = true; @@ -602,18 +610,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap //--------------------------------------------------------------------------- // Start to create a new aggregate by getting the base audio hardware plugin //--------------------------------------------------------------------------- - + char device_name[256]; for (UInt32 i = 0; i < captureDeviceID.size(); i++) { GetDeviceNameFromID(captureDeviceID[i], device_name); jack_info("Separated input = '%s' ", device_name); } - + for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { GetDeviceNameFromID(playbackDeviceID[i], device_name); jack_info("Separated output = '%s' ", device_name); } - + osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error"); @@ -624,7 +632,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap AudioValueTranslation pluginAVT; CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio"); - + pluginAVT.mInputData = &inBundleRef; pluginAVT.mInputDataSize = sizeof(inBundleRef); pluginAVT.mOutputData = &fPluginID; @@ -645,22 +653,22 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex"); CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex"); - + // add the name of the device to the dictionary CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef); // add our choice of UID for the aggregate device to the dictionary CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef); - + // add a "private aggregate key" to the dictionary int value = 1; CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value); - + SInt32 system; Gestalt(gestaltSystemVersion, &system); - + jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054); - + // Starting with 10.5.4 systems, the AD can be internal... (better) if (system < 0x00001054) { jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device...."); @@ -668,16 +676,16 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device...."); CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef); } - + // Prepare sub-devices for clock drift compensation CFMutableArrayRef subDevicesArrayClock = NULL; - + /* if (fClockDriftCompensate) { if (need_clock_drift_compensation) { jack_info("Clock drift compensation activated..."); subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - + for (UInt32 i = 0; i < captureDeviceID.size(); i++) { CFStringRef UID = GetDeviceName(captureDeviceID[i]); if (UID) { @@ -688,7 +696,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); } } - + for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { CFStringRef UID = GetDeviceName(playbackDeviceID[i]); if (UID) { @@ -699,7 +707,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); } } - + // add sub-device clock array for the aggregate device to the dictionary CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock); } else { @@ -707,14 +715,14 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap } } */ - + //------------------------------------------------- // Create a CFMutableArray for our sub-device list //------------------------------------------------- - + // we need to append the UID for each device to a CFMutableArray, so create one here CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - + vector captureDeviceUID; for (UInt32 i = 0; i < captureDeviceID.size(); i++) { CFStringRef ref = GetDeviceName(captureDeviceID[i]); @@ -724,7 +732,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap // input sub-devices in this example, so append the sub-device's UID to the CFArray CFArrayAppendValue(subDevicesArray, ref); } - + vector playbackDeviceUID; for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { CFStringRef ref = GetDeviceName(playbackDeviceID[i]); @@ -734,11 +742,11 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap // output sub-devices in this example, so append the sub-device's UID to the CFArray CFArrayAppendValue(subDevicesArray, ref); } - + //----------------------------------------------------------------------- // Feed the dictionary to the plugin, to create a blank aggregate device //----------------------------------------------------------------------- - + AudioObjectPropertyAddress pluginAOPA; pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice; pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; @@ -751,7 +759,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap printError(osErr); goto error; } - + osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error"); @@ -777,10 +785,10 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap printError(osErr); goto error; } - + // pause again to give the changes time to take effect CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - + //----------------------- // Set the master device //----------------------- @@ -797,36 +805,36 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap printError(osErr); goto error; } - + // pause again to give the changes time to take effect CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - + // Prepare sub-devices for clock drift compensation // Workaround for bug in the HAL : until 10.6.2 - + if (fClockDriftCompensate) { if (need_clock_drift_compensation) { jack_info("Clock drift compensation activated..."); - + // Get the property data size osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error"); printError(osErr); } - + // Calculate the number of object IDs subDevicesNum = outSize / sizeof(AudioObjectID); jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum); AudioObjectID subDevices[subDevicesNum]; outSize = sizeof(subDevices); - + osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices); if (osErr != noErr) { jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error"); printError(osErr); } - + // Set kAudioSubDevicePropertyDriftCompensation property... for (UInt32 index = 0; index < subDevicesNum; ++index) { UInt32 theDriftCompensationValue = 1; @@ -839,22 +847,22 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap } else { jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)"); } - } - + } + // pause again to give the changes time to take effect CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - + //---------- // Clean up //---------- - + // release the private AD key CFRelease(AggregateDeviceNumberRef); // release the CF objects we have created - we don't need them any more CFRelease(aggDeviceDict); CFRelease(subDevicesArray); - + if (subDevicesArrayClock) CFRelease(subDevicesArrayClock); @@ -862,35 +870,35 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector cap for (UInt32 i = 0; i < captureDeviceUID.size(); i++) { CFRelease(captureDeviceUID[i]); } - + for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) { CFRelease(playbackDeviceUID[i]); } - + jack_log("New aggregate device %ld", *outAggregateDevice); return noErr; - + error: DestroyAggregateDevice(); return -1; } -int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, - const char* playback_driver_uid, - char* capture_driver_name, - char* playback_driver_name, +int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, + const char* playback_driver_uid, + char* capture_driver_name, + char* playback_driver_name, jack_nframes_t samplerate) { capture_driver_name[0] = 0; playback_driver_name[0] = 0; - + // Duplex if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) { jack_log("JackCoreAudioDriver::Open duplex"); - + // Same device for capture and playback... if (strcmp(capture_driver_uid, playback_driver_uid) == 0) { - + if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) { jack_log("Will take default in/out"); if (GetDefaultDevice(&fDeviceID) != noErr) { @@ -902,12 +910,12 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, jack_error("Cannot get device name from device ID"); return -1; } - + } else { - + // Creates aggregate device AudioDeviceID captureID, playbackID; - + if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { jack_log("Will take default input"); if (GetDefaultInputDevice(&captureID) != noErr) { @@ -963,10 +971,10 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, jack_log("JackCoreAudioDriver::Open default driver"); if (GetDefaultDevice(&fDeviceID) != noErr) { jack_error("Cannot open default device in duplex mode, so aggregate default input and default output"); - + // Creates aggregate device AudioDeviceID captureID, playbackID; - + if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { jack_log("Will take default input"); if (GetDefaultInputDevice(&captureID) != noErr) { @@ -974,7 +982,7 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, return -1; } } - + if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) { jack_log("Will take default output"); if (GetDefaultOutputDevice(&playbackID) != noErr) { @@ -982,12 +990,12 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, return -1; } } - + if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) return -1; } } - + if (fHogged) { if (TakeHog()) { jack_info("Device = %ld has been hogged", fDeviceID); @@ -1111,7 +1119,7 @@ int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes usleep(100000); jack_log("Wait count = %d", count); } - + // Check new sample rate outSize = sizeof(Float64); err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); @@ -1150,7 +1158,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, jack_error("No input and output channels..."); return -1; } - + // AUHAL ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; Component HALOutput = FindNextComponent(NULL, &cd); @@ -1177,7 +1185,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, enableIO = 0; jack_log("Setup AUHAL input off"); } - + err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input"); @@ -1192,14 +1200,14 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, enableIO = 0; jack_log("Setup AUHAL output off"); } - + err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output"); printError(err1); goto error; } - + size = sizeof(AudioDeviceID); err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size); if (err1 != noErr) { @@ -1217,7 +1225,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, printError(err1); goto error; } - + // Set buffer size if (capturing && inchannels > 0) { err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32)); @@ -1272,7 +1280,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, // Setup stream converters if (capturing && inchannels > 0) { - + size = sizeof(AudioStreamBasicDescription); err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size); if (err1 != noErr) { @@ -1281,7 +1289,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, goto error; } PrintStreamDesc(&srcFormat); - + jack_log("Setup AUHAL input stream converter SR = %ld", samplerate); srcFormat.mSampleRate = samplerate; srcFormat.mFormatID = kAudioFormatLinearPCM; @@ -1292,7 +1300,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, srcFormat.mChannelsPerFrame = inchannels; srcFormat.mBitsPerChannel = 32; PrintStreamDesc(&srcFormat); - + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); @@ -1302,7 +1310,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, } if (playing && outchannels > 0) { - + size = sizeof(AudioStreamBasicDescription); err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &size); if (err1 != noErr) { @@ -1311,7 +1319,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, goto error; } PrintStreamDesc(&dstFormat); - + jack_log("Setup AUHAL output stream converter SR = %ld", samplerate); dstFormat.mSampleRate = samplerate; dstFormat.mFormatID = kAudioFormatLinearPCM; @@ -1322,7 +1330,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, dstFormat.mChannelsPerFrame = outchannels; dstFormat.mBitsPerChannel = 32; PrintStreamDesc(&dstFormat); - + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); @@ -1355,7 +1363,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, } return 0; - + error: CloseAUHAL(); return -1; @@ -1486,12 +1494,12 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, fComputationGrain = float(computation_grain) / 100.f; fHogged = hogged; fClockDriftCompensate = clock_drift; - + SInt32 major; SInt32 minor; Gestalt(gestaltSystemVersionMajor, &major); Gestalt(gestaltSystemVersionMinor, &minor); - + // Starting with 10.6 systems, the HAL notification thread is created internally if (major == 10 && minor >= 6) { CFRunLoopRef theRunLoop = NULL; @@ -1515,10 +1523,10 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, if (SetupBufferSize(buffer_size) < 0) goto error; - + if (SetupSampleRate(samplerate) < 0) goto error; - + if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, samplerate) < 0) goto error; @@ -1528,7 +1536,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, if (AddListeners() < 0) goto error; - + // Core driver may have changed the in/out values fCaptureChannels = inchannels; fPlaybackChannels = outchannels; @@ -1561,7 +1569,8 @@ int JackCoreAudioDriver::Attach() char channel_name[64]; char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - + jack_latency_range_t range; + jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); for (int i = 0; i < fCaptureChannels; i++) { @@ -1597,7 +1606,8 @@ int JackCoreAudioDriver::Attach() port = fGraphManager->GetPort(port_index); port->SetAlias(alias); - port->SetLatency(fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency); + range.min = range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency; + port->SetLatencyRange(JackCaptureLatency, &range); fCapturePortList[i] = port_index; } @@ -1635,7 +1645,8 @@ int JackCoreAudioDriver::Attach() port = fGraphManager->GetPort(port_index); port->SetAlias(alias); // Add more latency if "async" mode is used... - port->SetLatency(fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency); + range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency; + port->SetLatencyRange(JackPlaybackLatency, &range); fPlaybackPortList[i] = port_index; // Monitor ports @@ -1648,7 +1659,8 @@ int JackCoreAudioDriver::Attach() } else { port = fGraphManager->GetPort(port_index); port->SetAlias(alias); - port->SetLatency(fEngineControl->fBufferSize); + range.min = range.max = fEngineControl->fBufferSize; + port->SetLatencyRange(JackCaptureLatency, &range); fMonitorPortList[i] = port_index; } } @@ -1670,7 +1682,7 @@ int JackCoreAudioDriver::Start() OSStatus err = AudioOutputUnitStart(fAUHAL); if (err != noErr) return -1; - + // Waiting for Measure callback to be called (= driver has started) fState = false; int count = 0; @@ -1678,7 +1690,7 @@ int JackCoreAudioDriver::Start() usleep(100000); jack_log("JackCoreAudioDriver::Start wait count = %d", count); } - + if (count < WAIT_COUNTER) { jack_info("CoreAudio driver is running..."); return 0; @@ -1738,17 +1750,17 @@ bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput) return false; } } - + return true; } - + bool JackCoreAudioDriver::TakeHog() { OSStatus err = noErr; AudioObjectID sub_device[32]; UInt32 outSize = sizeof(sub_device); err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); - + if (err != noErr) { jack_log("Device does not have subdevices"); return TakeHogAux(fDeviceID, true); @@ -1763,12 +1775,12 @@ bool JackCoreAudioDriver::TakeHog() return true; } } - + bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device) { UInt32 deviceType, outSize = sizeof(UInt32); OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType); - + if (err != noErr) { jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error"); return false; @@ -1786,7 +1798,7 @@ extern "C" { #endif - SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() + SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() { jack_driver_desc_t *desc; unsigned int i; @@ -1794,7 +1806,7 @@ extern "C" strcpy(desc->name, "coreaudio"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 strcpy(desc->desc, "Apple CoreAudio API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 - + desc->nparams = 17; desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); @@ -1898,7 +1910,7 @@ extern "C" desc->params[i].value.i = FALSE; strcpy(desc->params[i].short_desc, "Display available CoreAudio devices"); strcpy(desc->params[i].long_desc, desc->params[i].short_desc); - + i++; strcpy(desc->params[i].name, "hog"); desc->params[i].character = 'H'; @@ -1906,7 +1918,7 @@ extern "C" desc->params[i].value.i = FALSE; strcpy(desc->params[i].short_desc, "Take exclusive access of the audio device"); strcpy(desc->params[i].long_desc, desc->params[i].short_desc); - + i++; strcpy(desc->params[i].name, "async-latency"); desc->params[i].character = 'L'; @@ -1914,7 +1926,7 @@ extern "C" desc->params[i].value.i = 100; strcpy(desc->params[i].short_desc, "Extra output latency in asynchronous mode (percent)"); strcpy(desc->params[i].long_desc, desc->params[i].short_desc); - + i++; strcpy(desc->params[i].name, "grain"); desc->params[i].character = 'G'; @@ -1922,7 +1934,7 @@ extern "C" desc->params[i].value.i = 100; strcpy(desc->params[i].short_desc, "Computation grain in RT thread (percent)"); strcpy(desc->params[i].long_desc, desc->params[i].short_desc); - + i++; strcpy(desc->params[i].name, "clock-drift"); desc->params[i].character = 's'; @@ -1934,7 +1946,7 @@ extern "C" return desc; } - SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) + SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) { jack_nframes_t srate = 44100; jack_nframes_t frames_per_interrupt = 128; @@ -1953,10 +1965,10 @@ extern "C" int computation_grain = -1; bool hogged = false; bool clock_drift = false; - + for (node = params; node; node = jack_slist_next(node)) { param = (const jack_driver_param_t *) node->data; - + switch (param->character) { case 'd': @@ -2018,19 +2030,19 @@ extern "C" case 'l': Jack::DisplayDeviceNames(); break; - + case 'H': hogged = true; break; - + case 'L': async_output_latency = param->value.ui; break; - + case 'G': computation_grain = param->value.ui; break; - + case 's': clock_drift = true; break; @@ -2044,7 +2056,7 @@ extern "C" } Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table); - if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid, + if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid, playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain, hogged, clock_drift) == 0) { return driver; } else { diff --git a/macosx/wscript b/macosx/wscript index 8fa9bd37..25ca9b3d 100644 --- a/macosx/wscript +++ b/macosx/wscript @@ -6,12 +6,6 @@ def create_jack_driver_obj(bld, target, sources, uselib = None): driver.features.append('cc') driver.env['shlib_PATTERN'] = 'jack_%s.so' driver.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] - # Seems uneeded here... - #if bld.env['HAVE_CELT']: - #if bld.env['HAVE_CELT_API_0_5']: - # driver.defines += ['HAVE_CELT', 'HAVE_CELT_API_0_5'] - #elif bld.env['HAVE_CELT_API_0_7']: - # driver.defines += ['HAVE_CELT', 'HAVE_CELT_API_0_7'] driver.includes = ['.', '../macosx', '../posix', '../common', '../common/jack'] driver.target = target driver.source = sources diff --git a/man/jack_iodelay.0 b/man/jack_iodelay.0 new file mode 100644 index 00000000..007e65a1 --- /dev/null +++ b/man/jack_iodelay.0 @@ -0,0 +1,53 @@ +.TH JACK_IODELAY "1" "!DATE!" "!VERSION!" +.SH NAME +jack_iodelay \- JACK toolkit client to measure roundtrip latency +.SH SYNOPSIS +.B jack_iodelay +.SH DESCRIPTION +.B jack_iodelay +will create one input and one output port, and then +measures the latency (signal delay) between them. For this to work, +the output port must be connected to its input port. The measurement +is accurate to a resolution of greater than 1 sample. +.PP +The expected use is to connect jack_iodelay's output port to a +hardware playback port, then use a physical loopback cable from the +corresponding hardware output connector to an input connector, and to +connect that corresponding hardware capture port to jack_iodelay's +input port. This creates a roundtrip that goes through any +analog-to-digital or digital-converters that are present in the audio +hardware. +.PP +Although the hardware loopback latency is the expected use, it is also +possible to use jack_iodelay to measure the latency along any fully +connected signal path, such as those involving other JACK clients. +.PP +Once jack_iodelay completes its measurement it will print the total +latency it has detected. This will include the JACK period length in +addition to any other latency in the signal path. It will continue to +print the value every 0.5 seconds or so so that if you wish you can +vary aspects of the signal path to see their effect on the measured +latency. +.PP +If no incoming signal is detected from the input port, jack_iodelay +will print +.PP +\fT Signal below threshold... .\fR +.PP +every second until this changes (e.g. until you establish the correct connections). +.PP +To use the value measured by jack_iodelay with the -I and -O arguments +of a JACK backend (also called Input Latency and Output Latency in the +setup dialog of qjackctl), you must subtract the JACK period size from +the result. Then, if you believe that the latency is equally +distributed between the input and output parts of your audio hardware +(extremely likely), divide the result by two and use that for input +and/or output latency value. Doing this measurement will enable JACK +clients that use the JACK latency API to accurately position/delay +audio to keep signals synchronized even when there are inherent delays +in the end-to-end signal pathways. +.SH AUTHOR +Originally written in C++ by Fons Adriensen, ported to C by Torben Hohn. + + + diff --git a/posix/JackPosixMutex.h b/posix/JackPosixMutex.h index ddf89553..a8607780 100644 --- a/posix/JackPosixMutex.h +++ b/posix/JackPosixMutex.h @@ -33,47 +33,47 @@ namespace Jack \brief Mutex abstraction. */ - + class JackBasePosixMutex { - + protected: - + pthread_mutex_t fMutex; - + public: - + JackBasePosixMutex() { - pthread_mutex_init(&fMutex, NULL); + pthread_mutex_init(&fMutex, NULL); } - + virtual ~JackBasePosixMutex() { pthread_mutex_destroy(&fMutex); } - + void Lock() { int res = pthread_mutex_lock(&fMutex); if (res != 0) - jack_error("JackBasePosixMutex::Lock res = %d", res); + jack_log("JackBasePosixMutex::Lock res = %d", res); } - + bool Trylock() { return (pthread_mutex_trylock(&fMutex) == 0); } - + void Unlock() { int res = pthread_mutex_unlock(&fMutex); if (res != 0) - jack_error("JackBasePosixMutex::Unlock res = %d", res); + jack_log("JackBasePosixMutex::Unlock res = %d", res); } - + }; - + class JackPosixMutex { @@ -97,7 +97,7 @@ class JackPosixMutex res = pthread_mutexattr_destroy(&mutex_attr); assert(res == 0); } - + virtual ~JackPosixMutex() { pthread_mutex_destroy(&fMutex); @@ -107,7 +107,7 @@ class JackPosixMutex { int res = pthread_mutex_lock(&fMutex); if (res != 0) - jack_error("JackPosixMutex::Lock res = %d", res); + jack_log("JackPosixMutex::Lock res = %d", res); return (res == 0); } @@ -120,7 +120,7 @@ class JackPosixMutex { int res = pthread_mutex_unlock(&fMutex); if (res != 0) - jack_error("JackPosixMutex::Unlock res = %d", res); + jack_log("JackPosixMutex::Unlock res = %d", res); return (res == 0); } diff --git a/posix/JackPosixThread.cpp b/posix/JackPosixThread.cpp index 4b4315db..aed3796b 100644 --- a/posix/JackPosixThread.cpp +++ b/posix/JackPosixThread.cpp @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -40,19 +40,19 @@ void* JackPosixThread::ThreadHandler(void* arg) if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) { jack_error("pthread_setcanceltype err = %s", strerror(err)); } - + // Signal creation thread when started with StartSync jack_log("ThreadHandler: start"); obj->fStatus = kIniting; - + // Call Init method if (!runnable->Init()) { jack_error("Thread init fails: thread quits"); return 0; } - + obj->fStatus = kRunning; - + // If Init succeed, start the thread loop bool res = true; while (obj->fStatus == kRunning && res) { @@ -76,11 +76,11 @@ int JackPosixThread::Start() return 0; } } - + int JackPosixThread::StartSync() { fStatus = kStarting; - + if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { fStatus = kIdle; return -1; @@ -90,10 +90,10 @@ int JackPosixThread::StartSync() JackSleep(1000); } return (count == 1000) ? -1 : 0; - } + } } - -int JackPosixThread::StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg) + +int JackPosixThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg) { pthread_attr_t attributes; struct sched_param rt_param; @@ -111,19 +111,19 @@ int JackPosixThread::StartImp(pthread_t* thread, int priority, int realtime, voi } if (realtime) { - + jack_log("Create RT thread"); if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) { jack_error("Cannot request explicit scheduling for RT thread res = %d", res); return -1; } - + if ((res = pthread_attr_setschedpolicy(&attributes, JACK_SCHED_POLICY))) { jack_error("Cannot set RR scheduling class for RT thread res = %d", res); return -1; } - + memset(&rt_param, 0, sizeof(rt_param)); rt_param.sched_priority = priority; @@ -152,13 +152,13 @@ int JackPosixThread::StartImp(pthread_t* thread, int priority, int realtime, voi int JackPosixThread::Kill() { - if (fThread != (pthread_t)NULL) { // If thread has been started + if (fThread != (jack_native_thread_t)NULL) { // If thread has been started jack_log("JackPosixThread::Kill"); void* status; pthread_cancel(fThread); pthread_join(fThread, &status); fStatus = kIdle; - fThread = (pthread_t)NULL; + fThread = (jack_native_thread_t)NULL; return 0; } else { return -1; @@ -167,21 +167,21 @@ int JackPosixThread::Kill() int JackPosixThread::Stop() { - if (fThread != (pthread_t)NULL) { // If thread has been started + if (fThread != (jack_native_thread_t)NULL) { // If thread has been started jack_log("JackPosixThread::Stop"); void* status; fStatus = kIdle; // Request for the thread to stop pthread_join(fThread, &status); - fThread = (pthread_t)NULL; + fThread = (jack_native_thread_t)NULL; return 0; } else { return -1; } } -int JackPosixThread::KillImp(pthread_t thread) +int JackPosixThread::KillImp(jack_native_thread_t thread) { - if (thread != (pthread_t)NULL) { // If thread has been started + if (thread != (jack_native_thread_t)NULL) { // If thread has been started jack_log("JackPosixThread::Kill"); void* status; pthread_cancel(thread); @@ -192,9 +192,9 @@ int JackPosixThread::KillImp(pthread_t thread) } } -int JackPosixThread::StopImp(pthread_t thread) +int JackPosixThread::StopImp(jack_native_thread_t thread) { - if (thread != (pthread_t)NULL) { // If thread has been started + if (thread != (jack_native_thread_t)NULL) { // If thread has been started jack_log("JackPosixThread::Stop"); void* status; pthread_join(thread, &status); @@ -206,7 +206,7 @@ int JackPosixThread::StopImp(pthread_t thread) int JackPosixThread::AcquireRealTime() { - return (fThread != (pthread_t)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1; + return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1; } int JackPosixThread::AcquireSelfRealTime() @@ -225,7 +225,7 @@ int JackPosixThread::AcquireSelfRealTime(int priority) fPriority = priority; return AcquireSelfRealTime(); } -int JackPosixThread::AcquireRealTimeImp(pthread_t thread, int priority) +int JackPosixThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority) { struct sched_param rtparam; int res; @@ -243,7 +243,7 @@ int JackPosixThread::AcquireRealTimeImp(pthread_t thread, int priority) int JackPosixThread::DropRealTime() { - return (fThread != (pthread_t)NULL) ? DropRealTimeImp(fThread) : -1; + return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1; } int JackPosixThread::DropSelfRealTime() @@ -251,7 +251,7 @@ int JackPosixThread::DropSelfRealTime() return DropRealTimeImp(pthread_self()); } -int JackPosixThread::DropRealTimeImp(pthread_t thread) +int JackPosixThread::DropRealTimeImp(jack_native_thread_t thread) { struct sched_param rtparam; int res; @@ -265,7 +265,7 @@ int JackPosixThread::DropRealTimeImp(pthread_t thread) return 0; } -pthread_t JackPosixThread::GetThreadID() +jack_native_thread_t JackPosixThread::GetThreadID() { return fThread; } @@ -320,42 +320,42 @@ bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr) bool jack_tls_allocate_key(jack_tls_key *key_ptr) { int ret; - + ret = pthread_key_create(key_ptr, NULL); if (ret != 0) { jack_error("pthread_key_create() failed with error %d", ret); return false; } - + return true; } bool jack_tls_free_key(jack_tls_key key) { int ret; - + ret = pthread_key_delete(key); if (ret != 0) { jack_error("pthread_key_delete() failed with error %d", ret); return false; } - + return true; } bool jack_tls_set(jack_tls_key key, void *data_ptr) { int ret; - + ret = pthread_setspecific(key, (const void *)data_ptr); if (ret != 0) { jack_error("pthread_setspecific() failed with error %d", ret); return false; } - + return true; } diff --git a/posix/JackPosixThread.h b/posix/JackPosixThread.h index d38c573c..764a48df 100644 --- a/posix/JackPosixThread.h +++ b/posix/JackPosixThread.h @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -40,16 +40,16 @@ class SERVER_EXPORT JackPosixThread : public detail::JackThreadInterface protected: - pthread_t fThread; + jack_native_thread_t fThread; static void* ThreadHandler(void* arg); public: JackPosixThread(JackRunnableInterface* runnable, bool real_time, int priority, int cancellation) - : JackThreadInterface(runnable, priority, real_time, cancellation), fThread((pthread_t)NULL) + : JackThreadInterface(runnable, priority, real_time, cancellation), fThread((jack_native_thread_t)NULL) {} JackPosixThread(JackRunnableInterface* runnable, int cancellation = PTHREAD_CANCEL_ASYNCHRONOUS) - : JackThreadInterface(runnable, 0, false, cancellation), fThread((pthread_t)NULL) + : JackThreadInterface(runnable, 0, false, cancellation), fThread((jack_native_thread_t)NULL) {} int Start(); @@ -60,23 +60,23 @@ class SERVER_EXPORT JackPosixThread : public detail::JackThreadInterface int AcquireRealTime(); // Used when called from another thread int AcquireSelfRealTime(); // Used when called from thread itself - + int AcquireRealTime(int priority); // Used when called from another thread int AcquireSelfRealTime(int priority); // Used when called from thread itself - + int DropRealTime(); // Used when called from another thread int DropSelfRealTime(); // Used when called from thread itself - pthread_t GetThreadID(); + jack_native_thread_t GetThreadID(); bool IsThread(); - static int AcquireRealTimeImp(pthread_t thread, int priority); - static int AcquireRealTimeImp(pthread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint) + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority); + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint) { return JackPosixThread::AcquireRealTimeImp(thread, priority); } - static int DropRealTimeImp(pthread_t thread); - static int StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); - static int StopImp(pthread_t thread); - static int KillImp(pthread_t thread); + static int DropRealTimeImp(jack_native_thread_t thread); + static int StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); + static int StopImp(jack_native_thread_t thread); + static int KillImp(jack_native_thread_t thread); }; SERVER_EXPORT void ThreadExit(); diff --git a/posix/JackSocket.cpp b/posix/JackSocket.cpp index e1984195..6d7d6879 100644 --- a/posix/JackSocket.cpp +++ b/posix/JackSocket.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -45,12 +45,12 @@ void JackClientSocket::SetReadTimeOut(long sec) { int flags; fTimeOut = sec; - + if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) { jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_GETFL"); return; } - + flags |= O_NONBLOCK; if (fcntl(fSocket, F_SETFL, flags) < 0) { jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_SETFL"); @@ -62,12 +62,12 @@ void JackClientSocket::SetWriteTimeOut(long sec) { int flags; fTimeOut = sec; - + if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) { jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_GETFL"); return; } - + flags |= O_NONBLOCK; if (fcntl(fSocket, F_SETFL, flags) < 0) { jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_SETFL"); @@ -100,7 +100,7 @@ void JackClientSocket::SetWriteTimeOut(long sec) #endif void JackClientSocket::SetNonBlocking(bool onoff) -{ +{ if (onoff) { long flags = 0; if (fcntl(fSocket, F_SETFL, flags | O_NONBLOCK) < 0) { @@ -140,7 +140,7 @@ int JackClientSocket::Connect(const char* dir, const char* name, int which) // A int JackClientSocket::Close() { - jack_log("JackClientSocket::Close"); + jack_log("JackClientSocket::Close"); if (fSocket > 0) { shutdown(fSocket, SHUT_RDWR); close(fSocket); @@ -161,17 +161,17 @@ int JackClientSocket::Read(void* data, int len) struct timeval tv; fd_set fdset; ssize_t res; - + tv.tv_sec = fTimeOut; tv.tv_usec = 0; - + FD_ZERO(&fdset); FD_SET(fSocket, &fdset); - + do { res = select(fSocket + 1, &fdset, NULL, NULL, &tv); } while (res < 0 && errno == EINTR); - + if (res < 0) { return res; } else if (res == 0) { @@ -179,9 +179,9 @@ int JackClientSocket::Read(void* data, int len) } } #endif - + if ((res = read(fSocket, data, len)) != len) { - if (errno == EWOULDBLOCK) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { jack_error("JackClientSocket::Read time out"); return 0; // For a non blocking socket, a read failure is not considered as an error } else if (res != 0) { @@ -201,21 +201,21 @@ int JackClientSocket::Write(void* data, int len) #if defined(__sun__) || defined(sun) if (fTimeOut > 0) { - + struct timeval tv; fd_set fdset; ssize_t res; - + tv.tv_sec = fTimeOut; tv.tv_usec = 0; - + FD_ZERO(&fdset); FD_SET(fSocket, &fdset); - + do { res = select(fSocket + 1, NULL, &fdset, NULL, &tv); } while (res < 0 && errno == EINTR); - + if (res < 0) { return res; } else if (res == 0) { @@ -225,7 +225,7 @@ int JackClientSocket::Write(void* data, int len) #endif if ((res = write(fSocket, data, len)) != len) { - if (errno == EWOULDBLOCK) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { jack_log("JackClientSocket::Write time out"); return 0; // For a non blocking socket, a write failure is not considered as an error } else if (res != 0) { @@ -251,7 +251,7 @@ int JackServerSocket::Bind(const char* dir, const char* name, int which) // A re addr.sun_family = AF_UNIX; BuildName(name, fName, dir, which); strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1); - + jack_log("Bind: addr.sun_path %s", addr.sun_path); unlink(fName); // Security... diff --git a/posix/JackSocketClientChannel.cpp b/posix/JackSocketClientChannel.cpp index 1a6d7ad5..23555c1d 100644 --- a/posix/JackSocketClientChannel.cpp +++ b/posix/JackSocketClientChannel.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -108,7 +108,6 @@ int JackSocketClientChannel::Start() } } - void JackSocketClientChannel::Stop() { jack_log("JackSocketClientChannel::Stop"); @@ -246,61 +245,73 @@ void JackSocketClientChannel::SetFreewheel(int onoff, int* result) ServerSyncCall(&req, &res, result); } -void JackSocketClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t ** result) +void JackSocketClientChannel::ComputeTotalLatencies(int* result) +{ + JackComputeTotalLatenciesRequest req; + JackResult res; + ServerSyncCall(&req, &res, result); +} + +void JackSocketClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result) { JackSessionNotifyRequest req(refnum, path, type, target); - JackSessionNotifyResult res; + JackSessionNotifyResult res; int intresult; ServerSyncCall(&req, &res, &intresult); - jack_session_command_t *session_command = (jack_session_command_t *)malloc( sizeof(jack_session_command_t) * (res.fCommandList.size()+1) ); - int i=0; - + jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (res.fCommandList.size() + 1)); + int i = 0; + for (std::list::iterator ci=res.fCommandList.begin(); ci!=res.fCommandList.end(); ci++) { - session_command[i].uuid = strdup( ci->fUUID ); - session_command[i].client_name = strdup( ci->fClientName ); - session_command[i].command = strdup( ci->fCommand ); - session_command[i].flags = ci->fFlags; - - i+=1; - } - + session_command[i].uuid = strdup( ci->fUUID ); + session_command[i].client_name = strdup( ci->fClientName ); + session_command[i].command = strdup( ci->fCommand ); + session_command[i].flags = ci->fFlags; + i += 1; + } + session_command[i].uuid = NULL; session_command[i].client_name = NULL; session_command[i].command = NULL; session_command[i].flags = (jack_session_flags_t)0; - *result = session_command; } void JackSocketClientChannel::SessionReply(int refnum, int* result) { JackSessionReplyRequest req(refnum); - JackResult res; + JackResult res; ServerSyncCall(&req, &res, result); } -void JackSocketClientChannel::GetUUIDForClientName( int refnum, const char *client_name, char *uuid_res, int *result ) +void JackSocketClientChannel::GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) { JackGetUUIDRequest req(client_name); - JackUUIDResult res; + JackUUIDResult res; ServerSyncCall(&req, &res, result); - strncpy( uuid_res, res.fUUID, JACK_UUID_SIZE ); + strncpy(uuid_res, res.fUUID, JACK_UUID_SIZE); } -void JackSocketClientChannel::GetClientNameForUUID( int refnum, const char *uuid, char *name_res, int *result ) +void JackSocketClientChannel::GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) { JackGetClientNameRequest req(uuid); - JackClientNameResult res; + JackClientNameResult res; + ServerSyncCall(&req, &res, result); + strncpy(name_res, res.fName, JACK_CLIENT_NAME_SIZE); +} + +void JackSocketClientChannel::ClientHasSessionCallback(const char* client_name, int* result) +{ + JackClientHasSessionCallbackRequest req(client_name); + JackResult res; ServerSyncCall(&req, &res, result); - strncpy( name_res, res.fName, JACK_CLIENT_NAME_SIZE ); } -void JackSocketClientChannel::ReserveClientName( int refnum, const char *client_name, const char *uuid, int *result ) +void JackSocketClientChannel::ReserveClientName(int refnum, const char* client_name, const char* uuid, int* result) { JackReserveNameRequest req(refnum, client_name, uuid); - JackResult res; + JackResult res; ServerSyncCall(&req, &res, result); } @@ -363,7 +374,7 @@ bool JackSocketClientChannel::Init() jack_error("JackSocketClientChannel: cannot establish notication socket"); return false; } else { - return fClient->Init(); + return true; } } diff --git a/posix/JackSocketClientChannel.h b/posix/JackSocketClientChannel.h index 225887e7..8e2b0e30 100644 --- a/posix/JackSocketClientChannel.h +++ b/posix/JackSocketClientChannel.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -38,11 +38,11 @@ class JackSocketClientChannel : public detail::JackClientChannelInterface, publi private: - JackClientSocket fRequestSocket; // Socket to communicate with the server - JackServerSocket fNotificationListenSocket; // Socket listener for server notification - JackClientSocket* fNotificationSocket; // Socket for server notification + JackClientSocket fRequestSocket; // Socket to communicate with the server + JackServerSocket fNotificationListenSocket; // Socket listener for server notification + JackClientSocket* fNotificationSocket; // Socket for server notification JackThread fThread; // Thread to execute the event loop - JackClient* fClient; + JackClient* fClient; void ServerSyncCall(JackRequest* req, JackResult* res, int* result); void ServerAsyncCall(JackRequest* req, JackResult* res, int* result); @@ -77,12 +77,14 @@ class JackSocketClientChannel : public detail::JackClientChannelInterface, publi void PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result); void PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result); - + void PortRename(int refnum, jack_port_id_t port, const char* name, int* result); void SetBufferSize(jack_nframes_t buffer_size, int* result); void SetFreewheel(int onoff, int* result); + void ComputeTotalLatencies(int* result); + void ReleaseTimebase(int refnum, int* result); void SetTimebaseCallback(int refnum, int conditional, int* result); @@ -91,18 +93,18 @@ class JackSocketClientChannel : public detail::JackClientChannelInterface, publi void InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, int* result); void InternalClientUnload(int refnum, int int_ref, int* status, int* result); - // Session Stuff + // Session API void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result); void SessionReply(int refnum, int* result); - void GetUUIDForClientName( int refnum, const char *client_name, char *uuid_res, int *result ); - void GetClientNameForUUID( int refnum, const char *uuid, char *name_res, int *result ); - void ReserveClientName( int refnum, const char *client_name, const char *uuid, int *result ); + void GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result); + void GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result); + void ReserveClientName(int refnum, const char* client_name, const char *uuid, int* result); + void ClientHasSessionCallback(const char* client_name, int* result); // JackRunnableInterface interface bool Init(); bool Execute(); - bool IsChannelThread() { return fThread.IsThread(); } }; diff --git a/posix/JackSocketServerChannel.cpp b/posix/JackSocketServerChannel.cpp index e9176230..ac857de2 100644 --- a/posix/JackSocketServerChannel.cpp +++ b/posix/JackSocketServerChannel.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -51,7 +51,7 @@ JackSocketServerChannel::~JackSocketServerChannel() int JackSocketServerChannel::Open(const char* server_name, JackServer* server) { jack_log("JackSocketServerChannel::Open"); - + // Prepare request socket if (fRequestListenSocket.Bind(jack_server_dir, server_name, 0) < 0) { jack_log("JackSocketServerChannel::Open : cannot create result listen socket"); @@ -79,14 +79,14 @@ void JackSocketServerChannel::Close() delete socket; } } - + int JackSocketServerChannel::Start() { if (fThread.Start() != 0) { jack_error("Cannot start Jack server listener"); return -1; - } - + } + return 0; } @@ -168,6 +168,12 @@ bool JackSocketServerChannel::HandleRequest(int fd) return false; } + if (fd == JackServerGlobals::fRTNotificationSocket && header.fType != JackRequest::kNotification) { + jack_error("fRTNotificationSocket = %d", JackServerGlobals::fRTNotificationSocket); + jack_error("JackSocketServerChannel::HandleRequest : incorrect notification !!"); + return true; + } + // Read data switch (header.fType) { @@ -292,7 +298,7 @@ bool JackSocketServerChannel::HandleRequest(int fd) jack_error("JackRequest::DisconnectPorts write error ref = %d", req.fRefNum); break; } - + case JackRequest::kPortRename: { jack_log("JackRequest::PortRename"); JackPortRenameRequest req; @@ -326,6 +332,17 @@ bool JackSocketServerChannel::HandleRequest(int fd) break; } + case JackRequest::kComputeTotalLatencies: { + jack_log("JackRequest::ComputeTotalLatencies"); + JackComputeTotalLatenciesRequest req; + JackResult res; + if (req.Read(socket) == 0) + res.fResult = fServer->GetEngine()->ComputeTotalLatencies(); + if (res.Write(socket) < 0) + jack_error("JackRequest::ComputeTotalLatencies write error"); + break; + } + case JackRequest::kReleaseTimebase: { jack_log("JackRequest::ReleaseTimebase"); JackReleaseTimebaseRequest req; @@ -430,27 +447,26 @@ bool JackSocketServerChannel::HandleRequest(int fd) } case JackRequest::kGetClientByUUID: { - jack_log("JackRequest::GetClientNameForUUID"); + jack_log("JackRequest::GetClientByUUID"); JackGetClientNameRequest req; JackClientNameResult res; if (req.Read(socket) == 0) { fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName, &res.fResult); } if (res.Write(socket) < 0) - jack_error("JackRequest::GetClientNameForUUID write error"); + jack_error("JackRequest::GetClientByUUID write error"); break; } case JackRequest::kGetUUIDByClient: { - jack_log("JackRequest::GetUUIDForClientName"); + jack_log("JackRequest::GetUUIDByClient"); JackGetUUIDRequest req; JackUUIDResult res; if (req.Read(socket) == 0) { fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult); - res.fResult = 0; } if (res.Write(socket) < 0) - jack_error("JackRequest::GetUUIDForClientName write error"); + jack_error("JackRequest::GetUUIDByClient write error"); break; } @@ -466,11 +482,23 @@ bool JackSocketServerChannel::HandleRequest(int fd) break; } + case JackRequest::kClientHasSessionCallback: { + jack_log("JackRequest::ClientHasSessionCallback"); + JackClientHasSessionCallbackRequest req; + JackResult res; + if (req.Read(socket) == 0) { + fServer->GetEngine()->ClientHasSessionCallbackRequest(req.fName, &res.fResult); + } + if (res.Write(socket) < 0) + jack_error("JackRequest::ClientHasSessionCallback write error"); + break; + } + default: jack_error("Unknown request %ld", header.fType); break; } - + return true; } @@ -511,7 +539,7 @@ bool JackSocketServerChannel::Init() bool JackSocketServerChannel::Execute() { try { - + // Global poll if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) { jack_error("Engine poll failed err = %s request thread quits...", strerror(errno)); @@ -526,22 +554,22 @@ bool JackSocketServerChannel::Execute() jack_log("Poll client error err = %s", strerror(errno)); ClientKill(fd); } else if (fPollTable[i].revents & POLLIN) { - if (!HandleRequest(fd)) + if (!HandleRequest(fd)) jack_log("Could not handle external client request"); } } // Check the server request socket */ - if (fPollTable[0].revents & POLLERR) + if (fPollTable[0].revents & POLLERR) jack_error("Error on server request socket err = %s", strerror(errno)); - - if (fPollTable[0].revents & POLLIN) + + if (fPollTable[0].revents & POLLIN) ClientCreate(); } BuildPoolTable(); return true; - + } catch (JackQuitException& e) { jack_log("JackMachServerChannel::Execute JackQuitException"); return false; diff --git a/posix/JackSocketServerChannel.h b/posix/JackSocketServerChannel.h index 59c1a0d0..af61291a 100644 --- a/posix/JackSocketServerChannel.h +++ b/posix/JackSocketServerChannel.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -41,7 +41,7 @@ class JackSocketServerChannel : public JackRunnableInterface JackServerSocket fRequestListenSocket; // Socket to create request socket for the client JackThread fThread; // Thread to execute the event loop - JackServer* fServer; + JackServer* fServer; pollfd* fPollTable; bool fRebuild; std::map > fSocketTable; @@ -61,7 +61,7 @@ class JackSocketServerChannel : public JackRunnableInterface int Open(const char* server_name, JackServer* server); // Open the Server/Client connection void Close(); // Close the Server/Client connection - + int Start(); // JackRunnableInterface interface diff --git a/posix/JackSocketServerNotifyChannel.cpp b/posix/JackSocketServerNotifyChannel.cpp index df7381f1..c9d25509 100644 --- a/posix/JackSocketServerNotifyChannel.cpp +++ b/posix/JackSocketServerNotifyChannel.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackRequest.h" #include "JackConstants.h" #include "JackNotification.h" +#include "JackServerGlobals.h" namespace Jack { @@ -33,6 +34,7 @@ int JackSocketServerNotifyChannel::Open(const char* server_name) return -1; } else { fRequestSocket.SetNonBlocking(true); + JackServerGlobals::fRTNotificationSocket = fRequestSocket.GetFd(); return 0; } } @@ -63,7 +65,7 @@ void JackSocketServerNotifyChannel::NotifyQuit() jack_error("Could not write request ref = %d notify = %d", -1, kQUIT); } } - + } // end of namespace diff --git a/posix/JackSocketServerNotifyChannel.h b/posix/JackSocketServerNotifyChannel.h index 261ddbd4..31008164 100644 --- a/posix/JackSocketServerNotifyChannel.h +++ b/posix/JackSocketServerNotifyChannel.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/posix/JackSystemDeps_os.h b/posix/JackSystemDeps_os.h index cbddb0b1..41ee9528 100644 --- a/posix/JackSystemDeps_os.h +++ b/posix/JackSystemDeps_os.h @@ -25,6 +25,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include +#define UINT32_MAX 4294967295U + #define DRIVER_HANDLE void* #define LoadDriverModule(name) dlopen((name), RTLD_NOW | RTLD_GLOBAL) #define UnloadDriverModule(handle) dlclose((handle)) diff --git a/posix/JackTypes_os.h b/posix/JackTypes_os.h index 01e6c9b9..896d91ea 100644 --- a/posix/JackTypes_os.h +++ b/posix/JackTypes_os.h @@ -26,6 +26,8 @@ typedef unsigned long long UInt64; typedef pthread_key_t jack_tls_key; +typedef pthread_t jack_native_thread_t; + typedef int (*jack_thread_creator_t)(pthread_t*, const pthread_attr_t*, void* (*function)(void*), void* arg); #endif diff --git a/tests/jdelay.cpp b/tests/iodelay.cpp similarity index 79% rename from tests/jdelay.cpp rename to tests/iodelay.cpp index 709fd7e2..4ef90fb0 100644 --- a/tests/jdelay.cpp +++ b/tests/iodelay.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2003-2008 Fons Adriaensen - + 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 @@ -95,14 +95,14 @@ int MTDM::process (size_t len, float *ip, float *op) vip = *ip++; for (i = 0, F = _freq; i < 5; i++, F++) { - a = 2 * (float) M_PI * (F->p & 65535) / 65536.0; + a = 2 * (float) M_PI * (F->p & 65535) / 65536.0; F->p += F->f; - c = cosf (a); - s = -sinf (a); + c = cosf (a); + s = -sinf (a); vop += F->a * s; F->xa += s * vip; F->ya += c * vip; - } + } *op++ = vop; if (++_cnt == 16) { @@ -142,10 +142,10 @@ int MTDM::resolve (void) k = (int)(floor (p + 0.5)); e = fabs (p - k); if (e > _err) _err = e; - if (e > 0.4) return 1; + if (e > 0.4) return 1; d += m * (k & 7); m *= 8; - } + } _del = 16 * d; return 0; @@ -158,6 +158,34 @@ static jack_client_t *jack_handle; static jack_port_t *jack_capt; static jack_port_t *jack_play; +jack_latency_range_t capture_latency = {-1, -1}; +jack_latency_range_t playback_latency = {-1, -1}; + +void +latency_cb (jack_latency_callback_mode_t mode, void *arg) +{ + jack_latency_range_t range; + + range.min = range.max = 0; + + if (mode == JackCaptureLatency) { + jack_port_set_latency_range (jack_play, mode, &range); + jack_port_get_latency_range (jack_capt, mode, &range); + if ((range.min != capture_latency.min) || (range.max != capture_latency.max)) { + capture_latency = range; + printf ("new capture latency: [%d, %d]\n", range.min, range.max); + } + } else { + jack_port_set_latency_range (jack_capt, mode, &range); + jack_port_get_latency_range (jack_play, mode, &range); + if ((range.min != playback_latency.min) || (range.max != playback_latency.max)) { + playback_latency = range; + printf ("new playback latency: [%d, %d]\n", range.min, range.max); + } + } + +} + int jack_callback (jack_nframes_t nframes, void *arg) { float *ip, *op; @@ -182,14 +210,12 @@ int main (int ac, char *av []) jack_set_process_callback (jack_handle, jack_callback, 0); + if (jack_set_latency_callback) + jack_set_latency_callback (jack_handle, latency_cb, 0); + jack_capt = jack_port_register (jack_handle, "in", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); jack_play = jack_port_register (jack_handle, "out", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - printf ("capture latency = %d\n", - jack_port_get_latency (jack_port_by_name (jack_handle, "system:capture_1"))); - printf ("playback_latency = %d\n", - jack_port_get_latency (jack_port_by_name (jack_handle, "system:playback_1"))); - t = 1000.0f / jack_get_sample_rate (jack_handle); if (jack_activate (jack_handle)) @@ -200,16 +226,16 @@ int main (int ac, char *av []) while (1) { - - #ifdef WIN32 - Sleep (250); - #else - usleep (250000); - #endif + + #ifdef WIN32 + Sleep (250); + #else + usleep (250000); + #endif if (mtdm.resolve () < 0) printf ("Signal below threshold...\n"); - else + else { - if (mtdm.err () > 0.3) + if (mtdm.err () > 0.3) { mtdm.invert (); mtdm.resolve (); diff --git a/tests/wscript b/tests/wscript index 6693ebad..c5e031fb 100644 --- a/tests/wscript +++ b/tests/wscript @@ -9,7 +9,7 @@ test_programs = { #'testSem': ['testSem.cpp'], 'jack_test': ['test.cpp'], 'jack_cpu': ['cpu.c'], - 'jack_delay': ['jdelay.cpp'], + 'jack_iodelay': ['iodelay.cpp'], 'jack_multiple_metro' : ['external_metro.cpp'], } diff --git a/windows/JackRouter/JackRouter.dsp b/windows/JackRouter/JackRouter.dsp index c92ddf99..f059568e 100644 --- a/windows/JackRouter/JackRouter.dsp +++ b/windows/JackRouter/JackRouter.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\..\..\ASIOSDK2\common" /I "..\..\common" /I "..\..\common\jack" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\..\..\ASIOSDK2\common" /I "..\..\common" /I "..\..\common\jack" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" diff --git a/windows/JackSystemDeps_os.h b/windows/JackSystemDeps_os.h index cf64509e..c74830d0 100644 --- a/windows/JackSystemDeps_os.h +++ b/windows/JackSystemDeps_os.h @@ -23,6 +23,8 @@ #include +#define UINT32_MAX 4294967295U + #define DRIVER_HANDLE HINSTANCE #define LoadDriverModule(name) LoadLibrary((name)) #define UnloadDriverModule(handle) (FreeLibrary(((HMODULE)handle))) diff --git a/windows/JackTypes_os.h b/windows/JackTypes_os.h index 6551378f..35b92644 100644 --- a/windows/JackTypes_os.h +++ b/windows/JackTypes_os.h @@ -1,20 +1,20 @@ /* Copyright (C) 2004-2008 Grame - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + */ @@ -22,11 +22,12 @@ #define __JackTypes_WIN32__ #include -#include "types.h" -typedef ULONGLONG UInt64; +typedef ULONGLONG UInt64; +typedef UInt64 uint64_t; typedef unsigned short uint16_t; -typedef DWORD jack_tls_key; +typedef DWORD jack_tls_key; +typedef HANDLE jack_native_thread_t; #endif diff --git a/windows/JackWinNamedPipeClientChannel.cpp b/windows/JackWinNamedPipeClientChannel.cpp index af390d21..f29f7ff5 100644 --- a/windows/JackWinNamedPipeClientChannel.cpp +++ b/windows/JackWinNamedPipeClientChannel.cpp @@ -1,20 +1,20 @@ /* Copyright (C) 2004-2008 Grame - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + */ @@ -246,14 +246,74 @@ void JackWinNamedPipeClientChannel::SetFreewheel(int onoff, int* result) ServerSyncCall(&req, &res, result); } -void JackWinNamedPipeClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result) +void JackWinNamedPipeClientChannel::ComputeTotalLatencies(int* result) { - JackSessionNotifyRequest req(refnum, target, type, path); + JackComputeTotalLatenciesRequest req; JackResult res; + ServerSyncCall(&req, &res, result); +} + +void JackWinNamedPipeClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result) +{ + JackSessionNotifyRequest req(refnum, path, type, target); + JackSessionNotifyResult res; int intresult; ServerSyncCall(&req, &res, &intresult); - *result = NULL; + jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (res.fCommandList.size() + 1)); + int i = 0; + + for (std::list::iterator ci=res.fCommandList.begin(); ci!=res.fCommandList.end(); ci++) { + session_command[i].uuid = strdup( ci->fUUID ); + session_command[i].client_name = strdup( ci->fClientName ); + session_command[i].command = strdup( ci->fCommand ); + session_command[i].flags = ci->fFlags; + i += 1; + } + + session_command[i].uuid = NULL; + session_command[i].client_name = NULL; + session_command[i].command = NULL; + session_command[i].flags = (jack_session_flags_t)0; + + *result = session_command; +} + +void JackWinNamedPipeClientChannel::SessionReply(int refnum, int* result) +{ + JackSessionReplyRequest req(refnum); + JackResult res; + ServerSyncCall(&req, &res, result); +} + +void JackWinNamedPipeClientChannel::GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) +{ + JackGetUUIDRequest req(client_name); + JackUUIDResult res; + ServerSyncCall(&req, &res, result); + strncpy(uuid_res, res.fUUID, JACK_UUID_SIZE); +} + +void JackWinNamedPipeClientChannel::GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) +{ + JackGetClientNameRequest req(uuid); + JackClientNameResult res; + ServerSyncCall(&req, &res, result); + strncpy(name_res, res.fName, JACK_CLIENT_NAME_SIZE); +} + +void JackWinNamedPipeClientChannel::ClientHasSessionCallback(const char* client_name, int* result) +{ + JackClientHasSessionCallbackRequest req(client_name); + JackResult res; + ServerSyncCall(&req, &res, result); +} + +void JackWinNamedPipeClientChannel::ReserveClientName(int refnum, const char* client_name, const char* uuid, int* result) +{ + JackReserveNameRequest req(refnum, client_name, uuid); + JackResult res; + ServerSyncCall(&req, &res, result); } void JackWinNamedPipeClientChannel::ReleaseTimebase(int refnum, int* result) @@ -312,7 +372,7 @@ bool JackWinNamedPipeClientChannel::Init() jack_error("JackWinNamedPipeClientChannel: cannot establish notification pipe"); return false; } else { - return fClient->Init(); + return true; } } diff --git a/windows/JackWinNamedPipeClientChannel.h b/windows/JackWinNamedPipeClientChannel.h index aa23266b..479e3271 100644 --- a/windows/JackWinNamedPipeClientChannel.h +++ b/windows/JackWinNamedPipeClientChannel.h @@ -81,6 +81,7 @@ class JackWinNamedPipeClientChannel : public detail::JackClientChannelInterface, void SetBufferSize(jack_nframes_t buffer_size, int* result); void SetFreewheel(int onoff, int* result); + void ComputeTotalLatencies(int* result); void ReleaseTimebase(int refnum, int* result); void SetTimebaseCallback(int refnum, int conditional, int* result); @@ -91,10 +92,17 @@ class JackWinNamedPipeClientChannel : public detail::JackClientChannelInterface, void InternalClientUnload(int refnum, int int_ref, int* status, int* result); void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result); + void SessionReply(int refnum, int* result); + void GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result); + void GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result); + void ReserveClientName(int refnum, const char* client_name, const char *uuid, int* result); + void ClientHasSessionCallback(const char* client_name, int* result); // JackRunnableInterface interface bool Init(); bool Execute(); + + bool IsChannelThread() { return fThread.IsThread(); } }; } // end of namespace diff --git a/windows/JackWinNamedPipeServerChannel.cpp b/windows/JackWinNamedPipeServerChannel.cpp index a8093ecb..b4d4d622 100644 --- a/windows/JackWinNamedPipeServerChannel.cpp +++ b/windows/JackWinNamedPipeServerChannel.cpp @@ -252,6 +252,16 @@ bool JackClientPipeThread::HandleRequest() break; } + case JackRequest::kComputeTotalLatencies: { + jack_log("JackRequest::ComputeTotalLatencies"); + JackComputeTotalLatenciesRequest req; + JackResult res; + if (req.Read(fPipe) == 0) + res.fResult = fServer->GetEngine()->ComputeTotalLatencies(); + res.Write(fPipe); + break; + } + case JackRequest::kReleaseTimebase: { jack_log("JackRequest::ReleaseTimebase"); JackReleaseTimebaseRequest req; @@ -345,11 +355,12 @@ bool JackClientPipeThread::HandleRequest() fServer->GetEngine()->SessionReply(req.fRefNum); res.fResult = 0; } + res.Write(fPipe); break; } case JackRequest::kGetClientByUUID: { - jack_log("JackRequest::GetClientNameForUUID"); + jack_log("JackRequest::GetClientByUUID"); JackGetClientNameRequest req; JackClientNameResult res; if (req.Read(fPipe) == 0) { @@ -360,12 +371,11 @@ bool JackClientPipeThread::HandleRequest() } case JackRequest::kGetUUIDByClient: { - jack_log("JackRequest::GetUUIDForClientName"); + jack_log("JackRequest::GetUUIDByClient"); JackGetUUIDRequest req; JackUUIDResult res; if (req.Read(fPipe) == 0) { fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult); - res.fResult = 0; } res.Write(fPipe); break; @@ -377,7 +387,17 @@ bool JackClientPipeThread::HandleRequest() JackResult res; if (req.Read(fPipe) == 0) { fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID, &res.fResult); - res.fResult = 0; + } + res.Write(fPipe); + break; + } + + case JackRequest::kClientHasSessionCallback: { + jack_log("JackRequest::ClientHasSessionCallback"); + JackClientHasSessionCallbackRequest req; + JackResult res; + if (req.Read(fPipe) == 0) { + fServer->GetEngine()->ClientHasSessionCallbackRequest(req.fName, &res.fResult); } res.Write(fPipe); break; diff --git a/windows/JackWinThread.cpp b/windows/JackWinThread.cpp index ec884c45..e3f2cdd9 100644 --- a/windows/JackWinThread.cpp +++ b/windows/JackWinThread.cpp @@ -1,20 +1,20 @@ /* Copyright (C) 2004-2008 Grame - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + */ @@ -30,19 +30,19 @@ DWORD WINAPI JackWinThread::ThreadHandler(void* arg) { JackWinThread* obj = (JackWinThread*)arg; JackRunnableInterface* runnable = obj->fRunnable; - + // Signal creation thread when started with StartSync jack_log("ThreadHandler: start"); obj->fStatus = kIniting; - + // Call Init method if (!runnable->Init()) { jack_error("Thread init fails: thread quits"); return 0; } - + obj->fStatus = kRunning; - + // If Init succeed, start the thread loop bool res = true; while (obj->fStatus == kRunning && res) { @@ -80,11 +80,11 @@ int JackWinThread::Start() return 0; } } - + int JackWinThread::StartSync() { fStatus = kStarting; - + if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { fStatus = kIdle; return -1; @@ -97,7 +97,7 @@ int JackWinThread::StartSync() } } -int JackWinThread::StartImp(pthread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg) +int JackWinThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg) { DWORD id; *thread = CreateThread(NULL, 0, start_routine, arg, 0, &id); @@ -108,7 +108,7 @@ int JackWinThread::StartImp(pthread_t* thread, int priority, int realtime, Threa } if (realtime) { - + jack_log("Create RT thread"); if (!SetThreadPriority(*thread, THREAD_PRIORITY_TIME_CRITICAL)) { jack_error("Cannot set priority class = %d", GetLastError()); @@ -118,7 +118,7 @@ int JackWinThread::StartImp(pthread_t* thread, int priority, int realtime, Threa } else { jack_log("Create non RT thread"); } - + return 0; } @@ -153,7 +153,7 @@ int JackWinThread::Stop() } } -int JackWinThread::KillImp(pthread_t thread) +int JackWinThread::KillImp(jack_native_thread_t thread) { if (thread != (HANDLE)NULL) { // If thread has been started TerminateThread(thread, 0); @@ -165,7 +165,7 @@ int JackWinThread::KillImp(pthread_t thread) } } -int JackWinThread::StopImp(pthread_t thread) +int JackWinThread::StopImp(jack_native_thread_t thread) { if (thread) { // If thread has been started WaitForSingleObject(thread, INFINITE); @@ -198,7 +198,7 @@ int JackWinThread::AcquireSelfRealTime(int priority) return AcquireSelfRealTime(); } -int JackWinThread::AcquireRealTimeImp(pthread_t thread, int priority) +int JackWinThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority) { jack_log("JackWinThread::AcquireRealTime"); @@ -220,7 +220,7 @@ int JackWinThread::DropSelfRealTime() return DropRealTimeImp(GetCurrentThread()); } -int JackWinThread::DropRealTimeImp(pthread_t thread) +int JackWinThread::DropRealTimeImp(jack_native_thread_t thread) { if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) { return 0; @@ -230,7 +230,7 @@ int JackWinThread::DropRealTimeImp(pthread_t thread) } } -pthread_t JackWinThread::GetThreadID() +jack_native_thread_t JackWinThread::GetThreadID() { return fThread; } @@ -262,14 +262,14 @@ bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr) bool jack_tls_allocate_key(jack_tls_key *key_ptr) { DWORD key; - + key = TlsAlloc(); if (key == TLS_OUT_OF_INDEXES) { jack_error("TlsAlloc() failed. Error is %d", (unsigned int)GetLastError()); return false; } - + *key_ptr = key; return true; } @@ -281,7 +281,7 @@ bool jack_tls_free_key(jack_tls_key key) jack_error("TlsFree() failed. Error is %d", (unsigned int)GetLastError()); return false; } - + return true; } @@ -292,7 +292,7 @@ bool jack_tls_set(jack_tls_key key, void *data_ptr) jack_error("TlsSetValue() failed. Error is %d", (unsigned int)GetLastError()); return false; } - + return true; } diff --git a/windows/JackWinThread.h b/windows/JackWinThread.h index 317d6aeb..6861b6fc 100644 --- a/windows/JackWinThread.h +++ b/windows/JackWinThread.h @@ -66,22 +66,22 @@ class SERVER_EXPORT JackWinThread : public detail::JackThreadInterface int DropRealTime(); // Used when called from another thread int DropSelfRealTime(); // Used when called from thread itself - pthread_t GetThreadID(); + jack_native_thread_t GetThreadID(); bool IsThread(); - static int AcquireRealTimeImp(pthread_t thread, int priority); - static int AcquireRealTimeImp(pthread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint) + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority); + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint) { return JackWinThread::AcquireRealTimeImp(thread, priority); } - static int DropRealTimeImp(pthread_t thread); - static int StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg) + static int DropRealTimeImp(jack_native_thread_t thread); + static int StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg) { return JackWinThread::StartImp(thread, priority, realtime, (ThreadCallback) start_routine, arg); } - static int StartImp(pthread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg); - static int StopImp(pthread_t thread); - static int KillImp(pthread_t thread); + static int StartImp(jack_native_thread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg); + static int StopImp(jack_native_thread_t thread); + static int KillImp(jack_native_thread_t thread); }; diff --git a/windows/Setup/JackRouter.dll b/windows/Setup/JackRouter.dll index 04d69ebd..829f6e10 100644 Binary files a/windows/Setup/JackRouter.dll and b/windows/Setup/JackRouter.dll differ diff --git a/windows/jack_latent_client.cbp b/windows/jack_latent_client.cbp new file mode 100644 index 00000000..57cb91b4 --- /dev/null +++ b/windows/jack_latent_client.cbp @@ -0,0 +1,91 @@ + + + + + + diff --git a/windows/jackaudioadapter.rc b/windows/jackaudioadapter.rc index ceb43d62..f9c115f3 100644 --- a/windows/jackaudioadapter.rc +++ b/windows/jackaudioadapter.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp Audio Adapter for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "audioadapter\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "audioadapter.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jackd.rc b/windows/jackd.rc index 4fdf0bb4..f61abc0e 100644 --- a/windows/jackd.rc +++ b/windows/jackd.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jack server for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "jackd\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "jackd.exe\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jackd.workspace b/windows/jackd.workspace index d26dfe36..c94a7a94 100644 --- a/windows/jackd.workspace +++ b/windows/jackd.workspace @@ -20,7 +20,7 @@ - + @@ -36,6 +36,9 @@ + + + diff --git a/windows/jackdummydriver.rc b/windows/jackdummydriver.rc index 2a364608..da787e2e 100644 --- a/windows/jackdummydriver.rc +++ b/windows/jackdummydriver.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp Dummy Driver for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "jack_dummy\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "jack_dummy.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jackloopbackdriver.rc b/windows/jackloopbackdriver.rc index 4249c39d..b4d32b0e 100644 --- a/windows/jackloopbackdriver.rc +++ b/windows/jackloopbackdriver.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp Loopback Driver for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "jack_loopback\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "jack_loopback.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jacknetadapter.rc b/windows/jacknetadapter.rc index e756d2bf..8142ce61 100644 --- a/windows/jacknetadapter.rc +++ b/windows/jacknetadapter.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp Net Adapter for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "netadapter\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "netadapter.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jacknetdriver.rc b/windows/jacknetdriver.rc index dd2228ce..edac06c3 100644 --- a/windows/jacknetdriver.rc +++ b/windows/jacknetdriver.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp Net Driver for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "jack_netdriver\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "jack_netdriver.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jacknetmanager.rc b/windows/jacknetmanager.rc index 9e4701f8..f30dc040 100644 --- a/windows/jacknetmanager.rc +++ b/windows/jacknetmanager.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp Net Manager for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "netmanager\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "netmanager.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jacknetonedriver.rc b/windows/jacknetonedriver.rc index 1dee018a..57518a2d 100644 --- a/windows/jacknetonedriver.rc +++ b/windows/jacknetonedriver.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp NetOne Driver for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "jack_netonedriver\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "jack_netonedriver.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jackportaudio.rc b/windows/jackportaudio.rc index 651d8ec3..d953dbd9 100644 --- a/windows/jackportaudio.rc +++ b/windows/jackportaudio.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp PortAudio Driver for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "jack_portaudio\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "jack_portaudio.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/jackwinmme.rc b/windows/jackwinmme.rc index 509b2715..dfe7bfe2 100644 --- a/windows/jackwinmme.rc +++ b/windows/jackwinmme.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jackmp WinMME Driver for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "jack_portaudio\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "jack_winmme.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/libjack.cbp b/windows/libjack.cbp index 41a71885..02932c57 100644 --- a/windows/libjack.cbp +++ b/windows/libjack.cbp @@ -174,6 +174,9 @@ + + diff --git a/windows/libjack.rc b/windows/libjack.rc index 7e99dfdb..d1aaae1e 100644 --- a/windows/libjack.rc +++ b/windows/libjack.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jack client library for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "libjack\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "libjack.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/libjackserver.rc b/windows/libjackserver.rc index 299d84a6..d0c02280 100644 --- a/windows/libjackserver.rc +++ b/windows/libjackserver.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "Jack server library for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "libjackserver\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "libjackserver.dll\0" VALUE "PrivateBuild", "\0" diff --git a/windows/portaudio/JackPortAudioDriver.h b/windows/portaudio/JackPortAudioDriver.h index a5995cdc..d18da9b8 100644 --- a/windows/portaudio/JackPortAudioDriver.h +++ b/windows/portaudio/JackPortAudioDriver.h @@ -82,6 +82,12 @@ class JackPortAudioDriver : public JackAudioDriver int Read(); int Write(); + // BufferSize can be changed + bool IsFixedBufferSize() + { + return false; + } + int SetBufferSize(jack_nframes_t buffer_size); }; diff --git a/windows/resource.rc b/windows/resource.rc index a0988d1f..65851b24 100644 --- a/windows/resource.rc +++ b/windows/resource.rc @@ -35,7 +35,7 @@ BEGIN VALUE "FileDescription", "Jackmp for Windows\0" VALUE "FileVersion", "1, 9, 7, 0\0" VALUE "InternalName", "libjackmp\0" - VALUE "LegalCopyright", "Copyright Grame © 2006-2010\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "libjackmp.dll\0" VALUE "PrivateBuild", "\0" diff --git a/wscript b/wscript index 12a59563..43ab73a2 100644 --- a/wscript +++ b/wscript @@ -108,8 +108,8 @@ def configure(conf): # conf.check_tool('compiler_cxx') # conf.check_tool('compiler_cc') - conf.env.append_unique('CXXFLAGS', '-O3 -Wall') - conf.env.append_unique('CCFLAGS', '-O3 -Wall') + conf.env.append_unique('CXXFLAGS', '-Wall') + conf.env.append_unique('CCFLAGS', '-Wall') conf.sub_config('common') if conf.env['IS_LINUX']: @@ -129,18 +129,26 @@ def configure(conf): conf.fatal('jackdbus was explicitly requested but cannot be built') conf.sub_config('example-clients') - if conf.check_cfg(package='celt', atleast_version='0.7.0', args='--cflags --libs'): + if conf.check_cfg(package='celt', atleast_version='0.8.0', args='--cflags --libs'): conf.define('HAVE_CELT', 1) + conf.define('HAVE_CELT_API_0_8', 1) + conf.define('HAVE_CELT_API_0_7', 0) + conf.define('HAVE_CELT_API_0_5', 0) + elif conf.check_cfg(package='celt', atleast_version='0.7.0', args='--cflags --libs'): + conf.define('HAVE_CELT', 1) + conf.define('HAVE_CELT_API_0_8', 0) conf.define('HAVE_CELT_API_0_7', 1) conf.define('HAVE_CELT_API_0_5', 0) elif conf.check_cfg(package='celt', atleast_version='0.5.0', args='--cflags --libs', required=True): conf.define('HAVE_CELT', 1) - conf.define('HAVE_CELT_API_0_5', 1) + conf.define('HAVE_CELT_API_0_8', 0) conf.define('HAVE_CELT_API_0_7', 0) + conf.define('HAVE_CELT_API_0_5', 1) else: conf.define('HAVE_CELT', 0) - conf.define('HAVE_CELT_API_0_5', 0) + conf.define('HAVE_CELT_API_0_8', 0) conf.define('HAVE_CELT_API_0_7', 0) + conf.define('HAVE_CELT_API_0_5', 0) conf.env['LIB_PTHREAD'] = ['pthread'] conf.env['LIB_DL'] = ['dl'] @@ -164,7 +172,7 @@ def configure(conf): else: conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib' - if Options.options.libdir: + if Options.options.mandir: conf.env['MANDIR'] = conf.env['PREFIX'] + Options.options.mandir else: conf.env['MANDIR'] = conf.env['PREFIX'] + '/share/man/man1' @@ -198,6 +206,22 @@ def configure(conf): if m != None: svnrev = m.group(1) + conf.env.append_unique('LINKFLAGS', '-lm -lstdc++') + + if Options.options.mixed == True: + env_variant2 = conf.env.copy() + conf.set_env_name('lib32', env_variant2) + env_variant2.set_variant('lib32') + conf.setenv('lib32') + conf.env.append_unique('CXXFLAGS', '-m32') + conf.env.append_unique('CCFLAGS', '-m32') + conf.env.append_unique('LINKFLAGS', '-m32') + if Options.options.libdir32: + conf.env['LIBDIR'] = conf.env['PREFIX'] + Options.options.libdir32 + else: + conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib32' + conf.write_config_header('config.h') + print display_msg("==================") version_msg = "JACK " + VERSION @@ -214,6 +238,9 @@ def configure(conf): display_msg("Library directory", conf.env['LIBDIR'], 'CYAN') display_msg("Drivers directory", conf.env['ADDON_DIR'], 'CYAN') display_feature('Build debuggable binaries', conf.env['BUILD_DEBUG']) + display_msg('C compiler flags', repr(conf.env['CCFLAGS'])) + display_msg('C++ compiler flags', repr(conf.env['CXXFLAGS'])) + display_msg('Linker flags', repr(conf.env['LINKFLAGS'])) display_feature('Build doxygen documentation', conf.env['BUILD_DOXYGEN_DOCS']) display_feature('Build with engine profiling', conf.env['BUILD_WITH_PROFILE']) display_feature('Build with 32/64 bits mixed mode', conf.env['BUILD_WITH_32_64']) @@ -248,22 +275,6 @@ def configure(conf): print Logs.colors.NORMAL, print - conf.env.append_unique('LINKFLAGS', '-lm -lstdc++') - - if Options.options.mixed == True: - env_variant2 = conf.env.copy() - conf.set_env_name('lib32', env_variant2) - env_variant2.set_variant('lib32') - conf.setenv('lib32') - conf.env.append_unique('CXXFLAGS', '-m32') - conf.env.append_unique('CCFLAGS', '-m32') - conf.env.append_unique('LINKFLAGS', '-m32') - if Options.options.libdir32: - conf.env['LIBDIR'] = conf.env['PREFIX'] + Options.options.libdir32 - else: - conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib32' - conf.write_config_header('config.h') - def build(bld): print ("make[1]: Entering directory `" + os.getcwd() + "/" + blddir + "'" ) if not os.access('svnversion.h', os.R_OK):