git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@4181 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
@@ -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 <letz@grame.fr> | |||
* Correct JackNetMaster::SetBufferSize. | |||
2011-03-10 Stephane Letz <letz@grame.fr> | |||
* 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 <letz@grame.fr> | |||
* 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 <letz@grame.fr> | |||
* 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 <letz@grame.fr> | |||
* 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 <letz@grame.fr> | |||
* Remove JackPortIsActive flag. | |||
2011-02-07 Stephane Letz <letz@grame.fr> | |||
* Valerio Pilo second CAS for ARMv7 patch. | |||
2011-02-03 Stephane Letz <letz@grame.fr> | |||
* Valerio Pilo CAS for ARMv7 patch. | |||
2011-01-11 Stephane Letz <letz@grame.fr> | |||
* Adrian Knoth jack_lsp patch. | |||
2010-11-17 Stephane Letz <letz@grame.fr> | |||
* ALSA backend : suspend/resume handling (jack1 r4075). | |||
* Correct dummy driver. | |||
2010-11-05 Stephane Letz <letz@grame.fr> | |||
* 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 <letz@grame.fr> | |||
@@ -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); | |||
} | |||
} |
@@ -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 |
@@ -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 | |||
@@ -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 <string.h> | |||
#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 | |||
@@ -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; | |||
} | |||
}; | |||
@@ -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 <math.h> | |||
#include <string> | |||
#include <algorithm> | |||
@@ -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<jack_port_id_t>::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; | |||
} | |||
@@ -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 <list> | |||
@@ -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<jack_port_id_t> fPortList; | |||
bool fImmediateSessionReply; | |||
int StartThread(); | |||
void SetupDriverSync(bool freewheel); | |||
bool IsActive(); | |||
void CallSyncCallback(); | |||
void CallTimebaseCallback(); | |||