diff options
author | Stephane Letz <letz@grame.fr> | 2011-07-30 10:51:18 +0200 |
---|---|---|
committer | Stephane Letz <letz@grame.fr> | 2011-07-30 10:51:18 +0200 |
commit | 80d316ece46717f3634c5466e499b2d11fceb209 (patch) | |
tree | 8b7b0913274e3cd06202f186b9624b9e9e2092d4 | |
parent | 4e979b964966b6596eb725916f9ff16932e85880 (diff) | |
parent | 7918f1c12abdd8d9328b829a87f9ae3a414344b5 (diff) | |
download | jack2-80d316ece46717f3634c5466e499b2d11fceb209.tar.gz |
Merge branch 'master' into js-dbus
90 files changed, 2358 insertions, 2460 deletions
@@ -35,6 +35,26 @@ Chris Caudle Jackdmp changes log --------------------------- +2011-07-29 Stephane Letz <letz@grame.fr> + + * New JackTimedDriver class to be used by JackDummyDriver, JackNetDriver and JackNetOneDriver classes. + +2011-07-28 Stephane Letz <letz@grame.fr> + + * Enable explicit channel mapping in CoreAudio driver. + +2011-07-25 Stephane Letz <letz@grame.fr> + + * NetJack2: no more timeout, correct JackWaitThreadedDriver::Execute. + +2011-07-25 Stephane Letz <letz@grame.fr> + + * NetJack2: improve latency management, cleanup. + +2011-07-23 Stephane Letz <letz@grame.fr> + + * Possible fix for http://trac.jackaudio.org/ticket/193. + 2011-07-22 Stephane Letz <letz@grame.fr> * NetJack2: improve error reporting. diff --git a/common/JackAPI.cpp b/common/JackAPI.cpp index b05704c4..2680396a 100644 --- a/common/JackAPI.cpp +++ b/common/JackAPI.cpp @@ -127,7 +127,6 @@ extern "C" unsigned long buffer_size); LIB_EXPORT int jack_port_unregister(jack_client_t *, jack_port_t *); LIB_EXPORT void * jack_port_get_buffer(jack_port_t *, jack_nframes_t); - LIB_EXPORT void * jack_port_get_buffer_nulled(jack_port_t *, jack_nframes_t); LIB_EXPORT const char* jack_port_name(const jack_port_t *port); LIB_EXPORT const char* jack_port_short_name(const jack_port_t *port); LIB_EXPORT int jack_port_flags(const jack_port_t *port); @@ -350,22 +349,6 @@ LIB_EXPORT void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t frames) } } -LIB_EXPORT void* jack_port_get_buffer_nulled(jack_port_t* port, jack_nframes_t frames) -{ -#ifdef __CLIENTDEBUG__ - JackGlobals::CheckContext("jack_port_get_buffer_nulled"); -#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_buffer_nulled called with an incorrect port %ld", myport); - return NULL; - } else { - JackGraphManager* manager = GetGraphManager(); - return (manager ? manager->GetBuffer(myport, frames, true) : NULL); - } -} - LIB_EXPORT const char* jack_port_name(const jack_port_t* port) { #ifdef __CLIENTDEBUG__ diff --git a/common/JackAudioAdapter.cpp b/common/JackAudioAdapter.cpp index bf4e5f8c..f1a74fc8 100644 --- a/common/JackAudioAdapter.cpp +++ b/common/JackAudioAdapter.cpp @@ -42,9 +42,12 @@ namespace Jack // Always clear output for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { #ifdef OPTIMIZED_PROTOCOL - inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer_nulled(adapter->fCapturePortList[i], frames); - if (inputBuffer[i]) + inputBuffer[i] = (jack_port_connected(adapter->fCapturePortList[i]) > 0) + ? (jack_default_audio_sample_t*)(adapter->fCapturePortList[i], frames) + : NULL; + if (inputBuffer[i]) { memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t)); + } #else inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames); memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t)); @@ -53,7 +56,9 @@ namespace Jack for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { #ifdef OPTIMIZED_PROTOCOL - outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer_nulled(adapter->fPlaybackPortList[i], frames); + outputBuffer[i] = (jack_port_connected(fAudioCapturePorts[audio_port_index] > 0) + ? (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames) + : NULL; #else outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); #endif diff --git a/common/JackAudioDriver.cpp b/common/JackAudioDriver.cpp index 8d65ebad..9d0cda32 100644 --- a/common/JackAudioDriver.cpp +++ b/common/JackAudioDriver.cpp @@ -215,23 +215,6 @@ int JackAudioDriver::Write() return 0; } -int JackAudioDriver::ProcessNull() -{ - // Keep begin cycle time - JackDriver::CycleTakeBeginTime(); - - if (fEngineControl->fSyncMode) { - ProcessGraphSyncMaster(); - } else { - ProcessGraphAsyncMaster(); - } - - // Keep end cycle time - JackDriver::CycleTakeEndTime(); - WaitUntilNextCycle(); - return 0; -} - int JackAudioDriver::Process() { return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); @@ -284,13 +267,13 @@ int JackAudioDriver::ProcessSync() // Process graph if (fIsMaster) { if (ProcessGraphSyncMaster() < 0) { - jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); - goto end; + //jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); + //goto end; } } else { if (ProcessGraphSyncSlave() < 0) { - jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); - goto end; + //jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); + //goto end; } } @@ -388,6 +371,7 @@ int JackAudioDriver::Stop() return res; } +/* void JackAudioDriver::WaitUntilNextCycle() { int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f)); @@ -395,6 +379,7 @@ void JackAudioDriver::WaitUntilNextCycle() if (wait_time_usec > 0) JackSleep(wait_time_usec); } +*/ jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index, bool nulled) { diff --git a/common/JackAudioDriver.h b/common/JackAudioDriver.h index bb9c1b9f..42ccb22d 100644 --- a/common/JackAudioDriver.h +++ b/common/JackAudioDriver.h @@ -41,8 +41,6 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver int ProcessGraphSyncMaster(); int ProcessGraphSyncSlave(); - void WaitUntilNextCycle(); - virtual int ProcessAsync(); virtual int ProcessSync(); @@ -94,7 +92,6 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver jack_nframes_t playback_latency); virtual int Process(); - virtual int ProcessNull(); virtual int Attach(); virtual int Detach(); diff --git a/common/JackChannel.h b/common/JackChannel.h index 69d25e00..5979ba8e 100644 --- a/common/JackChannel.h +++ b/common/JackChannel.h @@ -74,7 +74,7 @@ class JackClientChannelInterface return -1; } - virtual void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) + virtual void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) {} virtual void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result) {} diff --git a/common/JackClient.cpp b/common/JackClient.cpp index 121e7f91..639adfe8 100644 --- a/common/JackClient.cpp +++ b/common/JackClient.cpp @@ -151,6 +151,8 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, { int res = 0; + jack_log("JackClient::ClientNotify ref = %ld name = %s notify = %ld", refnum, name, notify); + // Done all time: redirected on subclass implementation JackLibClient and JackInternalClient switch (notify) { diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp index 2329ce80..6c359cde 100644 --- a/common/JackControlAPI.cpp +++ b/common/JackControlAPI.cpp @@ -486,7 +486,7 @@ do_nothing_handler(int sig) snprintf (buf, sizeof(buf), "received signal %d during shutdown (ignored)\n", sig); } -LIB_EXPORT sigset_t +SERVER_EXPORT sigset_t jackctl_setup_signals( unsigned int flags) { @@ -564,7 +564,7 @@ jackctl_setup_signals( return signals; } -LIB_EXPORT void +SERVER_EXPORT void jackctl_wait_signals(sigset_t signals) { int sig; @@ -631,7 +631,7 @@ get_realtime_priority_constraint() return constraint_ptr; } -LIB_EXPORT jackctl_server_t * jackctl_server_create( +SERVER_EXPORT jackctl_server_t * jackctl_server_create( bool (* on_device_acquire)(const char * device_name), void (* on_device_release)(const char * device_name)) { @@ -813,7 +813,7 @@ fail: return NULL; } -LIB_EXPORT void jackctl_server_destroy(jackctl_server *server_ptr) +SERVER_EXPORT void jackctl_server_destroy(jackctl_server *server_ptr) { jackctl_server_free_drivers(server_ptr); jackctl_server_free_internals(server_ptr); @@ -821,18 +821,18 @@ LIB_EXPORT void jackctl_server_destroy(jackctl_server *server_ptr) free(server_ptr); } -LIB_EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr) +SERVER_EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr) { return server_ptr->drivers; } -LIB_EXPORT bool jackctl_server_stop(jackctl_server *server_ptr) +SERVER_EXPORT bool jackctl_server_stop(jackctl_server *server_ptr) { server_ptr->engine->Stop(); return true; } -LIB_EXPORT bool jackctl_server_close(jackctl_server *server_ptr) +SERVER_EXPORT bool jackctl_server_close(jackctl_server *server_ptr) { server_ptr->engine->Close(); delete server_ptr->engine; @@ -855,12 +855,12 @@ LIB_EXPORT bool jackctl_server_close(jackctl_server *server_ptr) return true; } -LIB_EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr) +SERVER_EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr) { return server_ptr->parameters; } -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_server_open( jackctl_server *server_ptr, jackctl_driver *driver_ptr) @@ -944,7 +944,7 @@ fail: return false; } -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_server_start( jackctl_server *server_ptr) { @@ -957,47 +957,47 @@ jackctl_server_start( return result; } -LIB_EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr) +SERVER_EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr) { return driver_ptr->desc_ptr->name; } -LIB_EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr) +SERVER_EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr) { return driver_ptr->parameters; } -LIB_EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr) +SERVER_EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr) { return driver_ptr->desc_ptr; } -LIB_EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr) +SERVER_EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr) { return parameter_ptr->name; } -LIB_EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr) +SERVER_EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr) { return parameter_ptr->short_description; } -LIB_EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr) +SERVER_EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr) { return parameter_ptr->long_description; } -LIB_EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr) +SERVER_EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr) { return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0; } -LIB_EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr) +SERVER_EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr) { return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0; } -LIB_EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr) +SERVER_EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr) { if (!jackctl_parameter_has_enum_constraint(parameter_ptr)) { @@ -1007,7 +1007,7 @@ LIB_EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_paramet return parameter_ptr->constraint_ptr->constraint.enumeration.count; } -LIB_EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index) +SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index) { jack_driver_param_value_t * value_ptr; union jackctl_parameter_value jackctl_value; @@ -1036,12 +1036,12 @@ LIB_EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_v return jackctl_value; } -LIB_EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index) +SERVER_EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index) { return parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc; } -LIB_EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr) +SERVER_EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr) { switch (parameter_ptr->type) { @@ -1059,37 +1059,37 @@ LIB_EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parame } } -LIB_EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr) +SERVER_EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr) { return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0; } -LIB_EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr) +SERVER_EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr) { return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0; } -LIB_EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr) +SERVER_EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr) { return parameter_ptr->type; } -LIB_EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr) +SERVER_EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr) { return parameter_ptr->id; } -LIB_EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr) +SERVER_EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr) { return parameter_ptr->is_set; } -LIB_EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr) +SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr) { return *parameter_ptr->value_ptr; } -LIB_EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr) +SERVER_EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr) { if (!parameter_ptr->is_set) { @@ -1103,7 +1103,7 @@ LIB_EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr) return true; } -LIB_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr) +SERVER_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr) { bool new_driver_parameter; @@ -1162,29 +1162,29 @@ LIB_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, co return true; } -LIB_EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr) +SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr) { return *parameter_ptr->default_value_ptr; } // Internals clients -LIB_EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr) +SERVER_EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr) { return server_ptr->internals; } -LIB_EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr) +SERVER_EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr) { return internal_ptr->desc_ptr->name; } -LIB_EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr) +SERVER_EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr) { return internal_ptr->parameters; } -LIB_EXPORT bool jackctl_server_load_internal( +SERVER_EXPORT bool jackctl_server_load_internal( jackctl_server * server_ptr, jackctl_internal * internal) { @@ -1197,7 +1197,7 @@ LIB_EXPORT bool jackctl_server_load_internal( } } -LIB_EXPORT bool jackctl_server_unload_internal( +SERVER_EXPORT bool jackctl_server_unload_internal( jackctl_server * server_ptr, jackctl_internal * internal) { @@ -1210,7 +1210,7 @@ LIB_EXPORT bool jackctl_server_unload_internal( } } -LIB_EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) +SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) { if (server_ptr->engine != NULL) { if (server_ptr->engine->IsRunning()) { @@ -1230,7 +1230,7 @@ LIB_EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_dr } } -LIB_EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) +SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) { if (server_ptr->engine != NULL) { if (server_ptr->engine->IsRunning()) { @@ -1253,7 +1253,7 @@ LIB_EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl } } -LIB_EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr) +SERVER_EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr) { if (server_ptr->engine != NULL) { return (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, driver_ptr->set_parameters) == 0); diff --git a/common/JackControlAPI.h b/common/JackControlAPI.h index b3462880..8011f9ba 100644 --- a/common/JackControlAPI.h +++ b/common/JackControlAPI.h @@ -80,164 +80,164 @@ extern "C" { } /* Adjust editor indent */ #endif -LIB_EXPORT sigset_t +SERVER_EXPORT sigset_t jackctl_setup_signals( unsigned int flags); -LIB_EXPORT void +SERVER_EXPORT void jackctl_wait_signals( sigset_t signals); -LIB_EXPORT jackctl_server_t * +SERVER_EXPORT jackctl_server_t * jackctl_server_create( bool (* on_device_acquire)(const char * device_name), void (* on_device_release)(const char * device_name)); -LIB_EXPORT void +SERVER_EXPORT void jackctl_server_destroy( jackctl_server_t * server); -LIB_EXPORT const JSList * +SERVER_EXPORT const JSList * jackctl_server_get_drivers_list( jackctl_server_t * server); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_server_open( jackctl_server_t * server, jackctl_driver_t * driver); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_server_start( jackctl_server_t * server); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_server_stop( jackctl_server_t * server); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_server_close( jackctl_server_t * server); -LIB_EXPORT const JSList * +SERVER_EXPORT const JSList * jackctl_server_get_parameters( jackctl_server_t * server); -LIB_EXPORT const char * +SERVER_EXPORT const char * jackctl_driver_get_name( jackctl_driver_t * driver); -LIB_EXPORT const JSList * +SERVER_EXPORT const JSList * jackctl_driver_get_parameters( jackctl_driver_t * driver); -LIB_EXPORT const char * +SERVER_EXPORT const char * jackctl_parameter_get_name( jackctl_parameter_t * parameter); -LIB_EXPORT const char * +SERVER_EXPORT const char * jackctl_parameter_get_short_description( jackctl_parameter_t * parameter); -LIB_EXPORT const char * +SERVER_EXPORT const char * jackctl_parameter_get_long_description( jackctl_parameter_t * parameter); -LIB_EXPORT jackctl_param_type_t +SERVER_EXPORT jackctl_param_type_t jackctl_parameter_get_type( jackctl_parameter_t * parameter); -LIB_EXPORT char +SERVER_EXPORT char jackctl_parameter_get_id( jackctl_parameter_t * parameter); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_parameter_is_set( jackctl_parameter_t * parameter); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_parameter_reset( jackctl_parameter_t * parameter); -LIB_EXPORT union jackctl_parameter_value +SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_value( jackctl_parameter_t * parameter); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_parameter_set_value( jackctl_parameter_t * parameter, const union jackctl_parameter_value * value_ptr); -LIB_EXPORT union jackctl_parameter_value +SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value( jackctl_parameter_t * parameter); -LIB_EXPORT union jackctl_parameter_value +SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value( jackctl_parameter *parameter_ptr); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_parameter_has_range_constraint( jackctl_parameter_t * parameter_ptr); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_parameter_has_enum_constraint( jackctl_parameter_t * parameter_ptr); -LIB_EXPORT uint32_t +SERVER_EXPORT uint32_t jackctl_parameter_get_enum_constraints_count( jackctl_parameter_t * parameter_ptr); -LIB_EXPORT union jackctl_parameter_value +SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value( jackctl_parameter_t * parameter_ptr, uint32_t index); -LIB_EXPORT const char * +SERVER_EXPORT const char * jackctl_parameter_get_enum_constraint_description( jackctl_parameter_t * parameter_ptr, uint32_t index); -LIB_EXPORT void +SERVER_EXPORT void jackctl_parameter_get_range_constraint( jackctl_parameter_t * parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_parameter_constraint_is_strict( jackctl_parameter_t * parameter_ptr); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_parameter_constraint_is_fake_value( jackctl_parameter_t * parameter_ptr); -LIB_EXPORT const JSList * +SERVER_EXPORT const JSList * jackctl_server_get_internals_list( jackctl_server *server_ptr); -LIB_EXPORT const char * +SERVER_EXPORT const char * jackctl_internal_get_name( jackctl_internal *internal_ptr); -LIB_EXPORT const JSList * +SERVER_EXPORT const JSList * jackctl_internal_get_parameters( jackctl_internal *internal_ptr); -LIB_EXPORT bool jackctl_server_load_internal( +SERVER_EXPORT bool jackctl_server_load_internal( jackctl_server * server, jackctl_internal * internal); -LIB_EXPORT bool jackctl_server_unload_internal( +SERVER_EXPORT bool jackctl_server_unload_internal( jackctl_server * server, jackctl_internal * internal); -LIB_EXPORT bool jackctl_server_add_slave(jackctl_server_t * server, +SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server_t * server, jackctl_driver_t * driver); -LIB_EXPORT bool jackctl_server_remove_slave(jackctl_server_t * server, +SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server_t * server, jackctl_driver_t * driver); -LIB_EXPORT bool +SERVER_EXPORT bool jackctl_server_switch_master(jackctl_server_t * server, jackctl_driver_t * driver); diff --git a/common/JackDebugClient.h b/common/JackDebugClient.h index 465d9465..f781b075 100644 --- a/common/JackDebugClient.h +++ b/common/JackDebugClient.h @@ -46,7 +46,7 @@ PortFollower; \brief A "decorator" debug client to validate API use. */ -class SERVER_EXPORT JackDebugClient : public JackClient +class LIB_EXPORT JackDebugClient : public JackClient { protected: diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index e424ce28..b81cdb48 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -217,6 +217,8 @@ void JackDriver::SetupDriverSync(int ref, bool freewheel) int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) { + jack_log("JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify); + switch (notify) { case kStartFreewheelCallback: @@ -228,7 +230,7 @@ int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, jack_log("JackDriver::kStopFreewheel"); SetupDriverSync(fClientControl.fRefNum, false); break; - } + } return 0; } @@ -342,11 +344,6 @@ int JackDriver::Process() return 0; } -int JackDriver::ProcessNull() -{ - return 0; -} - int JackDriver::Attach() { return 0; diff --git a/common/JackDriver.h b/common/JackDriver.h index 45d695af..3bda602d 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -53,14 +53,14 @@ class SERVER_EXPORT JackDriverInterface virtual int Open() = 0; virtual int Open (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) = 0; + 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) = 0; virtual int Open(jack_nframes_t buffer_size, jack_nframes_t samplerate, @@ -88,7 +88,6 @@ class SERVER_EXPORT JackDriverInterface 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; @@ -176,14 +175,14 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface virtual int Open(); virtual int Open (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); + 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); virtual int Open(jack_nframes_t buffer_size, jack_nframes_t samplerate, @@ -199,8 +198,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface virtual int Close(); virtual int Process(); - virtual int ProcessNull(); - + virtual int Attach(); virtual int Detach(); diff --git a/common/JackDriverLoader.cpp b/common/JackDriverLoader.cpp index ec6053f6..5c5b3283 100644 --- a/common/JackDriverLoader.cpp +++ b/common/JackDriverLoader.cpp @@ -88,7 +88,7 @@ SERVER_EXPORT void jack_free_driver_params(JSList * driver_params) } } -LIB_EXPORT int +SERVER_EXPORT int jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr) { struct option * long_options; @@ -173,10 +173,10 @@ jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSLi if (optarg) { switch (desc->params[param_index].type) { case JackDriverParamInt: - driver_param->value.i = atoi (optarg); + driver_param->value.i = atoi(optarg); break; case JackDriverParamUInt: - driver_param->value.ui = strtoul (optarg, NULL, 10); + driver_param->value.ui = strtoul(optarg, NULL, 10); break; case JackDriverParamChar: driver_param->value.c = optarg[0]; @@ -185,20 +185,11 @@ jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSLi strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX); break; case JackDriverParamBool: - - /* - if (strcasecmp ("false", optarg) == 0 || - strcasecmp ("off", optarg) == 0 || - strcasecmp ("no", optarg) == 0 || - strcasecmp ("0", optarg) == 0 || - strcasecmp ("(null)", optarg) == 0 ) { - */ - // steph - if (strcmp ("false", optarg) == 0 || - strcmp ("off", optarg) == 0 || - strcmp ("no", optarg) == 0 || - strcmp ("0", optarg) == 0 || - strcmp ("(null)", optarg) == 0 ) { + if (strcasecmp("false", optarg) == 0 || + strcasecmp("off", optarg) == 0 || + strcasecmp("no", optarg) == 0 || + strcasecmp("0", optarg) == 0 || + strcasecmp("(null)", optarg) == 0 ) { driver_param->value.i = false; } else { @@ -317,11 +308,11 @@ jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[]) if (optarg) { switch (jackctl_parameter_get_type(param)) { case JackDriverParamInt: - value.i = atoi (optarg); + value.i = atoi(optarg); jackctl_parameter_set_value(param, &value); break; case JackDriverParamUInt: - value.ui = strtoul (optarg, NULL, 10); + value.ui = strtoul(optarg, NULL, 10); jackctl_parameter_set_value(param, &value); break; case JackDriverParamChar: @@ -329,23 +320,15 @@ jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[]) jackctl_parameter_set_value(param, &value); break; case JackDriverParamString: - strncpy (value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX); + strncpy(value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX); jackctl_parameter_set_value(param, &value); break; case JackDriverParamBool: - /* - if (strcasecmp ("false", optarg) == 0 || - strcasecmp ("off", optarg) == 0 || - strcasecmp ("no", optarg) == 0 || - strcasecmp ("0", optarg) == 0 || - strcasecmp ("(null)", optarg) == 0 ) { - */ - // steph - if (strcmp ("false", optarg) == 0 || - strcmp ("off", optarg) == 0 || - strcmp ("no", optarg) == 0 || - strcmp ("0", optarg) == 0 || - strcmp ("(null)", optarg) == 0 ) { + if (strcasecmp("false", optarg) == 0 || + strcasecmp("off", optarg) == 0 || + strcasecmp("no", optarg) == 0 || + strcasecmp("0", optarg) == 0 || + strcasecmp("(null)", optarg) == 0 ) { value.i = false; } else { value.i = true; @@ -835,7 +818,7 @@ JackDriverInfo::~JackDriverInfo() UnloadDriverModule(fHandle); } -LIB_EXPORT +SERVER_EXPORT jack_driver_desc_t * jack_driver_descriptor_construct( const char * name, @@ -873,7 +856,7 @@ jack_driver_descriptor_construct( return desc_ptr; } -LIB_EXPORT +SERVER_EXPORT int jack_driver_descriptor_add_parameter( jack_driver_desc_t * desc_ptr, diff --git a/common/JackDummyDriver.cpp b/common/JackDummyDriver.cpp index 72d1b4d0..184499b8 100644 --- a/common/JackDummyDriver.cpp +++ b/common/JackDummyDriver.cpp @@ -19,8 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "JackDummyDriver.h" -#include "JackEngineControl.h" -#include "JackGraphManager.h" #include "JackDriverLoader.h" #include "JackThreadedDriver.h" #include "JackCompilerDeps.h" @@ -28,61 +26,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include <unistd.h> #include <math.h> -namespace Jack -{ - -int JackDummyDriver::Open(jack_nframes_t buffer_size, - jack_nframes_t samplerate, - 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) -{ - if (JackAudioDriver::Open(buffer_size, - samplerate, - capturing, - playing, - inchannels, - outchannels, - monitor, - capture_driver_name, - playback_driver_name, - capture_latency, - playback_latency) == 0) { - int buffer_size = lroundf((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; - } -} - -int JackDummyDriver::Process() -{ - JackDriver::CycleTakeBeginTime(); - JackAudioDriver::Process(); - JackSleep(std::max(0L, long(fWaitTime - (GetMicroSeconds() - fBeginDateUst)))); - return 0; -} - -int JackDummyDriver::SetBufferSize(jack_nframes_t buffer_size) -{ - // Generic change, never fails - JackAudioDriver::SetBufferSize(buffer_size); - fWaitTime = (unsigned long)((((float)buffer_size) / ((float)fEngineControl->fSampleRate)) * 1000000.0f); - return 0; -} - -} // end of namespace #ifdef __cplusplus extern "C" @@ -117,10 +60,10 @@ extern "C" SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) { jack_nframes_t sample_rate = 48000; - jack_nframes_t period_size = 1024; + jack_nframes_t buffer_size = 1024; unsigned int capture_ports = 2; unsigned int playback_ports = 2; - unsigned long wait_time = 0; + int wait_time = 0; const JSList * node; const jack_driver_param_t * param; bool monitor = false; @@ -143,7 +86,7 @@ extern "C" break; case 'p': - period_size = param->value.ui; + buffer_size = param->value.ui; break; case 'w': @@ -156,11 +99,16 @@ extern "C" } } - if (wait_time == 0) // Not set - wait_time = (unsigned long)((((float)period_size) / ((float)sample_rate)) * 1000000.0f); - - Jack::JackDriverClientInterface* driver = new Jack::JackThreadedDriver(new Jack::JackDummyDriver("system", "dummy_pcm", engine, table, wait_time)); - if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports, monitor, "dummy", "dummy", 0, 0) == 0) { + if (wait_time > 0) { + buffer_size = lroundf((wait_time * sample_rate) / 1000000.0f); + if (buffer_size > BUFFER_SIZE_MAX) { + buffer_size = BUFFER_SIZE_MAX; + jack_error("Buffer size set to %d", BUFFER_SIZE_MAX); + } + } + + Jack::JackDriverClientInterface* driver = new Jack::JackThreadedDriver(new Jack::JackDummyDriver("system", "dummy_pcm", engine, table)); + if (driver->Open(buffer_size, sample_rate, 1, 1, capture_ports, playback_ports, monitor, "dummy", "dummy", 0, 0) == 0) { return driver; } else { delete driver; diff --git a/common/JackDummyDriver.h b/common/JackDummyDriver.h index cfd6b474..284b026b 100644 --- a/common/JackDummyDriver.h +++ b/common/JackDummyDriver.h @@ -21,7 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __JackDummyDriver__ #define __JackDummyDriver__ -#include "JackAudioDriver.h" +#include "JackTimedDriver.h" namespace Jack { @@ -30,42 +30,17 @@ namespace Jack \brief The dummy driver. */ -class JackDummyDriver : public JackAudioDriver +class JackDummyDriver : public JackTimedDriver { - private: - - long fWaitTime; - + public: - JackDummyDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, unsigned long wait_time) - : JackAudioDriver(name, alias, engine, table), fWaitTime(wait_time) + JackDummyDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) + : JackTimedDriver(name, alias, engine, table) {} virtual ~JackDummyDriver() {} - int Open(jack_nframes_t buffersize, - jack_nframes_t samplerate, - bool capturing, - bool playing, - int chan_in, - int chan_out, - bool monitor, - const char* capture_driver_name, - const char* playback_driver_name, - jack_nframes_t capture_latency, - jack_nframes_t playback_latency); - - int Process(); - - // BufferSize can be changed - bool IsFixedBufferSize() - { - return false; - } - - int SetBufferSize(jack_nframes_t buffer_size); - }; } // end of namespace diff --git a/common/JackEngine.cpp b/common/JackEngine.cpp index ff991fde..e4342f81 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -140,7 +140,6 @@ 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 fChannel.Notify(ALL_CLIENTS, kGraphOrderCallback, 0); - //NotifyGraphReorder(); } fSignal.Signal(); // Signal for threads waiting for next cycle } @@ -198,13 +197,11 @@ 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); } } } @@ -275,10 +272,10 @@ int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* nam // Notify existing clients of the new client and new client of existing clients. for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* old_client = fClientTable[i]; - if (old_client) { + if (old_client && old_client != new_client) { if (old_client->ClientNotify(refnum, name, kAddClient, true, "", 0, 0) < 0) { jack_error("NotifyAddClient old_client fails name = %s", old_client->GetClientControl()->fName); - return -1; + // Not considered as a failure... } if (new_client->ClientNotify(i, old_client->GetClientControl()->fName, kAddClient, true, "", 0, 0) < 0) { jack_error("NotifyAddClient new_client fails name = %s", name); @@ -296,7 +293,7 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum) for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client) { - client->ClientNotify(refnum, name, kRemoveClient, true, "",0, 0); + client->ClientNotify(refnum, name, kRemoveClient, true, "", 0, 0); } } } @@ -307,7 +304,6 @@ 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) @@ -427,7 +423,7 @@ int JackEngine::ClientCheck(const char* name, int uuid, char* name_res, int prot *status = 0; strcpy(name_res, name); - jack_log("Check protocol client %ld server = %ld", protocol, JACK_PROTOCOL_VERSION); + jack_log("Check protocol client = %ld server = %ld", protocol, JACK_PROTOCOL_VERSION); if (protocol != JACK_PROTOCOL_VERSION) { *status |= (JackFailure | JackVersionError); @@ -563,7 +559,6 @@ int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref } else { strncpy(real_name, name, JACK_CLIENT_NAME_SIZE); } - EnsureUUID(uuid); } @@ -686,12 +681,12 @@ int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wai int i; fGraphManager->GetInputPorts(refnum, ports); - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) { + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) { PortUnRegister(refnum, ports[i]); } fGraphManager->GetOutputPorts(refnum, ports); - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) { + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) { PortUnRegister(refnum, ports[i]); } diff --git a/common/JackExternalClient.cpp b/common/JackExternalClient.cpp index 54342f97..5fd1b60f 100644 --- a/common/JackExternalClient.cpp +++ b/common/JackExternalClient.cpp @@ -36,7 +36,7 @@ JackExternalClient::~JackExternalClient() int JackExternalClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) { int result = -1; - jack_log("JackExternalClient::ClientNotify ref = %ld name = %s notify = %ld", refnum, name, notify); + jack_log("JackExternalClient::ClientNotify ref = %ld client = %s name = %s notify = %ld", refnum, fClientControl->fName, name, notify); fChannel.ClientNotify(refnum, name, notify, sync, message, value1, value2, &result); return result; } @@ -49,17 +49,17 @@ int JackExternalClient::Open(const char* name, int pid, int refnum, int uuid, in jack_error("Cannot connect to client name = %s\n", name); return -1; } - + // Use "placement new" to allocate object in shared memory JackShmMemAble* shared_mem = static_cast<JackShmMemAble*>(JackShmMem::operator new(sizeof(JackClientControl))); shared_mem->Init(); fClientControl = new(shared_mem) JackClientControl(name, pid, refnum, uuid); - + if (!fClientControl) { jack_error("Cannot allocate client shared memory segment"); return -1; } - + *shared_client = shared_mem->GetShmIndex(); jack_log("JackExternalClient::Open name = %s index = %ld base = %x", name, shared_mem->GetShmIndex(), shared_mem->GetShmAddress()); return 0; diff --git a/common/JackExternalClient.h b/common/JackExternalClient.h index c7c7fc42..19318a33 100644 --- a/common/JackExternalClient.h +++ b/common/JackExternalClient.h @@ -38,8 +38,8 @@ class JackExternalClient : public JackClientInterface private: - JackNotifyChannel fChannel; /*! Server/client communication channel */ - JackClientControl* fClientControl; /*! Client control in shared memory */ + JackNotifyChannel fChannel; /*! Server/client communication channel */ + JackClientControl* fClientControl; /*! Client control in shared memory */ public: diff --git a/common/JackGlobals.h b/common/JackGlobals.h index 75c9b030..36d73c38 100644 --- a/common/JackGlobals.h +++ b/common/JackGlobals.h @@ -53,9 +53,9 @@ struct JackGlobals { }; // Each "side" server and client will implement this to get the shared graph manager, engine control and inter-process synchro table. -extern LIB_EXPORT JackGraphManager* GetGraphManager(); -extern LIB_EXPORT JackEngineControl* GetEngineControl(); -extern LIB_EXPORT JackSynchro* GetSynchroTable(); +extern SERVER_EXPORT JackGraphManager* GetGraphManager(); +extern SERVER_EXPORT JackEngineControl* GetEngineControl(); +extern SERVER_EXPORT JackSynchro* GetSynchroTable(); } // end of namespace diff --git a/common/JackInternalClient.cpp b/common/JackInternalClient.cpp index 9645f9d3..12d0c671 100644 --- a/common/JackInternalClient.cpp +++ b/common/JackInternalClient.cpp @@ -38,17 +38,17 @@ JackGraphManager* JackInternalClient::fGraphManager = NULL; JackEngineControl* JackInternalClient::fEngineControl = NULL; // Used for external C API (JackAPI.cpp) -LIB_EXPORT JackGraphManager* GetGraphManager() +SERVER_EXPORT JackGraphManager* GetGraphManager() { return JackServerGlobals::fInstance->GetGraphManager(); } -LIB_EXPORT JackEngineControl* GetEngineControl() +SERVER_EXPORT JackEngineControl* GetEngineControl() { return JackServerGlobals::fInstance->GetEngineControl(); } -LIB_EXPORT JackSynchro* GetSynchroTable() +SERVER_EXPORT JackSynchro* GetSynchroTable() { return JackServerGlobals::fInstance->GetSynchroTable(); } @@ -71,13 +71,14 @@ int JackInternalClient::Open(const char* server_name, const char* name, int uuid strncpy(fServerName, server_name, sizeof(fServerName)); - fChannel->ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); + fChannel->ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, false); if (result < 0) { int status1 = *status; - if (status1 & JackVersionError) + if (status1 & JackVersionError) { jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION); - else + } else { jack_error("Client name = %s conflits with another running client", name); + } goto error; } diff --git a/common/JackInternalClientChannel.h b/common/JackInternalClientChannel.h index 650b0ccc..69588a99 100644 --- a/common/JackInternalClientChannel.h +++ b/common/JackInternalClientChannel.h @@ -50,7 +50,7 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface return 0; } - void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) + void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) { *result = fEngine->ClientCheck(name, uuid, name_res, protocol, options, status); } diff --git a/common/JackLibAPI.cpp b/common/JackLibAPI.cpp index 403ce5d2..e0d83e76 100644 --- a/common/JackLibAPI.cpp +++ b/common/JackLibAPI.cpp @@ -42,6 +42,7 @@ extern "C" jack_client_t * jack_client_open_aux (const char *client_name, jack_options_t options, jack_status_t *status, va_list ap); + LIB_EXPORT jack_client_t * jack_client_open (const char *client_name, jack_options_t options, jack_status_t *status, ...); diff --git a/common/JackLibClient.cpp b/common/JackLibClient.cpp index 2b54aa16..4ba58c9c 100644 --- a/common/JackLibClient.cpp +++ b/common/JackLibClient.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. */ @@ -100,22 +100,19 @@ int JackLibClient::Open(const char* server_name, const char* name, int uuid, jac JackLibGlobals::fGlobals->fGraphManager.SetShmIndex(shared_graph, fServerName); fClientControl.SetShmIndex(shared_client, fServerName); JackGlobals::fVerbose = GetEngineControl()->fVerbose; - } catch (int n) { - jack_error("Map shared memory segments exception %d", n); - goto error; } catch (...) { - jack_error("Unknown error..."); + jack_error("Map shared memory segments exception"); goto error; } SetupDriverSync(false); - + // Connect shared synchro : the synchro must be usable in I/O mode when several clients live in the same process if (!fSynchroTable[GetClientControl()->fRefNum].Connect(name_res, fServerName)) { jack_error("Cannot ConnectSemaphore %s client", name_res); goto error; } - + JackGlobals::fClientTable[GetClientControl()->fRefNum] = this; JackGlobals::fServerRunning = true; SetClockSource(GetEngineControl()->fClockSource); @@ -146,7 +143,7 @@ int JackLibClient::ClientNotifyImp(int refnum, const char* name, int notify, int case kRemoveClient: jack_log("JackClient::RemoveClient name = %s, ref = %ld ", name, refnum); - if (strcmp(GetClientControl()->fName, name) != 0) + if (GetClientControl() && strcmp(GetClientControl()->fName, name) != 0) res = fSynchroTable[refnum].Disconnect() ? 0 : -1; break; } diff --git a/common/JackLibClient.h b/common/JackLibClient.h index ef07581c..000c9aa6 100644 --- a/common/JackLibClient.h +++ b/common/JackLibClient.h @@ -32,7 +32,7 @@ namespace Jack \brief Client on the library side. */ -class SERVER_EXPORT JackLibClient : public JackClient +class LIB_EXPORT JackLibClient : public JackClient { private: diff --git a/common/JackLibGlobals.h b/common/JackLibGlobals.h index a2f87ed1..be36cb47 100644 --- a/common/JackLibGlobals.h +++ b/common/JackLibGlobals.h @@ -50,7 +50,7 @@ class JackClient; \brief Global library static structure: singleton kind of pattern. */ -struct SERVER_EXPORT JackLibGlobals +struct LIB_EXPORT JackLibGlobals { JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */ JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable diff --git a/common/JackMidiAPI.cpp b/common/JackMidiAPI.cpp index 4e574394..c462cece 100644 --- a/common/JackMidiAPI.cpp +++ b/common/JackMidiAPI.cpp @@ -57,8 +57,9 @@ LIB_EXPORT jack_nframes_t jack_midi_get_event_count(void* port_buffer) { JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer; - if (!buf || !buf->IsValid()) + if (!buf || !buf->IsValid()) { return 0; + } return buf->event_count; } @@ -66,10 +67,12 @@ LIB_EXPORT int jack_midi_event_get(jack_midi_event_t *event, void* port_buffer, jack_nframes_t event_index) { JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer; - if (!buf || !buf->IsValid()) + if (!buf || !buf->IsValid()) { return -EINVAL; - if (event_index >= buf->event_count) + } + if (event_index >= buf->event_count) { return -ENOBUFS; + } JackMidiEvent* ev = &buf->events[event_index]; event->time = ev->time; event->size = ev->size; @@ -81,8 +84,9 @@ LIB_EXPORT void jack_midi_clear_buffer(void* port_buffer) { JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer; - if (buf && buf->IsValid()) + if (buf && buf->IsValid()) { buf->Reset(buf->nframes); + } } LIB_EXPORT @@ -124,13 +128,16 @@ int jack_midi_event_write(void* port_buffer, jack_nframes_t time, const jack_midi_data_t* data, size_t data_size) { JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer; - if (!buf && !buf->IsValid()) + if (!buf && !buf->IsValid()) { return -EINVAL; - if (time >= buf->nframes || (buf->event_count && buf->events[buf->event_count - 1].time > time)) + } + if (time >= buf->nframes || (buf->event_count && buf->events[buf->event_count - 1].time > time)) { return -EINVAL; + } jack_midi_data_t* dest = buf->ReserveEvent(time, data_size); - if (!dest) + if (!dest) { return -ENOBUFS; + } memcpy(dest, data, data_size); return 0; } diff --git a/common/JackMidiDriver.cpp b/common/JackMidiDriver.cpp index 86001ae2..47866647 100644 --- a/common/JackMidiDriver.cpp +++ b/common/JackMidiDriver.cpp @@ -143,11 +143,6 @@ int JackMidiDriver::SetBufferSize(jack_nframes_t buffer_size) return 0; } -int JackMidiDriver::ProcessNull() -{ - return 0; -} - int JackMidiDriver::ProcessRead() { return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync(); diff --git a/common/JackMidiDriver.h b/common/JackMidiDriver.h index b7584bbe..3e35ec08 100644 --- a/common/JackMidiDriver.h +++ b/common/JackMidiDriver.h @@ -74,8 +74,6 @@ class SERVER_EXPORT JackMidiDriver : public JackDriver virtual int ProcessRead(); virtual int ProcessWrite(); - virtual int ProcessNull(); - virtual int Attach(); virtual int Detach(); diff --git a/common/JackNetAPI.cpp b/common/JackNetAPI.cpp index 9be49aa0..4a7c40ee 100644 --- a/common/JackNetAPI.cpp +++ b/common/JackNetAPI.cpp @@ -1,5 +1,5 @@ /* -Copyright (C) 2009 Grame +Copyright (C) 2009-2011 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 @@ -35,18 +35,12 @@ extern "C" #define MASTER_NAME_SIZE 256 - enum JackNetMode { - - JackFastMode = 'f', - JackNormalMode = 'n', - JackSlowMode = 's', - }; - enum JackNetEncoder { JackFloatEncoder = 0, JackIntEncoder = 1, JackCeltEncoder = 2, + JackMaxEncoder = 3 }; typedef struct { @@ -57,9 +51,9 @@ extern "C" int midi_output; int mtu; int time_out; // in millisecond, -1 means in infinite - int encoder; + int encoder; // one of JackNetEncoder int kbps; // KB per second for CELT encoder - char mode; + int latency; // network cycles } jack_slave_t; @@ -100,10 +94,10 @@ extern "C" SERVER_EXPORT int jack_net_slave_activate(jack_net_slave_t* net); SERVER_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net); - SERVER_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t * net, JackNetSlaveProcessCallback net_callback, void *arg); - SERVER_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg); - SERVER_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg); - SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg); + SERVER_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg); + SERVER_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t* net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg); + SERVER_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t* net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg); + SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t* net, JackNetSlaveShutdownCallback shutdown_callback, void *arg); // NetJack master API @@ -190,19 +184,21 @@ struct JackNetExtMaster : public JackNetMasterInterface { } // Join multicast group - if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) - fprintf(stderr, "Can't join multicast group : %s\n", StrError(NET_ERROR_CODE)); + if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) { + fprintf(stderr, "Can't join multicast group : %s\n", StrError(NET_ERROR_CODE)); + } // Local loop - if (fSocket.SetLocalLoop() == SOCKET_ERROR) + if (fSocket.SetLocalLoop() == SOCKET_ERROR) { fprintf(stderr, "Can't set local loop : %s\n", StrError(NET_ERROR_CODE)); + } // Set a timeout on the multicast receive (the thread can now be cancelled) - if (fSocket.SetTimeOut(2000000) == SOCKET_ERROR) + if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) { fprintf(stderr, "Can't set timeout : %s\n", StrError(NET_ERROR_CODE)); + } - //main loop, wait for data, deal with it and wait again - //utility variables + // Main loop, wait for data, deal with it and wait again int attempt = 0; int rx_bytes = 0; @@ -251,7 +247,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { result->midi_input = fParams.fSendMidiChannels; result->midi_output = fParams.fReturnMidiChannels; result->mtu = fParams.fMtu; - result->mode = fParams.fNetworkMode; + result->latency = fParams.fNetworkLatency; return 0; error: @@ -278,12 +274,14 @@ struct JackNetExtMaster : public JackNetMasterInterface { fSocket.Close(); // Network slave init - if (!JackNetMasterInterface::Init()) + if (!JackNetMasterInterface::Init()) { return -1; + } // Set global parameters - if (!SetParams()) + if (!SetParams()) { return -1; + } AllocPorts(); return 0; @@ -376,8 +374,9 @@ struct JackNetExtMaster : public JackNetMasterInterface { fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]); } - if (SyncRecv() == SOCKET_ERROR) + if (SyncRecv() == SOCKET_ERROR) { return 0; + } DecodeSyncPacket(); return DataRecv(); @@ -391,22 +390,23 @@ struct JackNetExtMaster : public JackNetMasterInterface { int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) { try { - assert(audio_output == fParams.fSendAudioChannels); + assert(audio_output == fParams.fSendAudioChannels); - for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) { - fNetAudioCaptureBuffer->SetBuffer(audio_port_index, audio_output_buffer[audio_port_index]); - } + for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) { + fNetAudioCaptureBuffer->SetBuffer(audio_port_index, audio_output_buffer[audio_port_index]); + } - for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) { - fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); - } + for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) { + fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); + } - EncodeSyncPacket(); + EncodeSyncPacket(); - if (SyncSend() == SOCKET_ERROR) - return SOCKET_ERROR; + if (SyncSend() == SOCKET_ERROR) { + return SOCKET_ERROR; + } - return DataSend(); + return DataSend(); } catch (JackNetException& e) { jack_error("Connection lost."); @@ -472,7 +472,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf fParams.fReturnAudioChannels = request->audio_output; fParams.fSendMidiChannels = request->midi_input; fParams.fReturnMidiChannels = request->midi_output; - fParams.fNetworkMode = request->mode; + fParams.fNetworkLatency = request->latency; fParams.fSampleEncoder = request->encoder; fParams.fKBps = request->kbps; fParams.fSlaveSyncMode = 1; @@ -493,13 +493,20 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf int Open(jack_master_t* result) { + if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { + printf("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY); + return -1; + } + // Init network connection - if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) + if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) { return -1; + } // Then set global parameters - if (!SetParams()) + if (!SetParams()) { return -1; + } // Set result if (result != NULL) { @@ -519,23 +526,28 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf int Restart() { // If shutdown cb is set, then call it - if (fShutdownCallback) + if (fShutdownCallback) { fShutdownCallback(fShutdownArg); + } // Init network connection - if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) + if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) { return -1; + } // Then set global parameters - if (!SetParams()) + if (!SetParams()) { return -1; + } // We need to notify possibly new buffer size and sample rate (see Execute) - if (fBufferSizeCallback) + if (fBufferSizeCallback) { fBufferSizeCallback(fParams.fPeriodSize, fBufferSizeArg); + } - if (fSampleRateCallback) + if (fSampleRateCallback) { fSampleRateCallback(fParams.fSampleRate, fSampleRateArg); + } AllocPorts(); return 0; @@ -550,62 +562,58 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf void AllocPorts() { - int port_index; - // Set buffers fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels]; - for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) { - fAudioCaptureBuffer[port_index] = new float[fParams.fPeriodSize]; - fNetAudioCaptureBuffer->SetBuffer(port_index, fAudioCaptureBuffer[port_index]); + for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) { + fAudioCaptureBuffer[audio_port_index] = new float[fParams.fPeriodSize]; + fNetAudioCaptureBuffer->SetBuffer(audio_port_index, fAudioCaptureBuffer[audio_port_index]); } fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels]; - for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) { - fMidiCaptureBuffer[port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; - fNetMidiCaptureBuffer->SetBuffer(port_index, fMidiCaptureBuffer[port_index]); + for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { + fMidiCaptureBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; + fNetMidiCaptureBuffer->SetBuffer(midi_port_index, fMidiCaptureBuffer[midi_port_index]); } fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels]; - for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) { - fAudioPlaybackBuffer[port_index] = new float[fParams.fPeriodSize]; - fNetAudioPlaybackBuffer->SetBuffer(port_index, fAudioPlaybackBuffer[port_index]); + for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) { + fAudioPlaybackBuffer[audio_port_index] = new float[fParams.fPeriodSize]; + fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, fAudioPlaybackBuffer[audio_port_index]); } fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels]; - for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { - fMidiPlaybackBuffer[port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; - fNetMidiPlaybackBuffer->SetBuffer(port_index, fMidiPlaybackBuffer[port_index]); + for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { + fMidiPlaybackBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; + fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, fMidiPlaybackBuffer[midi_port_index]); } } void FreePorts() { - int port_index; - if (fAudioCaptureBuffer) { - for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) - delete[] fAudioCaptureBuffer[port_index]; + for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) + delete[] fAudioCaptureBuffer[audio_port_index]; delete[] fAudioCaptureBuffer; fAudioCaptureBuffer = NULL; } if (fMidiCaptureBuffer) { - for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) - delete[] (fMidiCaptureBuffer[port_index]); + for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) + delete[] (fMidiCaptureBuffer[midi_port_index]); delete[] fMidiCaptureBuffer; fMidiCaptureBuffer = NULL; } if (fAudioPlaybackBuffer) { - for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) - delete[] fAudioPlaybackBuffer[port_index]; + for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) + delete[] fAudioPlaybackBuffer[audio_port_index]; delete[] fAudioPlaybackBuffer; fAudioPlaybackBuffer = NULL; } if (fMidiPlaybackBuffer) { - for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) - delete[] fMidiPlaybackBuffer[port_index]; + for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) + delete[] fMidiPlaybackBuffer[midi_port_index]; delete[] fMidiPlaybackBuffer; fMidiPlaybackBuffer = NULL; } @@ -621,7 +629,11 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf bool Init() { // Will do "something" on OSX only... - fThread.SetParams(UInt64(float(fParams.fPeriodSize)/float(fParams.fSampleRate)*1000000), 100 * 1000, 500 * 1000); + UInt64 period, constraint; + period = constraint = float(fParams.fPeriodSize) / float(fParams.fSampleRate) * 1000000; + UInt64 computation = JackTools::ComputationMicroSec(fParams.fPeriodSize); + fThread.SetParams(period, computation, constraint); + return (fThread.AcquireRealTime(80) == 0); // TODO: get a value from the server } @@ -630,8 +642,9 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf try { // Keep running even in case of error while (fThread.GetStatus() == JackThread::kRunning) { - if (Process() == SOCKET_ERROR) + if (Process() == SOCKET_ERROR) { return false; + } } return false; } catch (JackNetException& e) { @@ -652,10 +665,10 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf int Read() { - // Don't return -1 in case of sync recv failure - // we need the process to continue for network error detection - if (SyncRecv() == SOCKET_ERROR) - return 0; + //receive sync (launch the cycle) + if (SyncRecv() == SOCKET_ERROR) { + return SOCKET_ERROR; + } DecodeSyncPacket(); return DataRecv(); @@ -665,18 +678,19 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf { EncodeSyncPacket(); - if (SyncSend() == SOCKET_ERROR) + if (SyncSend() == SOCKET_ERROR) { return SOCKET_ERROR; + } return DataSend(); } int Process() { - // Read data from the network - // in case of fatal network error, stop the process - if (Read() == SOCKET_ERROR) + // Read data from the network, throw JackNetException in case of network error... + if (Read() == SOCKET_ERROR) { return SOCKET_ERROR; + } fProcessCallback(fParams.fPeriodSize, fParams.fSendAudioChannels, @@ -689,10 +703,10 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf (void**)fMidiPlaybackBuffer, fProcessArg); - // Then write data to network - // in case of failure, stop process - if (Write() == SOCKET_ERROR) + // Then write data to network, throw JackNetException in case of network error... + if (Write() == SOCKET_ERROR) { return SOCKET_ERROR; + } return 0; } @@ -777,17 +791,20 @@ struct JackNetAdapter : public JackAudioAdapterInterface { { //ringbuffers - if (fCaptureChannels > 0) + if (fCaptureChannels > 0) { fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; - if (fPlaybackChannels > 0) + } + if (fPlaybackChannels > 0) { fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; + } if (fAdaptative) { AdaptRingBufferSize(); jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize); } else { - if (fRingbufferCurSize > DEFAULT_RB_SIZE) + if (fRingbufferCurSize > DEFAULT_RB_SIZE) { fRingbufferCurSize = DEFAULT_RB_SIZE; + } jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize); } @@ -800,10 +817,12 @@ struct JackNetAdapter : public JackAudioAdapterInterface { fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); } - if (fCaptureChannels > 0) + if (fCaptureChannels > 0) { jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); - if (fPlaybackChannels > 0) + } + if (fPlaybackChannels > 0) { jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); + } } virtual ~JackNetAdapter() @@ -923,7 +942,11 @@ SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, jack_nframes_t adapted_buffer_size, jack_nframes_t adapted_sample_rate) { - return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate); + try { + return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate); + } catch (...) { + return NULL; + } } SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) diff --git a/common/JackNetAdapter.cpp b/common/JackNetAdapter.cpp index 7642fd58..9be1bcf3 100644 --- a/common/JackNetAdapter.cpp +++ b/common/JackNetAdapter.cpp @@ -41,6 +41,7 @@ namespace Jack GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE); fSocket.GetName(fParams.fSlaveNetName); fParams.fMtu = DEFAULT_MTU; + // Desactivated for now... fParams.fTransportSync = 0; int send_audio = -1; int return_audio = -1; @@ -49,7 +50,7 @@ namespace Jack fParams.fSampleRate = sample_rate; fParams.fPeriodSize = buffer_size; fParams.fSlaveSyncMode = 1; - fParams.fNetworkMode = 's'; + fParams.fNetworkLatency = 2; fParams.fSampleEncoder = JackFloatEncoder; fJackClient = jack_client; @@ -94,15 +95,11 @@ namespace Jack } break; #endif - case 'm' : - if (strcmp(param->value.str, "normal") == 0) { - fParams.fNetworkMode = 'n'; - } else if (strcmp(param->value.str, "slow") == 0) { - fParams.fNetworkMode = 's'; - } else if (strcmp(param->value.str, "fast") == 0) { - fParams.fNetworkMode = 'f'; - } else { - jack_error("Unknown network mode, using 'normal' mode."); + case 'l' : + fParams.fNetworkLatency = param->value.i; + if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { + jack_error("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY); + throw std::bad_alloc(); } break; case 'q': @@ -276,20 +273,20 @@ namespace Jack { case JackTransportStopped : jack_transport_stop(fJackClient); - jack_info("NetMaster : transport stops."); + jack_info("NetMaster : transport stops"); break; case JackTransportStarting : jack_transport_reposition(fJackClient, &fSendTransportData.fPosition); jack_transport_start(fJackClient); - jack_info("NetMaster : transport starts."); + jack_info("NetMaster : transport starts"); break; case JackTransportRolling : // TODO, we need to : // - find a way to call TransportEngine->SetNetworkSync() // - turn the transport state to JackTransportRolling - jack_info("NetMaster : transport rolls."); + jack_info("NetMaster : transport rolls"); break; } } @@ -412,8 +409,8 @@ extern "C" value.ui = 1U; jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); - strcpy(value.str, "slow"); - jack_driver_descriptor_add_parameter(desc, &filler, "mode", 'm', JackDriverParamString, &value, NULL, "Slow, Normal or Fast mode.", NULL); + value.ui = 2U; + jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL); value.i = 0; jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL); @@ -448,6 +445,7 @@ extern "C" } } catch (...) { + jack_info("NetAdapter allocation error"); return 1; } } diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index 2855fb17..da8327d2 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -1,5 +1,4 @@ /* -Copyright (C) 2001 Paul Davis Copyright (C) 2008-2011 Romain Moret at Grame This program is free software; you can redistribute it and/or modify @@ -29,14 +28,15 @@ namespace Jack { JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports, - char* net_name, uint transport_sync, char network_mode, int celt_encoding) - : JackAudioDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) + char* net_name, uint transport_sync, int network_latency, int celt_encoding) + : JackTimedDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) { jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port); // Use the hostname if no name parameter was given - if (strcmp(net_name, "") == 0) + if (strcmp(net_name, "") == 0) { GetHostName(net_name, JACK_CLIENT_NAME_SIZE); + } fParams.fMtu = mtu; fParams.fSendMidiChannels = midi_input_ports; @@ -50,7 +50,7 @@ namespace Jack strcpy(fParams.fName, net_name); fSocket.GetName(fParams.fSlaveNetName); fParams.fTransportSync = transport_sync; - fParams.fNetworkMode = network_mode; + fParams.fNetworkLatency = network_latency; fSendTransportData.fState = -1; fReturnTransportData.fState = -1; fLastTransportState = -1; @@ -73,32 +73,16 @@ namespace Jack } //open, close, attach and detach------------------------------------------------------ - int JackNetDriver::Open(jack_nframes_t buffer_size, jack_nframes_t samplerate, 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) - { - return JackAudioDriver::Open(buffer_size, - samplerate, - capturing, - playing, - inchannels, - outchannels, - monitor, - capture_driver_name, - playback_driver_name, - capture_latency, - playback_latency); - } - + int JackNetDriver::Close() { #ifdef JACK_MONITOR - if (fNetTimeMon) + if (fNetTimeMon) { fNetTimeMon->Save(); + } #endif FreeAll(); - return JackDriver::Close(); + return JackTimedDriver::Close(); } // Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init) @@ -185,20 +169,7 @@ namespace Jack plot_name = string(fParams.fName); plot_name += string("_slave"); plot_name += (fEngineControl->fSyncMode) ? string("_sync") : string("_async"); - switch (fParams.fNetworkMode) - { - case 's' : - plot_name += string("_slow"); - break; - - case 'n' : - plot_name += string("_normal"); - break; - - case 'f' : - plot_name += string("_fast"); - break; - } + plot_name += string("_latency"); fNetTimeMon = new JackGnuPlotMonitor<float>(128, 5, plot_name); string net_time_mon_fields[] = { @@ -216,8 +187,8 @@ namespace Jack fNetTimeMon->SetPlotFile(net_time_mon_options, 2, net_time_mon_fields, 5); #endif // Driver parametering - JackAudioDriver::SetBufferSize(fParams.fPeriodSize); - JackAudioDriver::SetSampleRate(fParams.fSampleRate); + JackTimedDriver::SetBufferSize(fParams.fPeriodSize); + JackTimedDriver::SetSampleRate(fParams.fSampleRate); JackDriver::NotifyBufferSize(fParams.fPeriodSize); JackDriver::NotifySampleRate(fParams.fSampleRate); @@ -273,68 +244,56 @@ namespace Jack //audio port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; - for (audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) - { + for (audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) { snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1); snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1); if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, - static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) - { + static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) { jack_error("driver: cannot register port for %s", name); return -1; } + + //port latency port = fGraphManager->GetPort(port_index); port->SetAlias(alias); - //port latency range.min = range.max = fEngineControl->fBufferSize; port->SetLatencyRange(JackCaptureLatency, &range); fCapturePortList[audio_port_index] = port_index; jack_log("JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency()); } + port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; - for (audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) - { + for (audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1); snprintf(name, sizeof(name) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1); if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, - static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) - { + static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) { jack_error("driver: cannot register port for %s", name); return -1; } + + //port latency port = fGraphManager->GetPort(port_index); port->SetAlias(alias); - //port latency - switch (fParams.fNetworkMode) - { - case 'f' : - range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize; - break; - case 'n' : - range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); - break; - case 's' : - range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); - break; - } + range.min = range.max = (fParams.fNetworkLatency * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); port->SetLatencyRange(JackPlaybackLatency, &range); fPlaybackPortList[audio_port_index] = port_index; jack_log("JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency()); } + //midi port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; - for (midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) - { + for (midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1); snprintf(name, sizeof (name) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1); if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, - static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) - { + static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) { jack_error("driver: cannot register port for %s", name); return -1; } - port = fGraphManager->GetPort(port_index); + //port latency + port = fGraphManager->GetPort(port_index); range.min = range.max = fEngineControl->fBufferSize; port->SetLatencyRange(JackCaptureLatency, &range); fMidiCapturePortList[midi_port_index] = port_index; @@ -342,30 +301,18 @@ namespace Jack } port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; - for (midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) - { + for (midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1); snprintf(name, sizeof(name) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1); if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, - static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) - { + static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) { jack_error("driver: cannot register port for %s", name); return -1; } - port = fGraphManager->GetPort(port_index); + //port latency - switch (fParams.fNetworkMode) - { - case 'f' : - range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize; - break; - case 'n' : - range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); - break; - case 's' : - range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); - break; - } + port = fGraphManager->GetPort(port_index); + range.min = range.max = (fParams.fNetworkLatency * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize); port->SetLatencyRange(JackPlaybackLatency, &range); fMidiPlaybackPortList[midi_port_index] = port_index; jack_log("JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency()); @@ -413,7 +360,7 @@ namespace Jack const char** connections; fConnections.clear(); - JackAudioDriver::SaveConnections(); + JackTimedDriver::SaveConnections(); for (int i = 0; i < fParams.fSendMidiChannels; ++i) { if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fMidiCapturePortList[i])) != 0) { @@ -455,8 +402,9 @@ namespace Jack bool conditional; if (fSendTransportData.fTimebaseMaster == TIMEBASEMASTER) { fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional); - if (refnum != -1) + if (refnum != -1) { fEngineControl->fTransport.ResetTimebase(refnum); + } jack_info("The NetMaster is now the new timebase master."); } @@ -513,12 +461,19 @@ namespace Jack fReturnTransportData.fNewState = ((fReturnTransportData.fState == JackTransportNetStarting) && (fReturnTransportData.fState != fLastTransportState) && (fReturnTransportData.fState != fSendTransportData.fState)); - if (fReturnTransportData.fNewState) + if (fReturnTransportData.fNewState) { jack_info("Sending '%s'.", GetTransportState(fReturnTransportData.fState)); + } fLastTransportState = fReturnTransportData.fState; } //driver processes-------------------------------------------------------------------- + + int JackNetDriver::Process() + { + return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); + } + int JackNetDriver::Read() { //buffers @@ -538,8 +493,9 @@ namespace Jack #endif //receive sync (launch the cycle) - if (SyncRecv() == SOCKET_ERROR) - return 0; + if (SyncRecv() == SOCKET_ERROR) { + return SOCKET_ERROR; + } #ifdef JACK_MONITOR // For timing @@ -581,7 +537,7 @@ namespace Jack for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { #ifdef OPTIMIZED_PROTOCOL // Port is connected on other side... - if ((intptr_t)fNetAudioPlaybackBuffer->GetBuffer(audio_port_index) == -1) { + if (fNetAudioPlaybackBuffer->GetConnected(audio_port_index)) { fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index, true)); } else { fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); @@ -599,16 +555,18 @@ namespace Jack EncodeSyncPacket(); //send sync - if (SyncSend() == SOCKET_ERROR) + if (SyncSend() == SOCKET_ERROR) { return SOCKET_ERROR; + } #ifdef JACK_MONITOR fNetTimeMon->Add(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); #endif //send data - if (DataSend() == SOCKET_ERROR) + if (DataSend() == SOCKET_ERROR) { return SOCKET_ERROR; + } #ifdef JACK_MONITOR fNetTimeMon->AddLast(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); @@ -655,11 +613,11 @@ namespace Jack strcpy(value.str, "'hostname'"); jack_driver_descriptor_add_parameter(desc, &filler, "client_name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); - value.ui = 1U; + value.ui = 0U; jack_driver_descriptor_add_parameter(desc, &filler, "transport_sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); - strcpy(value.str, "slow"); - jack_driver_descriptor_add_parameter(desc, &filler, "mode", 'm', JackDriverParamString, &value, NULL, "Slow, Normal or Fast mode.", NULL); + value.ui = 5U; + jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL); return desc; } @@ -670,7 +628,8 @@ namespace Jack char net_name[JACK_CLIENT_NAME_SIZE + 1]; int udp_port; int mtu = DEFAULT_MTU; - uint transport_sync = 1; + // Desactivated for now... + uint transport_sync = 0; jack_nframes_t period_size = 128; jack_nframes_t sample_rate = 48000; int audio_capture_ports = -1; @@ -679,7 +638,7 @@ namespace Jack int midi_output_ports = 0; int celt_encoding = -1; bool monitor = false; - char network_mode = 's'; + int network_latency = 5; const JSList* node; const jack_driver_param_t* param; @@ -732,15 +691,12 @@ namespace Jack case 't' : transport_sync = param->value.ui; break; - case 'm' : - if (strcmp(param->value.str, "normal") == 0) - network_mode = 'n'; - else if (strcmp(param->value.str, "slow") == 0) - network_mode = 's'; - else if (strcmp(param->value.str, "fast") == 0) - network_mode = 'f'; - else - jack_error("Unknown network mode, using 'normal' mode."); + case 'l' : + network_latency = param->value.ui; + if (network_latency > NETWORK_MAX_LATENCY) { + printf("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY); + return NULL; + } break; } } @@ -751,7 +707,7 @@ namespace Jack new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, midi_input_ports, midi_output_ports, net_name, transport_sync, - network_mode, celt_encoding)); + network_latency, celt_encoding)); if (driver->Open(period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, monitor, "from_master_", "to_master_", 0, 0) == 0) { return driver; } else { diff --git a/common/JackNetDriver.h b/common/JackNetDriver.h index f73337c7..98f512ab 100644 --- a/common/JackNetDriver.h +++ b/common/JackNetDriver.h @@ -1,5 +1,4 @@ /* -Copyright (C) 2001 Paul Davis Copyright (C) 2008-2011 Romain Moret at Grame This program is free software; you can redistribute it and/or modify @@ -21,9 +20,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __JackNetDriver__ #define __JackNetDriver__ -#include "JackAudioDriver.h" +#include "JackTimedDriver.h" #include "JackNetInterface.h" +//#define JACK_MONITOR + #ifdef JACK_MONITOR #include "JackFrameTimer.h" #endif @@ -34,7 +35,7 @@ namespace Jack \Brief This class describes the Net Backend */ - class JackNetDriver : public JackAudioDriver, public JackNetSlaveInterface + class JackNetDriver : public JackTimedDriver, public JackNetSlaveInterface { private: @@ -72,14 +73,14 @@ namespace Jack JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, - char* net_name, uint transport_sync, char network_master_mode, int celt_encoding); - ~JackNetDriver(); + char* net_name, uint transport_sync, int network_latency, int celt_encoding); + virtual ~JackNetDriver(); - 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(); - + + // The + int Process(); + int Attach(); int Detach(); diff --git a/common/JackNetInterface.cpp b/common/JackNetInterface.cpp index d8562a05..32e2ed2f 100644 --- a/common/JackNetInterface.cpp +++ b/common/JackNetInterface.cpp @@ -1,5 +1,4 @@ /* -Copyright (C) 2001 Paul Davis Copyright (C) 2008-2011 Romain Moret at Grame This program is free software; you can redistribute it and/or modify @@ -24,8 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. using namespace std; -#define PACKET_AVAILABLE_SIZE (fParams.fMtu - sizeof(packet_header_t)) -#define HEADER_SIZE (sizeof(packet_header_t)) /* TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames, @@ -94,62 +91,142 @@ namespace Jack int JackNetInterface::SetNetBufferSize() { - //audio + // audio float audio_size = (fNetAudioCaptureBuffer) - ? fNetAudioCaptureBuffer->GetCycleSize() - : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0; + ? fNetAudioCaptureBuffer->GetCycleSize() + : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0; jack_log("audio_size %f", audio_size); - //midi + // midi float midi_size = (fNetMidiCaptureBuffer) - ? fNetMidiCaptureBuffer->GetCycleSize() - : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0; + ? fNetMidiCaptureBuffer->GetCycleSize() + : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0; jack_log("midi_size %f", midi_size); - //bufsize = sync + audio + midi - int bufsize = MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int) midi_size); + // bufsize = sync + audio + midi + int bufsize = NETWORK_MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int)midi_size); jack_log("SetNetBufferSize bufsize = %d", bufsize); - //tx buffer - if (fSocket.SetOption(SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) + // tx buffer + if (fSocket.SetOption(SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) { return SOCKET_ERROR; + } - //rx buffer - if (fSocket.SetOption(SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) + // rx buffer + if (fSocket.SetOption(SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) { return SOCKET_ERROR; + } return 0; } bool JackNetInterface::SetParams() { - //TX header init + // TX header init strcpy(fTxHeader.fPacketType, "header"); fTxHeader.fID = fParams.fID; fTxHeader.fCycle = 0; fTxHeader.fSubCycle = 0; fTxHeader.fIsLastPckt = 0; - //RX header init + // RX header init strcpy(fRxHeader.fPacketType, "header"); fRxHeader.fID = fParams.fID; fRxHeader.fCycle = 0; fRxHeader.fSubCycle = 0; fRxHeader.fIsLastPckt = 0; - //network buffers + // network buffers fTxBuffer = new char[fParams.fMtu]; fRxBuffer = new char[fParams.fMtu]; assert(fTxBuffer); assert(fRxBuffer); - //net audio/midi buffers'addresses + // net audio/midi buffers'addresses fTxData = fTxBuffer + HEADER_SIZE; fRxData = fRxBuffer + HEADER_SIZE; return true; } + int JackNetInterface::MidiSend(NetMidiBuffer* buffer, int midi_channnels, int audio_channels) + { + if (midi_channnels > 0) { + // set global header fields and get the number of midi packets + fTxHeader.fDataType = 'm'; + uint data_size = buffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = buffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE(&fParams)); + + for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { + fTxHeader.fSubCycle = subproc; + fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && audio_channels == 0) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + buffer->RenderToNetwork(subproc, data_size); + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) { + return SOCKET_ERROR; + } + } + } + return 0; + } + + int JackNetInterface::AudioSend(NetAudioBuffer* buffer, int audio_channels) + { + // audio + if (audio_channels > 0) { + fTxHeader.fDataType = 'a'; + fTxHeader.fActivePorts = buffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = buffer->GetNumPackets(fTxHeader.fActivePorts); + + for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { + fTxHeader.fSubCycle = subproc; + fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + buffer->RenderToNetwork(subproc, fTxHeader.fActivePorts); + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + // PacketHeaderDisplay(&fTxHeader); + if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) { + return SOCKET_ERROR; + } + } + } + return 0; + } + + int JackNetInterface::MidiRecv(packet_header_t* rx_head, NetMidiBuffer* buffer, uint& recvd_midi_pckt) + { + int rx_bytes = Recv(rx_head->fPacketSize, 0); + fRxHeader.fCycle = rx_head->fCycle; + fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; + buffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); + // Last midi packet is received, so finish rendering... + if (++recvd_midi_pckt == rx_head->fNumPacket) { + buffer->RenderToJackPorts(); + } + return rx_bytes; + } + + int JackNetInterface::AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer) + { + int rx_bytes = Recv(rx_head->fPacketSize, 0); + fRxHeader.fCycle = rx_head->fCycle; + fRxHeader.fSubCycle = rx_head->fSubCycle; + fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; + fRxHeader.fActivePorts = rx_head->fActivePorts; + rx_bytes = buffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, fRxHeader.fActivePorts); + // Last audio packet is received, so finish rendering... + if (fRxHeader.fIsLastPckt) { + buffer->RenderToJackPorts(); + } + return rx_bytes; + } + + int JackNetInterface::FinishRecv(NetAudioBuffer* buffer) + { + // TODO : finish midi and audio rendering ? + buffer->RenderToJackPorts(); + return NET_PACKET_ERROR; + } + // JackNetMasterInterface ************************************************************************************ bool JackNetMasterInterface::Init() @@ -160,23 +237,23 @@ namespace Jack uint attempt = 0; int rx_bytes = 0; - //socket + // socket if (fSocket.NewSocket() == SOCKET_ERROR) { jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE)); return false; } - //timeout on receive (for init) + // timeout on receive (for init) if (fSocket.SetTimeOut(MASTER_INIT_TIMEOUT) < 0) jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE)); - //connect + // connect if (fSocket.Connect() == SOCKET_ERROR) { jack_error("Can't connect : %s", StrError(NET_ERROR_CODE)); return false; } - //send 'SLAVE_SETUP' until 'START_MASTER' received + // send 'SLAVE_SETUP' until 'START_MASTER' received jack_info("Sending parameters to %s...", fParams.fSlaveNetName); do { @@ -185,12 +262,12 @@ namespace Jack SetPacketType(&fParams, SLAVE_SETUP); SessionParamsHToN(&fParams, &net_params); - if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR) + if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR) { jack_error("Error in send : %s", StrError(NET_ERROR_CODE)); + } memset(&net_params, 0, sizeof(session_params_t)); - if (((rx_bytes = fSocket.Recv(&net_params, sizeof(session_params_t), 0)) == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) - { + if (((rx_bytes = fSocket.Recv(&net_params, sizeof(session_params_t), 0)) == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { jack_error("Problem with network"); return false; } @@ -206,28 +283,6 @@ namespace Jack return true; } - /* - int JackNetMasterInterface::SetRxTimeout() - { - jack_log("JackNetMasterInterface::SetRxTimeout"); - - float time = 0; - - //slow or normal mode, short timeout on recv (2 audio subcycles) - if ((fParams.fNetworkMode == 's') || (fParams.fNetworkMode == 'n')) { - time = 2000000.f * ((fNetAudioCaptureBuffer) - ? fNetAudioCaptureBuffer->GetCycleDuration() - : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleDuration() : 0); - } - //fast mode, wait for 75% of the entire cycle duration - else if (fParams.fNetworkMode == 'f') { - time = 750000.f * (static_cast<float>(fParams.fPeriodSize) / static_cast<float>(fParams.fSampleRate)); - } - - return fSocket.SetTimeOut(static_cast<int>(time)); - } - */ - int JackNetMasterInterface::SetRxTimeout() { jack_log("JackNetMasterInterface::SetRxTimeout"); @@ -238,23 +293,28 @@ namespace Jack bool JackNetMasterInterface::SetParams() { jack_log("JackNetMasterInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d", - fParams.fSendAudioChannels, fParams.fReturnAudioChannels, fParams.fSendMidiChannels, fParams.fReturnMidiChannels); + fParams.fSendAudioChannels, fParams.fReturnAudioChannels, + fParams.fSendMidiChannels, fParams.fReturnMidiChannels); JackNetInterface::SetParams(); fTxHeader.fDataStream = 's'; fRxHeader.fDataStream = 'r'; - //midi net buffers - if (fParams.fSendMidiChannels > 0) + fMaxCycleOffset = fParams.fNetworkLatency; + + // midi net buffers + if (fParams.fSendMidiChannels > 0) { fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fTxData); + } - if (fParams.fReturnMidiChannels > 0) + if (fParams.fReturnMidiChannels > 0) { fNetMidiPlaybackBuffer = new NetMidiBuffer(&fParams, fParams.fReturnMidiChannels, fRxData); + } try { - //audio net buffers + // audio net buffers if (fParams.fSendAudioChannels > 0) { switch (fParams.fSampleEncoder) { @@ -304,13 +364,15 @@ namespace Jack return false; } - //set the new timeout for the socket + // set the new timeout for the socket + /* if (SetRxTimeout() == SOCKET_ERROR) { jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE)); goto error; } + */ - //set the new rx buffer size + // set the new rx buffer size if (SetNetBufferSize() == SOCKET_ERROR) { jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); goto error; @@ -327,10 +389,10 @@ namespace Jack { jack_log("JackNetMasterInterface::Exit, ID %u", fParams.fID); - //stop process + // stop process fRunning = false; - //send a 'multicast euthanasia request' - new socket is required on macosx + // send a 'multicast euthanasia request' - new socket is required on macosx jack_info("Exiting '%s'", fParams.fName); SetPacketType(&fParams, KILL_MASTER); JackNetSocket mcast_socket(fMulticastIP, fSocket.GetPort()); @@ -339,19 +401,31 @@ namespace Jack memset(&net_params, 0, sizeof(session_params_t)); SessionParamsHToN(&fParams, &net_params); - if (mcast_socket.NewSocket() == SOCKET_ERROR) + if (mcast_socket.NewSocket() == SOCKET_ERROR) { jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE)); - if (mcast_socket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR) + } + if (mcast_socket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR) { jack_error("Can't send suicide request : %s", StrError(NET_ERROR_CODE)); + } mcast_socket.Close(); } - void JackNetMasterInterface::FatalError() + void JackNetMasterInterface::FatalRecvError() { - //fatal connection issue, exit - jack_error("'%s' : %s, exiting", fParams.fName, StrError(NET_ERROR_CODE)); - //ask to the manager to properly remove the master + // fatal connection issue, exit + jack_error("Recv connection lost error = %s, '%s' exiting", StrError(NET_ERROR_CODE), fParams.fName); + // ask to the manager to properly remove the master + Exit(); + // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine. + ThreadExit(); + } + + void JackNetMasterInterface::FatalSendError() + { + // fatal connection issue, exit + jack_error("Send connection lost error = %s, '%s' exiting", StrError(NET_ERROR_CODE), fParams.fName); + // ask to the manager to properly remove the master Exit(); // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine. ThreadExit(); @@ -365,17 +439,17 @@ namespace Jack /* net_error_t error = fSocket.GetError(); - //no data isn't really a network error, so just return 0 available read bytes + // no data isn't really a network error, so just return 0 available read bytes if (error == NET_NO_DATA) { return 0; } else if (error == NET_CONN_ERROR) { - FatalError(); + FatalRecvError(); } else { jack_error("Error in master receive : %s", StrError(NET_ERROR_CODE)); } */ - FatalError(); + FatalRecvError(); } packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer); @@ -393,23 +467,19 @@ namespace Jack /* net_error_t error = fSocket.GetError(); if (error == NET_CONN_ERROR) { - FatalError(); + FatalSendError(); } else { jack_error("Error in master send : %s", StrError(NET_ERROR_CODE)); } */ - FatalError(); + FatalSendError(); } return tx_bytes; } bool JackNetMasterInterface::IsSynched() { - if (fParams.fNetworkMode == 's') { - return (fCycleOffset < (CYCLE_OFFSET_SLOW + 1)); - } else { - return true; - } + return (fCurrentCycleOffset <= fMaxCycleOffset); } int JackNetMasterInterface::SyncSend() @@ -420,60 +490,25 @@ namespace Jack fTxHeader.fIsLastPckt = (fParams.fSendMidiChannels == 0 && fParams.fSendAudioChannels == 0) ? 1 : 0; fTxHeader.fPacketSize = fParams.fMtu; - // Write active ports list - if (fNetAudioPlaybackBuffer) - fNetAudioPlaybackBuffer->ActivePortsToNetwork(fTxData, fTxHeader.fActivePorts); - memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - //PacketHeaderDisplay(&fTxHeader); + // PacketHeaderDisplay(&fTxHeader); return Send(fTxHeader.fPacketSize, 0); } int JackNetMasterInterface::DataSend() { - uint subproc; - uint data_size; - - //midi - if (fParams.fSendMidiChannels > 0) { - //set global header fields and get the number of midi packets - fTxHeader.fDataType = 'm'; - data_size = fNetMidiCaptureBuffer->RenderFromJackPorts(); - fTxHeader.fNumPacket = fNetMidiCaptureBuffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE); - - for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { - fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && (fParams.fSendAudioChannels == 0)) ? 1 : 0; - fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiCaptureBuffer->RenderToNetwork(subproc, data_size); - memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) - return SOCKET_ERROR; - } - } - - //audio - if (fParams.fSendAudioChannels > 0) { - fTxHeader.fDataType = 'a'; - fNetAudioCaptureBuffer->RenderFromJackPorts(); - fTxHeader.fNumPacket = fNetAudioCaptureBuffer->GetNumPackets(); - - for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { - fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; - fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioCaptureBuffer->RenderToNetwork(subproc, fTxHeader.fActivePorts); - memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - //PacketHeaderDisplay(&fTxHeader); - if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) - return SOCKET_ERROR; - } + if (MidiSend(fNetMidiCaptureBuffer, fParams.fSendMidiChannels, fParams.fSendAudioChannels) == SOCKET_ERROR) { + return SOCKET_ERROR; } - - return 0; + return AudioSend(fNetAudioCaptureBuffer, fParams.fSendAudioChannels); } int JackNetMasterInterface::SyncRecv() { + int rx_bytes = 0; packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); + + /* int rx_bytes = Recv(fParams.fMtu, MSG_PEEK); if ((rx_bytes == 0) || (rx_bytes == SOCKET_ERROR)) { @@ -481,68 +516,29 @@ namespace Jack return SOCKET_ERROR; } - fCycleOffset = fTxHeader.fCycle - rx_head->fCycle; - - // Read active ports list - if (fNetAudioCaptureBuffer) - fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); - - switch (fParams.fNetworkMode) - { - case 's' : - //slow mode : allow to use full bandwidth and heavy process on the slave - // - extra latency is set to two cycles, one cycle for send/receive operations + one cycle for heavy process on the slave - // - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master - // - this mode will skip the two first cycles, thus it lets time for data to be processed and queued on the socket rx buffer - //the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process) - - if (fCycleOffset < CYCLE_OFFSET_SLOW) { - return 0; - } else { - rx_bytes = Recv(rx_head->fPacketSize, 0); - } - - /* - rx_bytes = Recv(rx_head->fPacketSize, 0); - - if (fCycleOffset != fLastfCycleOffset) - jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); - fLastfCycleOffset = fCycleOffset; - */ - - break; - - case 'n' : - //normal use of the network : - // - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth - // - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter - // - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it - if (fCycleOffset < CYCLE_OFFSET_NORMAL) { - return 0; - } else { - rx_bytes = Recv(rx_head->fPacketSize, 0); - } + fCurrentCycleOffset = fTxHeader.fCycle - rx_head->fCycle; + */ - if (fCycleOffset > CYCLE_OFFSET_NORMAL) { - jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); - } - break; + // receive sync (launch the cycle) + do { + rx_bytes = Recv(fParams.fMtu, MSG_PEEK); + // connection issue, send will detect it, so don't skip the cycle (return 0) + if (rx_bytes == SOCKET_ERROR) { + return SOCKET_ERROR; + } + } + while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's')); - case 'f' : - //fast mode suppose the network bandwith is larger than required for the transmission (only a few channels for example) - // - packets can be quickly received, quickly is here relative to the cycle duration - // - here, receive data, we can't keep it queued on the rx buffer, - // - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow - rx_bytes = Recv(rx_head->fPacketSize, 0); + fCurrentCycleOffset = fTxHeader.fCycle - rx_head->fCycle; - if (fCycleOffset > CYCLE_OFFSET_FAST) { - jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); - } - break; + if (fCurrentCycleOffset < fMaxCycleOffset) { + jack_info("Synching with latency = %d", fCurrentCycleOffset); + return 0; + } else { + rx_bytes = Recv(rx_head->fPacketSize, 0); + fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; + return rx_bytes; } - - fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - return rx_bytes; } int JackNetMasterInterface::DataRecv() @@ -551,47 +547,30 @@ namespace Jack uint recvd_midi_pckt = 0; packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); - while (!fRxHeader.fIsLastPckt) - { - //how much data is queued on the rx buffer ? + while (!fRxHeader.fIsLastPckt) { + // how much data is queued on the rx buffer ? rx_bytes = Recv(fParams.fMtu, MSG_PEEK); - //error here, problem with recv, just skip the cycle (return -1) - if (rx_bytes == SOCKET_ERROR) + // error here, problem with recv, just skip the cycle (return -1) + if (rx_bytes == SOCKET_ERROR) { return rx_bytes; + } + + if (rx_bytes && (rx_head->fDataStream == 'r') && (rx_head->fID == fParams.fID)) { + // read data + switch (rx_head->fDataType) { - if (rx_bytes && (rx_head->fDataStream == 'r') && (rx_head->fID == fParams.fID)) - { - //read data - switch (rx_head->fDataType) - { - case 'm': //midi - rx_bytes = Recv(rx_head->fPacketSize, 0); - fRxHeader.fCycle = rx_head->fCycle; - fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fNetMidiPlaybackBuffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); - // Last midi packet is received, so finish rendering... - if (++recvd_midi_pckt == rx_head->fNumPacket) - fNetMidiPlaybackBuffer->RenderToJackPorts(); + case 'm': // midi + rx_bytes = MidiRecv(rx_head, fNetMidiPlaybackBuffer, recvd_midi_pckt); break; - case 'a': //audio - rx_bytes = Recv(rx_head->fPacketSize, 0); - fRxHeader.fCycle = rx_head->fCycle; - fRxHeader.fSubCycle = rx_head->fSubCycle; - fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fRxHeader.fActivePorts = rx_head->fActivePorts; - rx_bytes = fNetAudioPlaybackBuffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE, fRxHeader.fActivePorts); - // Last audio packet is received, so finish rendering... - if (fRxHeader.fIsLastPckt) - fNetAudioPlaybackBuffer->RenderToJackPorts(); + case 'a': // audio + rx_bytes = AudioRecv(rx_head, fNetAudioPlaybackBuffer); break; - case 's': //sync + case 's': // sync jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName); - // TODO : finish midi and audio rendering ? - fNetAudioPlaybackBuffer->RenderToJackPorts(); - return NET_PACKET_ERROR; + return FinishRecv(fNetAudioPlaybackBuffer); } } } @@ -601,35 +580,46 @@ namespace Jack void JackNetMasterInterface::EncodeSyncPacket() { - //this method contains every step of sync packet informations coding - //first of all, reset sync packet - memset(fTxData, 0, PACKET_AVAILABLE_SIZE); + // This method contains every step of sync packet informations coding + // first of all, clear sync packet + memset(fTxData, 0, PACKET_AVAILABLE_SIZE(&fParams)); - //then, first step : transport + // then, first step : transport if (fParams.fTransportSync) { - // desactivated... - //EncodeTransportData(); - TransportDataHToN(&fSendTransportData, &fSendTransportData); - //copy to TxBuffer + EncodeTransportData(); + TransportDataHToN(&fSendTransportData, &fSendTransportData); + // copy to TxBuffer memcpy(fTxData, &fSendTransportData, sizeof(net_transport_data_t)); } - //then others (freewheel etc.) - //... + // then others (freewheel etc.) + // ... + + // Transport not used for now... + + // Write active ports list + fTxHeader.fActivePorts = (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->ActivePortsToNetwork(fTxData) : 0; } void JackNetMasterInterface::DecodeSyncPacket() { - //this method contains every step of sync packet informations decoding process - //first : transport + // This method contains every step of sync packet informations decoding process + // first : transport if (fParams.fTransportSync) { - //copy received transport data to transport data structure + // copy received transport data to transport data structure memcpy(&fReturnTransportData, fRxData, sizeof(net_transport_data_t)); TransportDataNToH(&fReturnTransportData, &fReturnTransportData); - // desactivated... - //DecodeTransportData(); + DecodeTransportData(); + } + // then others + // ... + + // Transport not used for now... + packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); + + // Read active ports list + if (fNetAudioCaptureBuffer) { + fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); } - //then others - //... } // JackNetSlaveInterface ************************************************************************************************ @@ -640,27 +630,29 @@ namespace Jack { jack_log("JackNetSlaveInterface::Init()"); - //set the parameters to send + // set the parameters to send strcpy(fParams.fPacketType, "params"); fParams.fProtocolVersion = SLAVE_PROTOCOL; SetPacketType(&fParams, SLAVE_AVAILABLE); - //init loop : get a master and start, do it until connection is ok + // init loop : get a master and start, do it until connection is ok net_status_t status; do { - //first, get a master, do it until a valid connection is running + // first, get a master, do it until a valid connection is running do { status = SendAvailableToMaster(); - if (status == NET_SOCKET_ERROR) + if (status == NET_SOCKET_ERROR) { return false; + } } while (status != NET_CONNECTED); - //then tell the master we are ready + // then tell the master we are ready jack_info("Initializing connection with %s...", fParams.fMasterNetName); status = SendStartToMaster(); - if (status == NET_ERROR) + if (status == NET_ERROR) { return false; + } } while (status != NET_ROLLING); @@ -668,22 +660,23 @@ namespace Jack } // Separate the connection protocol into two separated step - bool JackNetSlaveInterface::InitConnection(int time_out) + bool JackNetSlaveInterface::InitConnection(int time_out_sec) { jack_log("JackNetSlaveInterface::InitConnection()"); - unsigned int try_count = (time_out > 0) ? ((1000000 * time_out) / SLAVE_INIT_TIMEOUT) : LONG_MAX; + uint try_count = (time_out_sec > 0) ? ((1000000 * time_out_sec) / SLAVE_INIT_TIMEOUT) : LONG_MAX; - //set the parameters to send + // set the parameters to send strcpy(fParams.fPacketType, "params"); fParams.fProtocolVersion = SLAVE_PROTOCOL; SetPacketType(&fParams, SLAVE_AVAILABLE); net_status_t status; do { - //get a master + // get a master status = SendAvailableToMaster(try_count); - if (status == NET_SOCKET_ERROR) + if (status == NET_SOCKET_ERROR) { return false; + } } while (status != NET_CONNECTED && --try_count > 0); @@ -696,7 +689,7 @@ namespace Jack net_status_t status; do { - //then tell the master we are ready + // then tell the master we are ready jack_info("Initializing connection with %s...", fParams.fMasterNetName); status = SendStartToMaster(); if (status == NET_ERROR) @@ -710,41 +703,41 @@ namespace Jack net_status_t JackNetSlaveInterface::SendAvailableToMaster(long try_count) { jack_log("JackNetSlaveInterface::SendAvailableToMaster()"); - //utility + // utility session_params_t host_params; int rx_bytes = 0; - //socket + // socket if (fSocket.NewSocket() == SOCKET_ERROR) { jack_error("Fatal error : network unreachable - %s", StrError(NET_ERROR_CODE)); return NET_SOCKET_ERROR; } - //bind the socket + // bind the socket if (fSocket.Bind() == SOCKET_ERROR) { jack_error("Can't bind the socket : %s", StrError(NET_ERROR_CODE)); return NET_SOCKET_ERROR; } - //timeout on receive + // timeout on receive if (fSocket.SetTimeOut(SLAVE_INIT_TIMEOUT) == SOCKET_ERROR) jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE)); - //disable local loop + // disable local loop if (fSocket.SetLocalLoop() == SOCKET_ERROR) jack_error("Can't disable multicast loop : %s", StrError(NET_ERROR_CODE)); - //send 'AVAILABLE' until 'SLAVE_SETUP' received + // send 'AVAILABLE' until 'SLAVE_SETUP' received jack_info("Waiting for a master..."); do { - //send 'available' + // send 'available' session_params_t net_params; memset(&net_params, 0, sizeof(session_params_t)); SessionParamsHToN(&fParams, &net_params); if (fSocket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR) jack_error("Error in data send : %s", StrError(NET_ERROR_CODE)); - //filter incoming packets : don't exit while no error is detected + // filter incoming packets : don't exit while no error is detected memset(&net_params, 0, sizeof(session_params_t)); rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0); SessionParamsNToH(&net_params, &host_params); @@ -761,10 +754,10 @@ namespace Jack return NET_CONNECT_ERROR; } - //everything is OK, copy parameters + // everything is OK, copy parameters fParams = host_params; - //connect the socket + // connect the socket if (fSocket.Connect() == SOCKET_ERROR) { jack_error("Error in connect : %s", StrError(NET_ERROR_CODE)); return NET_CONNECT_ERROR; @@ -776,7 +769,7 @@ namespace Jack { jack_log("JackNetSlaveInterface::SendStartToMaster"); - //tell the master to start + // tell the master to start session_params_t net_params; memset(&net_params, 0, sizeof(session_params_t)); SetPacketType(&fParams, START_MASTER); @@ -791,23 +784,26 @@ namespace Jack bool JackNetSlaveInterface::SetParams() { jack_log("JackNetSlaveInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d", - fParams.fSendAudioChannels, fParams.fReturnAudioChannels, fParams.fSendMidiChannels, fParams.fReturnMidiChannels); + fParams.fSendAudioChannels, fParams.fReturnAudioChannels, + fParams.fSendMidiChannels, fParams.fReturnMidiChannels); JackNetInterface::SetParams(); fTxHeader.fDataStream = 'r'; fRxHeader.fDataStream = 's'; - //midi net buffers - if (fParams.fSendMidiChannels > 0) + // midi net buffers + if (fParams.fSendMidiChannels > 0) { fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fRxData); + } - if (fParams.fReturnMidiChannels > 0) + if (fParams.fReturnMidiChannels > 0) { fNetMidiPlaybackBuffer = new NetMidiBuffer(&fParams, fParams.fReturnMidiChannels, fTxData); + } try { - //audio net buffers + // audio net buffers if (fParams.fSendAudioChannels > 0) { switch (fParams.fSampleEncoder) { @@ -857,7 +853,7 @@ namespace Jack return false; } - //set the new buffer sizes + // set the new buffer sizes if (SetNetBufferSize() == SOCKET_ERROR) { jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); goto error; @@ -870,24 +866,36 @@ namespace Jack return false; } + void JackNetSlaveInterface::FatalRecvError() + { + jack_error("Recv connection lost error = %s", StrError(NET_ERROR_CODE)); + throw JackNetException(); + } + + void JackNetSlaveInterface::FatalSendError() + { + jack_error("Send connection lost error = %s", StrError(NET_ERROR_CODE)); + throw JackNetException(); + } + int JackNetSlaveInterface::Recv(size_t size, int flags) { int rx_bytes = fSocket.Recv(fRxBuffer, size, flags); - //handle errors + // handle errors if (rx_bytes == SOCKET_ERROR) { /* net_error_t error = fSocket.GetError(); - //no data isn't really an error in realtime processing, so just return 0 + // no data isn't really an error in realtime processing, so just return 0 if (error == NET_NO_DATA) { jack_error("No data, is the master still running ?"); - //if a network error occurs, this exception will restart the driver + // if a network error occurs, this exception will restart the driver } else if (error == NET_CONN_ERROR) { - FatalError(); + FatalRecvError(); } else { jack_error("Fatal error in slave receive : %s", StrError(NET_ERROR_CODE)); } */ - FatalError(); + FatalRecvError(); } packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer); @@ -895,30 +903,24 @@ namespace Jack return rx_bytes; } - void JackNetSlaveInterface::FatalError() - { - jack_error("Send connection lost"); - throw JackNetException(); - } - int JackNetSlaveInterface::Send(size_t size, int flags) { packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer); PacketHeaderHToN(header, header); int tx_bytes = fSocket.Send(fTxBuffer, size, flags); - //handle errors + // handle errors if (tx_bytes == SOCKET_ERROR) { /* net_error_t error = fSocket.GetError(); - //if a network error occurs, this exception will restart the driver + // if a network error occurs, this exception will restart the driver if (error == NET_CONN_ERROR) { - FatalError(); + FatalSendError(); } else { jack_error("Fatal error in slave send : %s", StrError(NET_ERROR_CODE)); } */ - FatalError(); + FatalSendError(); } return tx_bytes; } @@ -928,19 +930,16 @@ namespace Jack int rx_bytes = 0; packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); - //receive sync (launch the cycle) + // receive sync (launch the cycle) do { rx_bytes = Recv(fParams.fMtu, 0); - //connection issue, send will detect it, so don't skip the cycle (return 0) - if (rx_bytes == SOCKET_ERROR) + // connection issue, send will detect it, so don't skip the cycle (return 0) + if (rx_bytes == SOCKET_ERROR) { return rx_bytes; + } } while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's')); - // Read active ports list - if (fNetAudioPlaybackBuffer) - fNetAudioPlaybackBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); - fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; return rx_bytes; } @@ -952,43 +951,29 @@ namespace Jack packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); while (!fRxHeader.fIsLastPckt) { - //how much data is queued on the rx buffer ? + // how much data is queued on the rx buffer ? rx_bytes = Recv(fParams.fMtu, MSG_PEEK); - //error here, problem with recv, just skip the cycle (return -1) - if (rx_bytes == SOCKET_ERROR) + // error here, problem with recv, just skip the cycle (return -1) + if (rx_bytes == SOCKET_ERROR) { return rx_bytes; + } if (rx_bytes && (rx_head->fDataStream == 's') && (rx_head->fID == fParams.fID)) { - switch (rx_head->fDataType) - { - case 'm': //midi - rx_bytes = Recv(rx_head->fPacketSize, 0); - fRxHeader.fCycle = rx_head->fCycle; - fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fNetMidiCaptureBuffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); - // Last midi packet is received, so finish rendering... - if (++recvd_midi_pckt == rx_head->fNumPacket) - fNetMidiCaptureBuffer->RenderToJackPorts(); + // read data + switch (rx_head->fDataType) { + + case 'm': // midi + rx_bytes = MidiRecv(rx_head, fNetMidiCaptureBuffer, recvd_midi_pckt); break; - case 'a': //audio - rx_bytes = Recv(rx_head->fPacketSize, 0); - fRxHeader.fCycle = rx_head->fCycle; - fRxHeader.fSubCycle = rx_head->fSubCycle; - fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fRxHeader.fActivePorts = rx_head->fActivePorts; - rx_bytes = fNetAudioCaptureBuffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE, fRxHeader.fActivePorts); - // Last audio packet is received, so finish rendering... - if (fRxHeader.fIsLastPckt) - fNetAudioCaptureBuffer->RenderToJackPorts(); + case 'a': // audio + rx_bytes = AudioRecv(rx_head, fNetAudioCaptureBuffer); break; - case 's': //sync + case 's': // sync jack_info("NetSlave : overloaded, skipping receive"); - // TODO : finish midi and audio rendering ? - fNetAudioCaptureBuffer->RenderToJackPorts(); - return NET_PACKET_ERROR; + return FinishRecv(fNetAudioCaptureBuffer); } } } @@ -999,7 +984,7 @@ namespace Jack int JackNetSlaveInterface::SyncSend() { - //tx header + // tx header if (fParams.fSlaveSyncMode) { fTxHeader.fCycle = fRxHeader.fCycle; } else { @@ -1010,86 +995,62 @@ namespace Jack fTxHeader.fIsLastPckt = (fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ? 1 : 0; fTxHeader.fPacketSize = fParams.fMtu; - // Write active ports list - if (fNetAudioCaptureBuffer) - fNetAudioCaptureBuffer->ActivePortsToNetwork(fTxData, fTxHeader.fActivePorts); - memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + // PacketHeaderDisplay(&fTxHeader); return Send(fTxHeader.fPacketSize, 0); } int JackNetSlaveInterface::DataSend() { - uint subproc, data_size; - - //midi - if (fParams.fReturnMidiChannels > 0) { - //set global header fields and get the number of midi packets - fTxHeader.fDataType = 'm'; - data_size = fNetMidiPlaybackBuffer->RenderFromJackPorts(); - fTxHeader.fNumPacket = fNetMidiPlaybackBuffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE); - - for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { - fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && !fParams.fReturnAudioChannels) ? 1 : 0; - fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiPlaybackBuffer->RenderToNetwork(subproc, data_size); - memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) - return SOCKET_ERROR; - } - } - - //audio - if (fParams.fReturnAudioChannels > 0) { - - fTxHeader.fDataType = 'a'; - fNetAudioPlaybackBuffer->RenderFromJackPorts(); - fTxHeader.fNumPacket = fNetAudioPlaybackBuffer->GetNumPackets(); - - for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { - fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; - fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioPlaybackBuffer->RenderToNetwork(subproc, fTxHeader.fActivePorts); - memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - //PacketHeaderDisplay(&fTxHeader); - if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) - return SOCKET_ERROR; - } + if (MidiSend(fNetMidiPlaybackBuffer, fParams.fReturnMidiChannels, fParams.fReturnAudioChannels) == SOCKET_ERROR) { + return SOCKET_ERROR; } - return 0; + return AudioSend(fNetAudioPlaybackBuffer, fParams.fReturnAudioChannels); } - //network sync------------------------------------------------------------------------ + // network sync------------------------------------------------------------------------ void JackNetSlaveInterface::EncodeSyncPacket() { - //this method contains every step of sync packet informations coding - //first of all, reset sync packet - memset(fTxData, 0, PACKET_AVAILABLE_SIZE); - //then first step : transport + // This method contains every step of sync packet informations coding + // first of all, clear sync packet + memset(fTxData, 0, PACKET_AVAILABLE_SIZE(&fParams)); + + // then first step : transport if (fParams.fTransportSync) { - // desactivated... - //EncodeTransportData(); - TransportDataHToN(&fReturnTransportData, &fReturnTransportData); - //copy to TxBuffer + EncodeTransportData(); + TransportDataHToN(&fReturnTransportData, &fReturnTransportData); + // copy to TxBuffer memcpy(fTxData, &fReturnTransportData, sizeof(net_transport_data_t)); } - //then others - //... + // then others + // ... + + // Transport is not used for now... + + // Write active ports list + fTxHeader.fActivePorts = (fNetAudioCaptureBuffer) ? fNetAudioCaptureBuffer->ActivePortsToNetwork(fTxData) : 0; } void JackNetSlaveInterface::DecodeSyncPacket() { - //this method contains every step of sync packet informations decoding process - //first : transport + // This method contains every step of sync packet informations decoding process + // first : transport if (fParams.fTransportSync) { - //copy received transport data to transport data structure + // copy received transport data to transport data structure memcpy(&fSendTransportData, fRxData, sizeof(net_transport_data_t)); - TransportDataNToH(&fSendTransportData, &fSendTransportData); - // desactivated... - //DecodeTransportData(); + TransportDataNToH(&fSendTransportData, &fSendTransportData); + DecodeTransportData(); + } + // then others + // ... + + // Transport not used for now... + packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); + + // Read active ports list + if (fNetAudioPlaybackBuffer) { + fNetAudioPlaybackBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); } - //then others - //... } } diff --git a/common/JackNetInterface.h b/common/JackNetInterface.h index 082292a2..45a42cb9 100644 --- a/common/JackNetInterface.h +++ b/common/JackNetInterface.h @@ -1,5 +1,4 @@ /* -Copyright (C) 2001 Paul Davis Copyright (C) 2008-2011 Romain Moret at Grame This program is free software; you can redistribute it and/or modify @@ -25,8 +24,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. namespace Jack { + +#define DEFAULT_MULTICAST_IP "225.3.19.154" +#define DEFAULT_PORT 19000 +#define DEFAULT_MTU 1500 + +#define SLAVE_SETUP_RETRY 5 + +#define MANAGER_INIT_TIMEOUT 2000000 // in usec +#define MASTER_INIT_TIMEOUT 1000000 // in usec +#define SLAVE_INIT_TIMEOUT 1000000 // in usec + +#define NETWORK_MAX_LATENCY 20 + /** - \Brief This class describes the basic Net Interface, used by both master and slave + \Brief This class describes the basic Net Interface, used by both master and slave. */ class SERVER_EXPORT JackNetInterface @@ -40,7 +52,7 @@ namespace Jack JackNetSocket fSocket; char fMulticastIP[32]; - //headers + // headers packet_header_t fTxHeader; packet_header_t fRxHeader; @@ -48,31 +60,31 @@ namespace Jack net_transport_data_t fSendTransportData; net_transport_data_t fReturnTransportData; - //network buffers + // network buffers char* fTxBuffer; char* fRxBuffer; char* fTxData; char* fRxData; - //jack buffers + // JACK buffers NetMidiBuffer* fNetMidiCaptureBuffer; NetMidiBuffer* fNetMidiPlaybackBuffer; NetAudioBuffer* fNetAudioCaptureBuffer; NetAudioBuffer* fNetAudioPlaybackBuffer; - //utility methods + // utility methods int SetNetBufferSize(); void FreeNetworkBuffers(); - //virtual methods : depends on the sub class master/slave + // virtual methods : depends on the sub class master/slave virtual bool SetParams(); virtual bool Init() = 0; - //transport + // transport virtual void EncodeTransportData() = 0; virtual void DecodeTransportData() = 0; - //sync packet + // sync packet virtual void EncodeSyncPacket() = 0; virtual void DecodeSyncPacket() = 0; @@ -84,14 +96,23 @@ namespace Jack virtual int Send(size_t size, int flags) = 0; virtual int Recv(size_t size, int flags) = 0; - virtual void FatalError() = 0; + virtual void FatalRecvError() = 0; + virtual void FatalSendError() = 0; + + int MidiSend(NetMidiBuffer* buffer, int midi_channnels, int audio_channels); + int AudioSend(NetAudioBuffer* buffer, int audio_channels); + + int MidiRecv(packet_header_t* rx_head, NetMidiBuffer* buffer, uint& recvd_midi_pckt); + int AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer); + + int FinishRecv(NetAudioBuffer* buffer); + + public: JackNetInterface(); JackNetInterface(const char* multicast_ip, int port); JackNetInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip); - public: - virtual ~JackNetInterface(); }; @@ -106,7 +127,9 @@ namespace Jack protected: bool fRunning; - int fCycleOffset; + + int fCurrentCycleOffset; + int fMaxCycleOffset; int fLastfCycleOffset; bool Init(); @@ -121,24 +144,27 @@ namespace Jack int DataRecv(); int DataSend(); - //sync packet + // sync packet void EncodeSyncPacket(); void DecodeSyncPacket(); - int Send ( size_t size, int flags ); - int Recv ( size_t size, int flags ); + int Send(size_t size, int flags); + int Recv(size_t size, int flags); bool IsSynched(); - void FatalError(); + void FatalRecvError(); + void FatalSendError(); public: - JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCycleOffset(0), fLastfCycleOffset(0) + + JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCurrentCycleOffset(0), fMaxCycleOffset(0), fLastfCycleOffset(0) {} - JackNetMasterInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) - : JackNetInterface ( params, socket, multicast_ip ) + JackNetMasterInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip) + : JackNetInterface(params, socket, multicast_ip) {} - ~JackNetMasterInterface() + + virtual~JackNetMasterInterface() {} }; @@ -154,7 +180,7 @@ namespace Jack static uint fSlaveCounter; bool Init(); - bool InitConnection(int time_out); + bool InitConnection(int time_out_sec); bool InitRendering(); net_status_t SendAvailableToMaster(long count = LONG_MAX); // long here (and not int...) @@ -168,65 +194,47 @@ namespace Jack int DataRecv(); int DataSend(); - //sync packet + // sync packet void EncodeSyncPacket(); void DecodeSyncPacket(); - int Recv ( size_t size, int flags ); - int Send ( size_t size, int flags ); + int Recv(size_t size, int flags); + int Send(size_t size, int flags); + + void FatalRecvError(); + void FatalSendError(); - void FatalError(); + void InitAPI() + { + // open Socket API with the first slave + if (fSlaveCounter++ == 0) { + if (SocketAPIInit() < 0) { + jack_error("Can't init Socket API, exiting..."); + throw std::bad_alloc(); + } + } + } public: JackNetSlaveInterface() : JackNetInterface() { - //open Socket API with the first slave - if ( fSlaveCounter++ == 0 ) - { - if ( SocketAPIInit() < 0 ) - { - jack_error ( "Can't init Socket API, exiting..." ); - throw -1; - } - } + InitAPI(); } - JackNetSlaveInterface ( const char* ip, int port ) : JackNetInterface ( ip, port ) + JackNetSlaveInterface(const char* ip, int port) : JackNetInterface(ip, port) { - //open Socket API with the first slave - if ( fSlaveCounter++ == 0 ) - { - if ( SocketAPIInit() < 0 ) - { - jack_error ( "Can't init Socket API, exiting..." ); - throw -1; - } - } + InitAPI(); } - ~JackNetSlaveInterface() + virtual ~JackNetSlaveInterface() { - //close Socket API with the last slave - if ( --fSlaveCounter == 0 ) + // close Socket API with the last slave + if (--fSlaveCounter == 0) { SocketAPIEnd(); + } } }; } -#define DEFAULT_MULTICAST_IP "225.3.19.154" -#define DEFAULT_PORT 19000 -#define DEFAULT_MTU 1500 - -#define SLAVE_SETUP_RETRY 5 - -#define MASTER_INIT_TIMEOUT 1000000 // in usec -#define SLAVE_INIT_TIMEOUT 1000000 // in usec - -#define CYCLE_OFFSET_FAST 0 -#define CYCLE_OFFSET_NORMAL 1 -#define CYCLE_OFFSET_SLOW 2 -//#define CYCLE_OFFSET_SLOW 30 -#define MAX_LATENCY CYCLE_OFFSET_SLOW * 4 - #endif diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index a0c14de3..4a813b9b 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (C) 2008-2011 Romain Moret at Grame +Copyright(C) 2008-2011 Romain Moret at 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 @@ -29,13 +29,13 @@ namespace Jack { //JackNetMaster****************************************************************************************************** - JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip) - : JackNetMasterInterface ( params, socket, multicast_ip ) + JackNetMaster::JackNetMaster(JackNetSocket& socket, session_params_t& params, const char* multicast_ip) + : JackNetMasterInterface(params, socket, multicast_ip) { - jack_log ( "JackNetMaster::JackNetMaster" ); + jack_log("JackNetMaster::JackNetMaster"); //settings - fClientName = const_cast<char*> ( fParams.fName ); + fClientName = const_cast<char*>(fParams.fName); fJackClient = NULL; fSendTransportData.fState = -1; fReturnTransportData.fState = -1; @@ -44,64 +44,59 @@ namespace Jack //jack audio ports fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels]; - for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ ) + for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) { fAudioCapturePorts[port_index] = NULL; + } + fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels]; - for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ ) + for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) { fAudioPlaybackPorts[port_index] = NULL; + } + //jack midi ports fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels]; - for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ ) + for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) { fMidiCapturePorts[port_index] = NULL; + } + fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels]; - for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ ) + for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { fMidiPlaybackPorts[port_index] = NULL; + } //monitor #ifdef JACK_MONITOR - fPeriodUsecs = ( int ) ( 1000000.f * ( ( float ) fParams.fPeriodSize / ( float ) fParams.fSampleRate ) ); + fPeriodUsecs = (int)(1000000.f * ((float) fParams.fPeriodSize / (float) fParams.fSampleRate)); string plot_name; - plot_name = string ( fParams.fName ); - plot_name += string ( "_master" ); - plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" ); - switch ( fParams.fNetworkMode ) - { - case 's' : - plot_name += string ( "_slow" ); - break; - case 'n' : - plot_name += string ( "_normal" ); - break; - case 'f' : - plot_name += string ( "_fast" ); - break; - } - fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name ); + plot_name = string(fParams.fName); + plot_name += string("_master"); + plot_name += string((fParams.fSlaveSyncMode) ? "_sync" : "_async"); + plot_name += string("_latency"); + fNetTimeMon = new JackGnuPlotMonitor<float>(128, 4, plot_name); string net_time_mon_fields[] = { - string ( "sync send" ), - string ( "end of send" ), - string ( "sync recv" ), - string ( "end of cycle" ) + string("sync send"), + string("end of send"), + string("sync recv"), + string("end of cycle") }; string net_time_mon_options[] = { - string ( "set xlabel \"audio cycles\"" ), - string ( "set ylabel \"% of audio cycle\"" ) + string("set xlabel \"audio cycles\""), + string("set ylabel \"% of audio cycle\"") }; - fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 ); + fNetTimeMon->SetPlotFile(net_time_mon_options, 2, net_time_mon_fields, 4); #endif } JackNetMaster::~JackNetMaster() { - jack_log ( "JackNetMaster::~JackNetMaster, ID %u", fParams.fID ); + jack_log("JackNetMaster::~JackNetMaster ID = %u", fParams.fID); - if ( fJackClient ) - { - jack_deactivate ( fJackClient ); + if (fJackClient) { + jack_deactivate(fJackClient); FreePorts(); - jack_client_close ( fJackClient ); + jack_client_close(fJackClient); } delete[] fAudioCapturePorts; delete[] fAudioPlaybackPorts; @@ -117,33 +112,33 @@ namespace Jack { //network init if (!JackNetMasterInterface::Init()) { - jack_error("JackNetMasterInterface::Init() error..." ); + jack_error("JackNetMasterInterface::Init() error..."); return false; } //set global parameters if (!SetParams()) { - jack_error("SetParams error..." ); + jack_error("SetParams error..."); return false; } //jack client and process jack_status_t status; - if ( ( fJackClient = jack_client_open ( fClientName, JackNullOption, &status, NULL ) ) == NULL ) - { - jack_error ( "Can't open a new jack client" ); + if ((fJackClient = jack_client_open(fClientName, JackNullOption, &status, NULL)) == NULL) { + jack_error("Can't open a new JACK client"); return false; } - if (jack_set_process_callback(fJackClient, SetProcess, this ) < 0) - goto fail; + if (jack_set_process_callback(fJackClient, SetProcess, this) < 0) { + goto fail; + } - if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0) - goto fail; + if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0) { + goto fail; + } - if ( AllocPorts() != 0 ) - { - jack_error ( "Can't allocate jack ports" ); + if (AllocPorts() != 0) { + jack_error("Can't allocate JACK ports"); goto fail; } @@ -151,20 +146,20 @@ namespace Jack fRunning = true; //finally activate jack client - if ( jack_activate ( fJackClient ) != 0 ) - { - jack_error ( "Can't activate jack client" ); + if (jack_activate(fJackClient) != 0) { + jack_error("Can't activate JACK client"); goto fail; } - if (auto_connect) + if (auto_connect) { ConnectPorts(); - jack_info ( "New NetMaster started" ); + } + jack_info("New NetMaster started"); return true; fail: FreePorts(); - jack_client_close ( fJackClient ); + jack_client_close(fJackClient); fJackClient = NULL; return false; } @@ -174,76 +169,47 @@ namespace Jack { int i; char name[24]; - jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient ); + jack_nframes_t port_latency = jack_get_buffer_size(fJackClient); jack_latency_range_t range; - jack_log ( "JackNetMaster::AllocPorts" ); + jack_log("JackNetMaster::AllocPorts"); //audio - for ( i = 0; i < fParams.fSendAudioChannels; i++ ) - { - sprintf ( name, "to_slave_%d", i+1 ); - if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL ) + for (i = 0; i < fParams.fSendAudioChannels; i++) { + sprintf(name, "to_slave_%d", i+1); + if ((fAudioCapturePorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) return -1; //port latency 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 ); - if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) + for (i = 0; i < fParams.fReturnAudioChannels; i++) { + sprintf(name, "from_slave_%d", i+1); + if ((fAudioPlaybackPorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) return -1; //port latency - switch ( fParams.fNetworkMode ) - { - case 'f' : - range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency; - jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); - break; - case 'n' : - range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; - jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); - break; - case 's' : - range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; - jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); - break; - } + range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; + jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); } //midi - for ( i = 0; i < fParams.fSendMidiChannels; i++ ) - { - sprintf ( name, "midi_to_slave_%d", i+1 ); - if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL ) + for (i = 0; i < fParams.fSendMidiChannels; i++) { + sprintf(name, "midi_to_slave_%d", i+1); + if ((fMidiCapturePorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) return -1; //port latency range.min = range.max = 0; jack_port_set_latency_range(fMidiCapturePorts[i], JackCaptureLatency, &range); } - for ( i = 0; i < fParams.fReturnMidiChannels; i++ ) - { - sprintf ( name, "midi_from_slave_%d", i+1 ); - if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) + + for (i = 0; i < fParams.fReturnMidiChannels; i++) { + sprintf(name, "midi_from_slave_%d", i+1); + if ((fMidiPlaybackPorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) return -1; //port latency - switch ( fParams.fNetworkMode ) - { - case 'f' : - range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency; - jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); - break; - case 'n' : - range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; - jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); - break; - case 's' : - range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; - jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); - break; - } + range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; + jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); } return 0; } @@ -271,21 +237,29 @@ namespace Jack void JackNetMaster::FreePorts() { - jack_log ( "JackNetMaster::FreePorts, ID %u", fParams.fID ); + jack_log("JackNetMaster::FreePorts ID = %u", fParams.fID); int port_index; - for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ ) - if ( fAudioCapturePorts[port_index] ) - jack_port_unregister ( fJackClient, fAudioCapturePorts[port_index] ); - for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ ) - if ( fAudioPlaybackPorts[port_index] ) - jack_port_unregister ( fJackClient, fAudioPlaybackPorts[port_index] ); - for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ ) - if ( fMidiCapturePorts[port_index] ) - jack_port_unregister ( fJackClient, fMidiCapturePorts[port_index] ); - for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ ) - if ( fMidiPlaybackPorts[port_index] ) - jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] ); + for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) { + if (fAudioCapturePorts[port_index]) { + jack_port_unregister(fJackClient, fAudioCapturePorts[port_index]); + } + } + for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) { + if (fAudioPlaybackPorts[port_index]) { + jack_port_unregister(fJackClient, fAudioPlaybackPorts[port_index]); + } + } + for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) { + if (fMidiCapturePorts[port_index]) { + jack_port_unregister(fJackClient, fMidiCapturePorts[port_index]); + } + } + for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { + if (fMidiPlaybackPorts[port_index]) { + jack_port_unregister(fJackClient, fMidiPlaybackPorts[port_index]); + } + } } //transport--------------------------------------------------------------------------- @@ -296,26 +270,26 @@ namespace Jack fSendTransportData.fTimebaseMaster = NO_CHANGE; //update state and position - fSendTransportData.fState = static_cast<uint> ( jack_transport_query ( fJackClient, &fSendTransportData.fPosition ) ); + fSendTransportData.fState = static_cast<uint>(jack_transport_query(fJackClient, &fSendTransportData.fPosition)); //is it a new state ? - fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) && - ( fSendTransportData.fState != fReturnTransportData.fState ) ); - if ( fSendTransportData.fNewState ) - jack_info ( "Sending '%s' to '%s' frame = %ld", GetTransportState ( fSendTransportData.fState ), fParams.fName, fSendTransportData.fPosition.frame ); + fSendTransportData.fNewState = ((fSendTransportData.fState != fLastTransportState) && (fSendTransportData.fState != fReturnTransportData.fState)); + if (fSendTransportData.fNewState) { + jack_info("Sending '%s' to '%s' frame = %ld", GetTransportState(fSendTransportData.fState), fParams.fName, fSendTransportData.fPosition.frame); + } fLastTransportState = fSendTransportData.fState; } void JackNetMaster::DecodeTransportData() { //is there timebase master change ? - if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE ) - { + if (fReturnTransportData.fTimebaseMaster != NO_CHANGE) { + int timebase = 0; - switch ( fReturnTransportData.fTimebaseMaster ) + switch (fReturnTransportData.fTimebaseMaster) { case RELEASE_TIMEBASEMASTER : - timebase = jack_release_timebase ( fJackClient ); + timebase = jack_release_timebase(fJackClient); if (timebase < 0) { jack_error("Can't release timebase master"); } else { @@ -324,7 +298,7 @@ namespace Jack break; case TIMEBASEMASTER : - timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this ); + timebase = jack_set_timebase_callback(fJackClient, 0, SetTimebaseCallback, this); if (timebase < 0) { jack_error("Can't set a new timebase master"); } else { @@ -333,7 +307,7 @@ namespace Jack break; case CONDITIONAL_TIMEBASEMASTER : - timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this ); + timebase = jack_set_timebase_callback(fJackClient, 1, SetTimebaseCallback, this); if (timebase != EBUSY) { if (timebase < 0) jack_error("Can't set a new timebase master"); @@ -345,39 +319,39 @@ namespace Jack } //is the slave in a new transport state and is this state different from master's ? - if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) ) - { - switch ( fReturnTransportData.fState ) + if (fReturnTransportData.fNewState && (fReturnTransportData.fState != jack_transport_query(fJackClient, NULL))) { + + switch (fReturnTransportData.fState) { case JackTransportStopped : - jack_transport_stop ( fJackClient ); - jack_info ( "'%s' stops transport", fParams.fName ); + 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); + 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 ); + jack_info("'%s' is ready to roll...", fParams.fName); break; case JackTransportRolling : - jack_info ( "'%s' is rolling", fParams.fName ); + jack_info("'%s' is rolling", fParams.fName); break; } } } - void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg ) + void JackNetMaster::SetTimebaseCallback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg) { - static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos ); + static_cast<JackNetMaster*>(arg)->TimebaseCallback(pos); } - void JackNetMaster::TimebaseCallback ( jack_position_t* pos ) + void JackNetMaster::TimebaseCallback(jack_position_t* pos) { pos->bar = fReturnTransportData.fPosition.bar; pos->beat = fReturnTransportData.fPosition.beat; @@ -393,7 +367,7 @@ namespace Jack bool JackNetMaster::IsSlaveReadyToRoll() { - return ( fReturnTransportData.fState == JackTransportNetStarting ); + return (fReturnTransportData.fState == JackTransportNetStarting); } int JackNetMaster::SetBufferSize(jack_nframes_t nframes, void* arg) @@ -420,8 +394,9 @@ namespace Jack { int res; - if (!fRunning) + if (!fRunning) { return 0; + } #ifdef JACK_MONITOR jack_time_t begin_time = GetMicroSeconds(); @@ -437,11 +412,12 @@ namespace Jack for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) { #ifdef OPTIMIZED_PROTOCOL - if ((intptr_t)fNetAudioCaptureBuffer->GetBuffer(audio_port_index) == -1) { + if (fNetAudioCaptureBuffer->GetConnected(audio_port_index)) { // Port is connected on other side... fNetAudioCaptureBuffer->SetBuffer(audio_port_index, - static_cast<sample_t*>(jack_port_get_buffer_nulled(fAudioCapturePorts[audio_port_index], - fParams.fPeriodSize))); + ((jack_port_connected(fAudioCapturePorts[audio_port_index]) > 0) + ? static_cast<sample_t*>(jack_port_get_buffer(fAudioCapturePorts[audio_port_index], fParams.fPeriodSize)) + : NULL)); } else { fNetAudioCaptureBuffer->SetBuffer(audio_port_index, NULL); } @@ -461,13 +437,19 @@ namespace Jack for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) { #ifdef OPTIMIZED_PROTOCOL - fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, - static_cast<sample_t*>(jack_port_get_buffer_nulled(fAudioPlaybackPorts[audio_port_index], - fParams.fPeriodSize))); + sample_t* out = (jack_port_connected(fAudioPlaybackPorts[audio_port_index]) > 0) + ? static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], fParams.fPeriodSize)) + : NULL; + if (out) { + memset(out, 0, sizeof(float) * fParams.fPeriodSize); + } + fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out); #else - fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, - static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], - fParams.fPeriodSize))); + sample_t* out = static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], fParams.fPeriodSize)); + if (out) { + memset(out, 0, sizeof(float) * fParams.fPeriodSize); + } + fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out))); #endif } @@ -476,19 +458,21 @@ namespace Jack //encode the first packet EncodeSyncPacket(); - if (SyncSend() == SOCKET_ERROR) + if (SyncSend() == SOCKET_ERROR) { return SOCKET_ERROR; + } #ifdef JACK_MONITOR - fNetTimeMon->Add((((float) (GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs ) * 100.f); + fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); #endif //send data - if (DataSend() == SOCKET_ERROR) + if (DataSend() == SOCKET_ERROR) { return SOCKET_ERROR; + } #ifdef JACK_MONITOR - fNetTimeMon->Add((((float) (GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); + fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); #endif } else { @@ -497,8 +481,9 @@ namespace Jack //receive sync res = SyncRecv(); - if ((res == 0) || (res == SOCKET_ERROR)) + if ((res == 0) || (res == SOCKET_ERROR)) { return res; + } /* switch (SyncRecv()) { @@ -521,7 +506,7 @@ namespace Jack */ #ifdef JACK_MONITOR - fNetTimeMon->Add ((((float) (GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); + fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); #endif //decode sync @@ -532,7 +517,7 @@ namespace Jack if ((res == 0) || (res == SOCKET_ERROR)) { return res; } else if (res == NET_PACKET_ERROR) { - // Well not a real XRun, but... + // Well not a real XRun... JackServerGlobals::fInstance->GetEngine()->NotifyXRun(GetMicroSeconds(), 0); } @@ -557,19 +542,19 @@ namespace Jack */ #ifdef JACK_MONITOR - fNetTimeMon->AddLast((((float) (GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); + fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); #endif return 0; } //JackNetMasterManager*********************************************************************************************** - JackNetMasterManager::JackNetMasterManager ( jack_client_t* client, const JSList* params ) : fSocket() + JackNetMasterManager::JackNetMasterManager(jack_client_t* client, const JSList* params) : fSocket() { - jack_log ( "JackNetMasterManager::JackNetMasterManager" ); + jack_log("JackNetMasterManager::JackNetMasterManager"); fManagerClient = client; - fManagerName = jack_get_client_name ( fManagerClient ); + fManagerName = jack_get_client_name(fManagerClient); fGlobalID = 0; fRunning = true; fAutoConnect = false; @@ -588,20 +573,21 @@ namespace Jack strcpy(fMulticastIP, DEFAULT_MULTICAST_IP); } - for ( node = params; node; node = jack_slist_next ( node ) ) - { - param = ( const jack_driver_param_t* ) node->data; - switch ( param->character ) + for (node = params; node; node = jack_slist_next(node)) { + + param = (const jack_driver_param_t*) node->data; + switch (param->character) { case 'a' : - if (strlen (param->value.str) < 32) + if (strlen(param->value.str) < 32) { strcpy(fMulticastIP, param->value.str); - else + } 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 ); + fSocket.SetPort(param->value.ui); break; case 'c': @@ -611,26 +597,29 @@ namespace Jack } //set sync callback - jack_set_sync_callback ( fManagerClient, SetSyncCallback, this ); + jack_set_sync_callback(fManagerClient, SetSyncCallback, this); //activate the client (for sync callback) - if ( jack_activate ( fManagerClient ) != 0 ) - jack_error ( "Can't activate the network manager client, transport disabled" ); + if (jack_activate(fManagerClient) != 0) { + jack_error("Can't activate the NetManager client, transport disabled"); + } //launch the manager thread - if ( jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this ) ) - jack_error ( "Can't create the network manager control thread" ); + if (jack_client_create_thread(fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this)) { + jack_error("Can't create the NetManager control thread"); + } } JackNetMasterManager::~JackNetMasterManager() { - jack_log ( "JackNetMasterManager::~JackNetMasterManager" ); - jack_info ( "Exiting net manager..." ); + jack_log("JackNetMasterManager::~JackNetMasterManager"); + jack_info("Exiting NetManager..."); fRunning = false; - jack_client_kill_thread ( fManagerClient, fManagerThread ); + jack_client_kill_thread(fManagerClient, fManagerThread); master_list_t::iterator it; - for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) - delete ( *it ); + for (it = fMasterList.begin(); it != fMasterList.end(); it++) { + delete(*it); + } fSocket.Close(); SocketAPIEnd(); } @@ -653,35 +642,37 @@ namespace Jack return count; } - int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg ) + int JackNetMasterManager::SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg) { - return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos ); + return static_cast<JackNetMasterManager*>(arg)->SyncCallback(state, pos); } - int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos ) + int JackNetMasterManager::SyncCallback(jack_transport_state_t state, jack_position_t* pos) { //check if each slave is ready to roll int ret = 1; master_list_it_t it; - for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) - if ( ! ( *it )->IsSlaveReadyToRoll() ) + for (it = fMasterList.begin(); it != fMasterList.end(); it++) { + if (!(*it)->IsSlaveReadyToRoll()) { ret = 0; - jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" ); + } + } + jack_log("JackNetMasterManager::SyncCallback returns '%s'", (ret) ? "true" : "false"); return ret; } - void* JackNetMasterManager::NetManagerThread ( void* arg ) + void* JackNetMasterManager::NetManagerThread(void* arg) { - JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg ); - jack_info ( "Starting Jack Network Manager" ); - jack_info ( "Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort() ); + JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*>(arg); + jack_info("Starting Jack NetManager"); + jack_info("Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort()); master_manager->Run(); return NULL; } void JackNetMasterManager::Run() { - jack_log ( "JackNetMasterManager::Run" ); + jack_log("JackNetMasterManager::Run"); //utility variables int attempt = 0; @@ -691,75 +682,75 @@ namespace Jack JackNetMaster* net_master; //init socket API (win32) - if ( SocketAPIInit() < 0 ) - { - jack_error ( "Can't init Socket API, exiting..." ); + if (SocketAPIInit() < 0) { + jack_error("Can't init Socket API, exiting..."); return; } //socket - if ( fSocket.NewSocket() == SOCKET_ERROR ) - { - jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE ) ); + if (fSocket.NewSocket() == SOCKET_ERROR) { + jack_error("Can't create NetManager input socket : %s", StrError(NET_ERROR_CODE)); return; } //bind the socket to the local port - if ( fSocket.Bind() == SOCKET_ERROR ) - { - jack_error ( "Can't bind the network manager socket : %s", StrError ( NET_ERROR_CODE ) ); + if (fSocket.Bind() == SOCKET_ERROR) { + jack_error("Can't bind NetManager socket : %s", StrError(NET_ERROR_CODE)); fSocket.Close(); return; } //join multicast group - if ( fSocket.JoinMCastGroup ( fMulticastIP ) == SOCKET_ERROR ) - jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE ) ); + if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) { + jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE)); + } //local loop - if ( fSocket.SetLocalLoop() == SOCKET_ERROR ) - jack_error ( "Can't set local loop : %s", StrError ( NET_ERROR_CODE ) ); + if (fSocket.SetLocalLoop() == SOCKET_ERROR) { + jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE)); + } //set a timeout on the multicast receive (the thread can now be cancelled) - if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR ) - jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) ); + if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) { + jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE)); + } //main loop, wait for data, deal with it and wait again do { session_params_t net_params; - rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 ); + rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0); SessionParamsNToH(&net_params, &host_params); - if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) ) - { - jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) ); - if ( ++attempt == 10 ) - { - jack_error ( "Can't receive on the socket, exiting net manager" ); + if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { + jack_error("Error in receive : %s", StrError(NET_ERROR_CODE)); + if (++attempt == 10) { + jack_error("Can't receive on the socket, exiting net manager"); return; } } - if ( rx_bytes == sizeof ( session_params_t ) ) - { - switch ( GetPacketType ( &host_params ) ) + + if (rx_bytes == sizeof(session_params_t)) { + switch (GetPacketType (&host_params)) { case SLAVE_AVAILABLE: - if ( ( net_master = InitMaster ( host_params ) ) ) - SessionParamsDisplay ( &net_master->fParams ); - else - jack_error ( "Can't init new net master..." ); - jack_info ( "Waiting for a slave..." ); + if ((net_master = InitMaster(host_params))) { + SessionParamsDisplay(&net_master->fParams); + } else { + jack_error("Can't init new NetMaster..."); + } + jack_info("Waiting for a slave..."); break; case KILL_MASTER: - if ( KillMaster ( &host_params ) ) - jack_info ( "Waiting for a slave..." ); + if (KillMaster(&host_params)) { + jack_info("Waiting for a slave..."); + } break; default: break; } } } - while ( fRunning ); + while (fRunning); } JackNetMaster* JackNetMasterManager::InitMaster(session_params_t& params) @@ -768,15 +759,15 @@ namespace Jack //check MASTER <<==> SLAVE network protocol coherency if (params.fProtocolVersion != MASTER_PROTOCOL) { - jack_error ( "Error : slave %s is running with a different protocol %d != %d", params.fName, params.fProtocolVersion, MASTER_PROTOCOL); + jack_error("Error : slave %s is running with a different protocol %d != %d", params.fName, params.fProtocolVersion, MASTER_PROTOCOL); return NULL; } //settings - fSocket.GetName ( params.fMasterNetName ); + fSocket.GetName(params.fMasterNetName); params.fID = ++fGlobalID; - params.fSampleRate = jack_get_sample_rate ( fManagerClient ); - params.fPeriodSize = jack_get_buffer_size ( fManagerClient ); + params.fSampleRate = jack_get_sample_rate(fManagerClient); + params.fPeriodSize = jack_get_buffer_size(fManagerClient); if (params.fSendAudioChannels == -1) { params.fSendAudioChannels = CountIO(JackPortIsPhysical | JackPortIsOutput); @@ -800,35 +791,38 @@ namespace Jack return NULL; } - void JackNetMasterManager::SetSlaveName ( session_params_t& params ) + void JackNetMasterManager::SetSlaveName(session_params_t& params) { - jack_log ( "JackNetMasterManager::SetSlaveName" ); + jack_log("JackNetMasterManager::SetSlaveName"); master_list_it_t it; - for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) - if ( strcmp ( ( *it )->fParams.fName, params.fName ) == 0 ) - sprintf ( params.fName, "%s-%u", params.fName, params.fID ); + for (it = fMasterList.begin(); it != fMasterList.end(); it++) { + if (strcmp((*it)->fParams.fName, params.fName) == 0) { + sprintf(params.fName, "%s-%u", params.fName, params.fID); + } + } } - master_list_it_t JackNetMasterManager::FindMaster ( uint32_t id ) + master_list_it_t JackNetMasterManager::FindMaster(uint32_t id) { - jack_log ( "JackNetMasterManager::FindMaster, ID %u", id ); + jack_log("JackNetMasterManager::FindMaster ID = %u", id); master_list_it_t it; - for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) - if ( ( *it )->fParams.fID == id ) + for (it = fMasterList.begin(); it != fMasterList.end(); it++) { + if ((*it)->fParams.fID == id) { return it; + } + } return it; } - int JackNetMasterManager::KillMaster ( session_params_t* params ) + int JackNetMasterManager::KillMaster(session_params_t* params) { - jack_log ( "JackNetMasterManager::KillMaster, ID %u", params->fID ); + jack_log("JackNetMasterManager::KillMaster ID = %u", params->fID); - master_list_it_t master = FindMaster ( params->fID ); - if ( master != fMasterList.end() ) - { - fMasterList.erase ( master ); + master_list_it_t master = FindMaster(params->fID); + if (master != fMasterList.end()) { + fMasterList.erase(master); delete *master; return 1; } @@ -851,7 +845,7 @@ extern "C" desc = jack_driver_descriptor_construct("netmanager", "netjack multi-cast master component", &filler); - strcpy(value.str, DEFAULT_MULTICAST_IP ); + strcpy(value.str, DEFAULT_MULTICAST_IP); jack_driver_descriptor_add_parameter(desc, &filler, "multicast_ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL); value.i = DEFAULT_PORT; @@ -863,48 +857,46 @@ extern "C" return desc; } - SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params ) + SERVER_EXPORT int jack_internal_initialize(jack_client_t* jack_client, const JSList* params) { - if ( master_manager ) - { - jack_error ( "Master Manager already loaded" ); + if (master_manager) { + jack_error("Master Manager already loaded"); return 1; - } - else - { - jack_log ( "Loading Master Manager" ); - master_manager = new Jack::JackNetMasterManager ( jack_client, params ); - return ( master_manager ) ? 0 : 1; + } else { + jack_log("Loading Master Manager"); + master_manager = new Jack::JackNetMasterManager(jack_client, params); + return (master_manager) ? 0 : 1; } } - SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init ) + SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init) { JSList* params = NULL; bool parse_params = true; int res = 1; jack_driver_desc_t* desc = jack_get_descriptor(); - Jack::JackArgParser parser ( load_init ); - if ( parser.GetArgc() > 0 ) - parse_params = parser.ParseParams ( desc, ¶ms ); + Jack::JackArgParser parser(load_init); + if (parser.GetArgc() > 0) { + parse_params = parser.ParseParams(desc, ¶ms); + } if (parse_params) { - res = jack_internal_initialize ( jack_client, params ); - parser.FreeParams ( params ); + res = jack_internal_initialize(jack_client, params); + parser.FreeParams(params); } return res; } - SERVER_EXPORT void jack_finish ( void* arg ) + SERVER_EXPORT void jack_finish(void* arg) { - if ( master_manager ) - { - jack_log ( "Unloading Master Manager" ); + if (master_manager) { + jack_log ("Unloading Master Manager"); delete master_manager; master_manager = NULL; } } + #ifdef __cplusplus } #endif diff --git a/common/JackNetManager.h b/common/JackNetManager.h index 48b6c25c..bc1e790a 100644 --- a/common/JackNetManager.h +++ b/common/JackNetManager.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2008 Grame +Copyright (C) 2008-2011 Romain Moret at 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 @@ -40,9 +40,9 @@ namespace Jack private: - static int SetProcess ( jack_nframes_t nframes, void* arg ); - static int SetBufferSize (jack_nframes_t nframes, void* arg); - static void SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg ); + static int SetProcess(jack_nframes_t nframes, void* arg); + static int SetBufferSize(jack_nframes_t nframes, void* arg); + static void SetTimebaseCallback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg); //jack client jack_client_t* fJackClient; @@ -72,13 +72,13 @@ namespace Jack void DecodeTransportData(); int Process(); - void TimebaseCallback ( jack_position_t* pos ); + void TimebaseCallback(jack_position_t* pos); void ConnectPorts(); public: - JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip); - ~JackNetMaster (); + JackNetMaster(JackNetSocket& socket, session_params_t& params, const char* multicast_ip); + ~JackNetMaster(); bool IsSlaveReadyToRoll(); }; @@ -96,8 +96,8 @@ namespace Jack private: - static int SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg ); - static void* NetManagerThread ( void* arg ); + static int SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg); + static void* NetManagerThread(void* arg); jack_client_t* fManagerClient; const char* fManagerName; @@ -110,18 +110,18 @@ namespace Jack bool fAutoConnect; void Run(); - JackNetMaster* InitMaster ( session_params_t& params ); - master_list_it_t FindMaster ( uint32_t client_id ); - int KillMaster ( session_params_t* params ); - void SetSlaveName ( session_params_t& params ); + JackNetMaster* InitMaster(session_params_t& params); + master_list_it_t FindMaster(uint32_t client_id); + int KillMaster(session_params_t* params); + void SetSlaveName(session_params_t& params); - int SyncCallback ( jack_transport_state_t state, jack_position_t* pos ); + int SyncCallback(jack_transport_state_t state, jack_position_t* pos); int CountIO(int flags); public: - JackNetMasterManager ( jack_client_t* jack_client, const JSList* params); + JackNetMasterManager(jack_client_t* jack_client, const JSList* params); ~JackNetMasterManager(); }; } diff --git a/common/JackNetOneDriver.cpp b/common/JackNetOneDriver.cpp index a7bec4c6..7dd4e69d 100644 --- a/common/JackNetOneDriver.cpp +++ b/common/JackNetOneDriver.cpp @@ -1,6 +1,5 @@ /* -Copyright (C) 2001 Paul Davis -Copyright (C) 2008-2011 Romain Moret at Grame +Copyright (C) 2008-2011 Torben Horn 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 @@ -46,21 +45,21 @@ using namespace std; namespace Jack { -JackNetOneDriver::JackNetOneDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, +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 ) - : JackAudioDriver ( name, alias, engine, table ) + int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val) + : JackTimedDriver(name, alias, engine, table) { - jack_log ( "JackNetOneDriver::JackNetOneDriver port %d", port ); + jack_log("JackNetOneDriver::JackNetOneDriver port %d", port); #ifdef WIN32 WSADATA wsa; int rc = WSAStartup(MAKEWORD(2, 0), &wsa); #endif - netjack_init( & (this->netj), + netjack_init(& (this->netj), NULL, // client name, capture_ports, @@ -88,28 +87,11 @@ JackNetOneDriver::~JackNetOneDriver() } //open, close, attach and detach------------------------------------------------------ -int JackNetOneDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, 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 ) -{ - return JackAudioDriver::Open(buffer_size, - samplerate, - capturing, - playing, - inchannels, - outchannels, - monitor, - capture_driver_name, - playback_driver_name, - capture_latency, - playback_latency); -} int JackNetOneDriver::Close() { // Generic audio driver close - int res = JackAudioDriver::Close(); + int res = JackTimedDriver::Close(); FreePorts(); netjack_release(&netj); @@ -254,8 +236,8 @@ bool JackNetOneDriver::Initialize() //monitor //driver parametering - JackAudioDriver::SetBufferSize ( netj.period_size ); - JackAudioDriver::SetSampleRate ( netj.sample_rate ); + JackTimedDriver::SetBufferSize ( netj.period_size ); + JackTimedDriver::SetSampleRate ( netj.sample_rate ); JackDriver::NotifyBufferSize ( netj.period_size ); JackDriver::NotifySampleRate ( netj.sample_rate ); @@ -269,6 +251,12 @@ bool JackNetOneDriver::Initialize() //jack ports and buffers-------------------------------------------------------------- //driver processes-------------------------------------------------------------------- + +int JackNetOneDriver::Process() +{ + return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); +} + int JackNetOneDriver::Read() { int delay; @@ -951,8 +939,7 @@ extern "C" } try { - Jack::JackDriverClientInterface* driver = - new Jack::JackWaitThreadedDriver ( + 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, diff --git a/common/JackNetOneDriver.h b/common/JackNetOneDriver.h index f0dfc165..ae5fd078 100644 --- a/common/JackNetOneDriver.h +++ b/common/JackNetOneDriver.h @@ -1,6 +1,5 @@ /* -Copyright (C) 2001 Paul Davis -Copyright (C) 2008-2011 Romain Moret at Grame +Copyright (C) 2008-2011 Torben Horn 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 @@ -21,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __JackNetDriver__ #define __JackNetDriver__ -#include "JackAudioDriver.h" +#include "JackTimedDriver.h" #include "netjack.h" #include "netjack_packet.h" @@ -31,7 +30,7 @@ namespace Jack \Brief This class describes the Net Backend */ -class JackNetOneDriver : public JackAudioDriver +class JackNetOneDriver : public JackTimedDriver { private: @@ -59,15 +58,13 @@ class JackNetOneDriver : public JackAudioDriver 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); + virtual ~JackNetOneDriver(); int Close(); int Attach(); int Detach(); + + int Process(); int Read(); int Write(); @@ -77,15 +74,18 @@ class JackNetOneDriver : public JackAudioDriver void FreePorts(); // BufferSize can't be changed - bool IsFixedBufferSize() { + bool IsFixedBufferSize() + { return true; } - int SetBufferSize(jack_nframes_t buffer_size) { + int SetBufferSize(jack_nframes_t buffer_size) + { return -1; } - int SetSampleRate(jack_nframes_t sample_rate) { + int SetSampleRate(jack_nframes_t sample_rate) + { return -1; } diff --git a/common/JackNetTool.cpp b/common/JackNetTool.cpp index 791af963..f5997e3b 100644 --- a/common/JackNetTool.cpp +++ b/common/JackNetTool.cpp @@ -97,12 +97,14 @@ namespace Jack fMaxPcktSize = params->fMtu - sizeof(packet_header_t); fBuffer = new char[fMaxBufsize]; fPortBuffer = new JackMidiBuffer* [fNPorts]; - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { fPortBuffer[port_index] = NULL; + } fNetBuffer = net_buffer; - fCycleSize = params->fMtu * (max(params->fSendMidiChannels, params->fReturnMidiChannels) * - params->fPeriodSize * sizeof(sample_t) / (params->fMtu - sizeof(packet_header_t))); + fCycleBytesSize = params->fMtu + * (max(params->fSendMidiChannels, params->fReturnMidiChannels) + * params->fPeriodSize * sizeof(sample_t) / (params->fMtu - sizeof(packet_header_t))); } NetMidiBuffer::~NetMidiBuffer() @@ -113,14 +115,14 @@ namespace Jack size_t NetMidiBuffer::GetCycleSize() { - return fCycleSize; + return fCycleBytesSize; } int NetMidiBuffer::GetNumPackets(int data_size, int max_size) { - return (data_size % max_size) - ? (data_size / max_size + 1) - : data_size / max_size; + int res1 = data_size % max_size; + int res2 = data_size / max_size; + return (res1) ? res2 + 1 : res2; } void NetMidiBuffer::SetBuffer(int index, JackMidiBuffer* buffer) @@ -137,10 +139,11 @@ namespace Jack { for (int port_index = 0; port_index < fNPorts; port_index++) { for (uint event = 0; event < fPortBuffer[port_index]->event_count; event++) { - if (fPortBuffer[port_index]->IsValid()) + if (fPortBuffer[port_index]->IsValid()) { jack_info("port %d : midi event %u/%u -> time : %u, size : %u", port_index + 1, event + 1, fPortBuffer[port_index]->event_count, fPortBuffer[port_index]->events[event].time, fPortBuffer[port_index]->events[event].size); + } } } } @@ -155,8 +158,9 @@ namespace Jack copy_size = sizeof(JackMidiBuffer) + fPortBuffer[port_index]->event_count * sizeof(JackMidiEvent); memcpy(fBuffer + pos, fPortBuffer[port_index], copy_size); pos += copy_size; - memcpy(fBuffer + pos, fPortBuffer[port_index] + (fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos), - fPortBuffer[port_index]->write_pos); + memcpy(fBuffer + pos, + fPortBuffer[port_index] + (fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos), + fPortBuffer[port_index]->write_pos); pos += fPortBuffer[port_index]->write_pos; JackMidiBuffer* midi_buffer = reinterpret_cast<JackMidiBuffer*>(write_pos); @@ -168,7 +172,7 @@ namespace Jack void NetMidiBuffer::RenderToJackPorts() { int pos = 0; - int copy_size; + size_t copy_size; for (int port_index = 0; port_index < fNPorts; port_index++) { JackMidiBuffer* midi_buffer = reinterpret_cast<JackMidiBuffer*>(fBuffer + pos); @@ -177,7 +181,8 @@ namespace Jack memcpy(fPortBuffer[port_index], fBuffer + pos, copy_size); pos += copy_size; memcpy(fPortBuffer[port_index] + (fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos), - fBuffer + pos, fPortBuffer[port_index]->write_pos); + fBuffer + pos, + fPortBuffer[port_index]->write_pos); pos += fPortBuffer[port_index]->write_pos; } } @@ -197,60 +202,277 @@ namespace Jack // net audio buffer ********************************************************************************* + NetAudioBuffer::NetAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer) + { + fNPorts = nports; + fNetBuffer = net_buffer; + + fPortBuffer = new sample_t* [fNPorts]; + fConnectedPorts = new bool[fNPorts]; + for (int port_index = 0; port_index < fNPorts; port_index++) { + fPortBuffer[port_index] = NULL; + fConnectedPorts[port_index] = true; + } + } + + NetAudioBuffer::~NetAudioBuffer() + { + delete [] fConnectedPorts; + delete [] fPortBuffer; + } + + void NetAudioBuffer::SetBuffer(int index, sample_t* buffer) + { + fPortBuffer[index] = buffer; + } + + sample_t* NetAudioBuffer::GetBuffer(int index) + { + return fPortBuffer[index]; + } + + int NetAudioBuffer::CheckPacket(int cycle, int sub_cycle) + { + int res; + + if (sub_cycle != fLastSubCycle + 1) { + jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle); + res = NET_PACKET_ERROR; + } else { + res = 0; + } + + fLastSubCycle = sub_cycle; + return res; + } + + void NetAudioBuffer::NextCycle() + { + // reset for next cycle + fLastSubCycle = -1; + } + + void NetAudioBuffer::Cleanup() + { + for (int port_index = 0; port_index < fNPorts; port_index++) { + if (fPortBuffer[port_index]) { + memset(fPortBuffer[port_index], 0, fPeriodSize * sizeof(sample_t)); + } + } + } + + //network<->buffer + + int NetAudioBuffer::ActivePortsToNetwork(char* net_buffer) + { + int active_ports = 0; + int* active_port_address = (int*)net_buffer; + + for (int port_index = 0; port_index < fNPorts; port_index++) { + // Write the active port number + if (fPortBuffer[port_index]) { + *active_port_address = port_index; + active_port_address++; + active_ports++; + assert(active_ports < 256); + } + } + + return active_ports; + } + + void NetAudioBuffer::ActivePortsFromNetwork(char* net_buffer, uint32_t port_num) + { + int* active_port_address = (int*)net_buffer; + + for (int port_index = 0; port_index < fNPorts; port_index++) { + fConnectedPorts[port_index] = false; + } + + for (uint port_index = 0; port_index < port_num; port_index++) { + // Use -1 when port is actually connected on other side + int active_port = *active_port_address; + if (active_port >= 0 && active_port < fNPorts) { + fConnectedPorts[active_port] = true; + } else { + jack_error("ActivePortsFromNetwork: incorrect port = %d", active_port); + } + active_port_address++; + } + } + + int NetAudioBuffer::RenderFromJackPorts() + { + // Count active ports + int active_ports = 0; + for (int port_index = 0; port_index < fNPorts; port_index++) { + + if (fPortBuffer[port_index]) { + active_ports++; + } + } + //jack_info("active_ports %d", active_ports); + return active_ports; + } + + void NetAudioBuffer::RenderToJackPorts() + { + // Nothing to do + NextCycle(); + } + + // Float converter + NetFloatAudioBuffer::NetFloatAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer) - : fPortBuffer(params, nports), fNetBuffer(net_buffer) - {} + : NetAudioBuffer(params, nports, net_buffer) + { + fPeriodSize = params->fPeriodSize; + fPacketSize = PACKET_AVAILABLE_SIZE(params); + + UpdateParams(max(params->fReturnAudioChannels, params->fSendAudioChannels)); + + fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t); + + fCycleDuration = float(fSubPeriodSize) / float(params->fSampleRate); + fCycleBytesSize = params->fMtu * (fPeriodSize / fSubPeriodSize); + + fLastSubCycle = -1; + } NetFloatAudioBuffer::~NetFloatAudioBuffer() {} + // needed size in bytes for an entire cycle size_t NetFloatAudioBuffer::GetCycleSize() { - return fPortBuffer.GetCycleSize(); + return fCycleBytesSize; } - void NetFloatAudioBuffer::SetBuffer(int index, sample_t* buffer) + // cycle duration in sec + float NetFloatAudioBuffer::GetCycleDuration() { - fPortBuffer.SetBuffer(index, buffer); + return fCycleDuration; } - sample_t* NetFloatAudioBuffer::GetBuffer(int index) + void NetFloatAudioBuffer::UpdateParams(int active_ports) { - return fPortBuffer.GetBuffer(index); + if (active_ports == 0) { + fSubPeriodSize = fPeriodSize; + } else { + jack_nframes_t period = (int) powf(2.f, (int)(log(float(fPacketSize) / (active_ports * sizeof(sample_t))) / log(2.))); + fSubPeriodSize = (period > fPeriodSize) ? fPeriodSize : period; + } + + fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t) + sizeof(int); // The port number in coded on 4 bytes } - void NetFloatAudioBuffer::RenderFromJackPorts() + int NetFloatAudioBuffer::GetNumPackets(int active_ports) { - fPortBuffer.RenderFromJackPorts(); + UpdateParams(active_ports); + + /* + jack_log("GetNumPackets packet = %d fPeriodSize = %d fSubPeriodSize = %d fSubPeriodBytesSize = %d", + fPeriodSize / fSubPeriodSize, fPeriodSize, fSubPeriodSize, fSubPeriodBytesSize); + */ + return fPeriodSize / fSubPeriodSize; // At least one packet } - void NetFloatAudioBuffer::RenderToJackPorts() + //jack<->buffer + + /* + int NetFloatAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num) { - fPortBuffer.RenderToJackPorts(); + // Cleanup all JACK ports at the beginning of the cycle + if (sub_cycle == 0) { + Cleanup(); + } + + if (port_num > 0) { + + /// Setup rendering parameters + int sub_period_size, sub_period_bytes_size; + if (port_num == 0) { + sub_period_size = fPeriodSize; + } else { + jack_nframes_t period = (int) powf(2.f, (int)(log(float(fPacketSize) / (port_num * sizeof(sample_t))) / log(2.))); + sub_period_size = (period > fPeriodSize) ? fPeriodSize : period; + } + sub_period_bytes_size = sub_period_size * sizeof(sample_t) + sizeof(uint32_t); // The port number in coded on 4 bytes + + for (uint32_t port_index = 0; port_index < port_num; port_index++) { + // Only copy to active ports : read the active port number then audio data + uint32_t* active_port_address = (uint32_t*)(fNetBuffer + port_index * sub_period_bytes_size); + uint32_t active_port = (uint32_t)(*active_port_address); + printf("active_port %d\n", active_port); + if (fPortBuffer[active_port]) { + memcpy(fPortBuffer[active_port] + sub_cycle * sub_period_size, (char*)(active_port_address + 1), sub_period_bytes_size - sizeof(uint32_t)); + //RenderFromNetwork((char*)(active_port_address + 1), active_port, sub_cycle, sub_period_bytes_size - sizeof(uint32_t)); + } + } + } + + return CheckPacket(cycle, sub_cycle); } + */ - //network<->buffer - int NetFloatAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num) + int NetFloatAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num) { - return fPortBuffer.RenderFromNetwork(fNetBuffer, cycle, sub_cycle, copy_size, port_num); + // Cleanup all JACK ports at the beginning of the cycle + if (sub_cycle == 0) { + Cleanup(); + } + + if (port_num > 0) { + + UpdateParams(port_num); + + for (uint32_t port_index = 0; port_index < port_num; port_index++) { + // Only copy to active ports : read the active port number then audio data + int* active_port_address = (int*)(fNetBuffer + port_index * fSubPeriodBytesSize); + int active_port = *active_port_address; + /* + if (fPortBuffer[active_port]) { + memcpy(fPortBuffer[active_port] + sub_cycle * fSubPeriodSize, (char*)(active_port_address + 1), fSubPeriodBytesSize - sizeof(uint32_t)); + } + */ + RenderFromNetwork((char*)(active_port_address + 1), active_port, sub_cycle); + } + } + + return CheckPacket(cycle, sub_cycle); } - int NetFloatAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t& port_num) + + int NetFloatAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num) { - return fPortBuffer.RenderToNetwork(fNetBuffer, sub_cycle, port_num); + int active_ports = 0; + + for (int port_index = 0; port_index < fNPorts; port_index++) { + // Only copy from active ports : write the active port number then audio data + if (fPortBuffer[port_index]) { + int* active_port_address = (int*)(fNetBuffer + active_ports * fSubPeriodBytesSize); + *active_port_address = port_index; + //memcpy((char*)(active_port_address + 1), fPortBuffer[port_index] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize - sizeof(uint32_t)); + RenderToNetwork((char*)(active_port_address + 1), port_index, sub_cycle); + active_ports++; + } + } + + return port_num * fSubPeriodBytesSize; } - void NetFloatAudioBuffer::ActivePortsToNetwork(char* net_buffer, uint32_t& port_num) + void NetFloatAudioBuffer::RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle) { - fPortBuffer.ActivePortsToNetwork(net_buffer, port_num); + if (fPortBuffer[active_port]) { + memcpy(fPortBuffer[active_port] + sub_cycle * fSubPeriodSize, net_buffer, fSubPeriodBytesSize - sizeof(int)); + } } - void NetFloatAudioBuffer::ActivePortsFromNetwork(char* net_buffer, uint32_t port_num) + void NetFloatAudioBuffer::RenderToNetwork(char* net_buffer, int active_port, int sub_cycle) { - fPortBuffer.ActivePortsFromNetwork(net_buffer, port_num); + memcpy(net_buffer, fPortBuffer[active_port] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize - sizeof(int)); } - // Celt audio buffer ********************************************************************************* #if HAVE_CELT @@ -259,13 +481,8 @@ namespace Jack #define KPS_DIV 8 NetCeltAudioBuffer::NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps) - : fNetBuffer(net_buffer) + :NetAudioBuffer(params, nports, net_buffer) { - int res1, res2; - - fNPorts = nports; - fPeriodSize = params->fPeriodSize; - fCeltMode = new CELTMode *[fNPorts]; fCeltEncoder = new CELTEncoder *[fNPorts]; fCeltDecoder = new CELTDecoder *[fNPorts]; @@ -278,77 +495,84 @@ namespace Jack for (int i = 0; i < fNPorts; i++) { fCeltMode[i] = celt_mode_create(params->fSampleRate, params->fPeriodSize, &error); - if (error != CELT_OK) + if (error != CELT_OK) { goto error; + } #if HAVE_CELT_API_0_11 fCeltEncoder[i] = celt_encoder_create_custom(fCeltMode[i], 1, &error); - if (error != CELT_OK) + if (error != CELT_OK) { goto error; + } celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1)); fCeltDecoder[i] = celt_decoder_create_custom(fCeltMode[i], 1, &error); - if (error != CELT_OK) + if (error != CELT_OK) { goto error; + } celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1)); #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 fCeltEncoder[i] = celt_encoder_create(fCeltMode[i], 1, &error); - if (error != CELT_OK) + if (error != CELT_OK) { goto error; + } celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1)); fCeltDecoder[i] = celt_decoder_create(fCeltMode[i], 1, &error); - if (error != CELT_OK) + if (error != CELT_OK) { goto error; + } celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1)); #else fCeltEncoder[i] = celt_encoder_create(fCeltMode[i]); - if (error != CELT_OK) + if (error != CELT_OK) { goto error; + } celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1)); fCeltDecoder[i] = celt_decoder_create(fCeltMode[i]); - if (error != CELT_OK) + if (error != CELT_OK) { goto error; + } celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1)); #endif } - fPortBuffer = new sample_t* [fNPorts]; - for (int port_index = 0; port_index < fNPorts; port_index++) - fPortBuffer[port_index] = NULL; - - fCompressedSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8); + { + fPeriodSize = params->fPeriodSize; - fCompressedBuffer = new unsigned char* [fNPorts]; - for (int port_index = 0; port_index < fNPorts; port_index++) - fCompressedBuffer[port_index] = new unsigned char[fCompressedSizeByte]; + fCompressedSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8); + jack_log("NetCeltAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte); - jack_log("NetCeltAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte); + fCompressedBuffer = new unsigned char* [fNPorts]; + for (int port_index = 0; port_index < fNPorts; port_index++) { + fCompressedBuffer[port_index] = new unsigned char[fCompressedSizeByte]; + } - res1 = (fNPorts * fCompressedSizeByte) % (params->fMtu - sizeof(packet_header_t)); - res2 = (fNPorts * fCompressedSizeByte) / (params->fMtu - sizeof(packet_header_t)); + int res1 = (fNPorts * fCompressedSizeByte) % PACKET_AVAILABLE_SIZE(params); + int res2 = (fNPorts * fCompressedSizeByte) / PACKET_AVAILABLE_SIZE(params); - fNumPackets = (res1) ? (res2 + 1) : res2; + fNumPackets = (res1) ? (res2 + 1) : res2; - jack_log("NetCeltAudioBuffer res1 = %d res2 = %d", res1, res2); + jack_log("NetCeltAudioBuffer res1 = %d res2 = %d", res1, res2); - fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets; - fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets; + fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets; + fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets; - jack_log("NetCeltAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize); + jack_log("NetCeltAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize); - fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate); - fCycleSize = params->fMtu * fNumPackets; + fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate); + fCycleBytesSize = params->fMtu * fNumPackets; - fLastSubCycle = -1; - return; + fLastSubCycle = -1; + return; + } error: @@ -360,22 +584,25 @@ namespace Jack { FreeCelt(); - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { delete [] fCompressedBuffer[port_index]; + } delete [] fCompressedBuffer; - delete [] fPortBuffer; } void NetCeltAudioBuffer::FreeCelt() { for (int i = 0; i < fNPorts; i++) { - if (fCeltEncoder[i]) + if (fCeltEncoder[i]) { celt_encoder_destroy(fCeltEncoder[i]); - if (fCeltDecoder[i]) + } + if (fCeltDecoder[i]) { celt_decoder_destroy(fCeltDecoder[i]); - if (fCeltMode[i]) + } + if (fCeltMode[i]) { celt_mode_destroy(fCeltMode[i]); + } } delete [] fCeltMode; @@ -385,7 +612,7 @@ namespace Jack size_t NetCeltAudioBuffer::GetCycleSize() { - return fCycleSize; + return fCycleBytesSize; } float NetCeltAudioBuffer::GetCycleDuration() @@ -393,38 +620,29 @@ namespace Jack return fCycleDuration; } - int NetCeltAudioBuffer::GetNumPackets() + int NetCeltAudioBuffer::GetNumPackets(int active_ports) { return fNumPackets; } - void NetCeltAudioBuffer::SetBuffer(int index, sample_t* buffer) - { - assert(fPortBuffer); - fPortBuffer[index] = buffer; - } - - sample_t* NetCeltAudioBuffer::GetBuffer(int index) - { - assert(fPortBuffer); - return fPortBuffer[index]; - } - - void NetCeltAudioBuffer::RenderFromJackPorts() + int NetCeltAudioBuffer::RenderFromJackPorts() { - float floatbuf[fPeriodSize]; + float buffer[fPeriodSize]; for (int port_index = 0; port_index < fNPorts; port_index++) { - memcpy(floatbuf, fPortBuffer[port_index], fPeriodSize * sizeof(float)); + memcpy(buffer, fPortBuffer[port_index], fPeriodSize * sizeof(sample_t)); #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 - int res = celt_encode_float(fCeltEncoder[port_index], floatbuf, fPeriodSize, fCompressedBuffer[port_index], fCompressedSizeByte); + int res = celt_encode_float(fCeltEncoder[port_index], buffer, fPeriodSize, fCompressedBuffer[port_index], fCompressedSizeByte); #else - int res = celt_encode_float(fCeltEncoder[port_index], floatbuf, NULL, fCompressedBuffer[port_index], fCompressedSizeByte); + int res = celt_encode_float(fCeltEncoder[port_index], buffer, NULL, fCompressedBuffer[port_index], fCompressedSizeByte); #endif if (res != fCompressedSizeByte) { - jack_error("celt_encode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res); + jack_error("celt_encode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res); } } + + // All ports active + return fNPorts; } void NetCeltAudioBuffer::RenderToJackPorts() @@ -436,47 +654,42 @@ namespace Jack int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index]); #endif if (res != CELT_OK) { - jack_error("celt_decode_float error res = %d", fCompressedSizeByte, res); + jack_error("celt_decode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res); } } - // reset for next cycle - fLastSubCycle = -1; + NextCycle(); } //network<->buffer - int NetCeltAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num) + int NetCeltAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num) { - int res = 0; - + // Last packet of the cycle if (sub_cycle == fNumPackets - 1) { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize); + } } else { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); + } } - if (sub_cycle != fLastSubCycle + 1) { - jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle); - res = NET_PACKET_ERROR; - } - - fLastSubCycle = sub_cycle; - return res; + return CheckPacket(cycle, sub_cycle); } - int NetCeltAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t& port_num) + int NetCeltAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num) { - port_num = fNPorts; - + // Last packet of the cycle if (sub_cycle == fNumPackets - 1) { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fLastSubPeriodBytesSize); + } return fNPorts * fLastSubPeriodBytesSize; } else { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fSubPeriodBytesSize); + } return fNPorts * fSubPeriodBytesSize; } } @@ -484,42 +697,34 @@ namespace Jack #endif NetIntAudioBuffer::NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer) - : fNetBuffer(net_buffer) + : NetAudioBuffer(params, nports, net_buffer) { - int res1, res2; - - fNPorts = nports; fPeriodSize = params->fPeriodSize; - fPortBuffer = new sample_t* [fNPorts]; - for (int port_index = 0; port_index < fNPorts; port_index++) - fPortBuffer[port_index] = NULL; + fCompressedSizeByte = (params->fPeriodSize * sizeof(short)); + jack_log("NetIntAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte); fIntBuffer = new short* [fNPorts]; - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { fIntBuffer[port_index] = new short[fPeriodSize]; + } - fCompressedSizeByte = (params->fPeriodSize * sizeof(short)); - - jack_log("fCompressedSizeByte %d", fCompressedSizeByte); - - res1 = (fNPorts * fCompressedSizeByte) % (params->fMtu - sizeof(packet_header_t)); - res2 = (fNPorts * fCompressedSizeByte) / (params->fMtu - sizeof(packet_header_t)); + int res1 = (fNPorts * fCompressedSizeByte) % PACKET_AVAILABLE_SIZE(params); + int res2 = (fNPorts * fCompressedSizeByte) / PACKET_AVAILABLE_SIZE(params); - jack_log("res1 = %d res2 = %d", res1, res2); + jack_log("NetIntAudioBuffer res1 = %d res2 = %d", res1, res2); fNumPackets = (res1) ? (res2 + 1) : res2; fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets; - fSubPeriodSize = fSubPeriodBytesSize / sizeof(short); - fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets; - fLastSubPeriodSize = fLastSubPeriodBytesSize / sizeof(short); - jack_log("fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize); + fSubPeriodSize = fSubPeriodBytesSize / sizeof(short); + + jack_log("NetIntAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize); fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate); - fCycleSize = params->fMtu * fNumPackets; + fCycleBytesSize = params->fMtu * fNumPackets; fLastSubCycle = -1; return; @@ -527,16 +732,16 @@ namespace Jack NetIntAudioBuffer::~NetIntAudioBuffer() { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { delete [] fIntBuffer[port_index]; + } delete [] fIntBuffer; - delete [] fPortBuffer; } size_t NetIntAudioBuffer::GetCycleSize() { - return fCycleSize; + return fCycleBytesSize; } float NetIntAudioBuffer::GetCycleDuration() @@ -544,135 +749,67 @@ namespace Jack return fCycleDuration; } - int NetIntAudioBuffer::GetNumPackets() + int NetIntAudioBuffer::GetNumPackets(int active_ports) { return fNumPackets; } - void NetIntAudioBuffer::SetBuffer(int index, sample_t* buffer) - { - fPortBuffer[index] = buffer; - } - - sample_t* NetIntAudioBuffer::GetBuffer(int index) - { - return fPortBuffer[index]; - } - - void NetIntAudioBuffer::RenderFromJackPorts() + int NetIntAudioBuffer::RenderFromJackPorts() { for (int port_index = 0; port_index < fNPorts; port_index++) { - for (unsigned int frame = 0; frame < fPeriodSize; frame++) + for (uint frame = 0; frame < fPeriodSize; frame++) { fIntBuffer[port_index][frame] = short(fPortBuffer[port_index][frame] * 32768.f); + } } + + // All ports active + return fNPorts; } void NetIntAudioBuffer::RenderToJackPorts() { + float coef = 1.f / 32768.f; for (int port_index = 0; port_index < fNPorts; port_index++) { - float coef = 1.f / 32768.f; - for (unsigned int frame = 0; frame < fPeriodSize; frame++) + for (uint frame = 0; frame < fPeriodSize; frame++) { fPortBuffer[port_index][frame] = float(fIntBuffer[port_index][frame] * coef); + } } - // reset for next cycle - fLastSubCycle = -1; + NextCycle(); } - //network<->buffer - int NetIntAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num) + //network<->buffer + int NetIntAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num) { - int res = 0; - if (sub_cycle == fNumPackets - 1) { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { memcpy(fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize); + } } else { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { memcpy(fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); + } } - if (sub_cycle != fLastSubCycle + 1) { - jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle); - res = NET_PACKET_ERROR; - } - - fLastSubCycle = sub_cycle; - return res; + return CheckPacket(cycle, sub_cycle); } - int NetIntAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t& port_num) + int NetIntAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num) { - port_num = fNPorts; - + // Last packet of the cycle if (sub_cycle == fNumPackets - 1) { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fLastSubPeriodBytesSize); + } return fNPorts * fLastSubPeriodBytesSize; } else { - for (int port_index = 0; port_index < fNPorts; port_index++) + for (int port_index = 0; port_index < fNPorts; port_index++) { memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize); + } return fNPorts * fSubPeriodBytesSize; } } -// Buffered - -/* - NetBufferedAudioBuffer::NetBufferedAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer) - { - fMaxCycle = 0; - fNetBuffer = net_buffer; - - for (int i = 0; i < AUDIO_BUFFER_SIZE; i++) { - fPortBuffer[i].Init(params, nports); - } - - fJackPortBuffer = new sample_t* [nports]; - for (uint32_t port_index = 0; port_index < nports; port_index++) - fJackPortBuffer[port_index] = NULL; - } - - NetBufferedAudioBuffer::~NetBufferedAudioBuffer() - { - delete [] fJackPortBuffer; - } - - size_t NetBufferedAudioBuffer::GetCycleSize() - { - return fPortBuffer[0].GetCycleSize(); - } - - void NetBufferedAudioBuffer::SetBuffer(int index, sample_t* buffer) - { - fJackPortBuffer[index] = buffer; - } - - sample_t* NetBufferedAudioBuffer::GetBuffer(int index) - { - return fJackPortBuffer[index]; - } - - void NetBufferedAudioBuffer::RenderFromJackPorts (int sub_cycle) - { - fPortBuffer[0].RenderFromJackPorts(fNetBuffer, sub_cycle); // Always use first buffer... - } - - void NetBufferedAudioBuffer::RenderToJackPorts (int cycle, int sub_cycle) - { - if (cycle < fMaxCycle) { - jack_info("Wrong order fCycle %d sub_cycle %d fMaxCycle %d", cycle, sub_cycle, fMaxCycle); - } - fPortBuffer[cycle % AUDIO_BUFFER_SIZE].RenderToJackPorts(fNetBuffer, sub_cycle); - } - - void NetBufferedAudioBuffer::FinishRenderToJackPorts (int cycle) - { - fMaxCycle = std::max(fMaxCycle, cycle); - fPortBuffer[(cycle + 1) % AUDIO_BUFFER_SIZE].Copy(fJackPortBuffer); // Copy internal buffer in JACK ports - } - */ - // SessionParams ************************************************************************************ SERVER_EXPORT void SessionParamsHToN(session_params_t* src_params, session_params_t* dst_params) @@ -690,6 +827,7 @@ namespace Jack dst_params->fPeriodSize = htonl(src_params->fPeriodSize); dst_params->fSampleEncoder = htonl(src_params->fSampleEncoder); dst_params->fSlaveSyncMode = htonl(src_params->fSlaveSyncMode); + dst_params->fNetworkLatency = htonl(src_params->fNetworkLatency); } SERVER_EXPORT void SessionParamsNToH(session_params_t* src_params, session_params_t* dst_params) @@ -707,6 +845,7 @@ namespace Jack dst_params->fPeriodSize = ntohl(src_params->fPeriodSize); dst_params->fSampleEncoder = ntohl(src_params->fSampleEncoder); dst_params->fSlaveSyncMode = ntohl(src_params->fSlaveSyncMode); + dst_params->fNetworkLatency = ntohl(src_params->fNetworkLatency); } SERVER_EXPORT void SessionParamsDisplay(session_params_t* params) @@ -725,19 +864,6 @@ namespace Jack break; } - char mode[8]; - switch (params->fNetworkMode) - { - case 's' : - strcpy(mode, "slow"); - break; - case 'n' : - strcpy(mode, "normal"); - break; - case 'f' : - strcpy(mode, "fast"); - break; - } jack_info("**************** Network parameters ****************"); jack_info("Name : %s", params->fName); jack_info("Protocol revision : %d", params->fProtocolVersion); @@ -750,6 +876,7 @@ namespace Jack jack_info("Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels); jack_info("Sample rate : %u frames per second", params->fSampleRate); jack_info("Period size : %u frames per period", params->fPeriodSize); + jack_info("Network latency : %u cycles", params->fNetworkLatency); switch (params->fSampleEncoder) { case (JackFloatEncoder): jack_info("SampleEncoder : %s", "Float"); @@ -763,7 +890,6 @@ namespace Jack break; }; jack_info("Slave mode : %s", (params->fSlaveSyncMode) ? "sync" : "async"); - jack_info("Network mode : %s", mode); jack_info("****************************************************"); } @@ -943,14 +1069,12 @@ namespace Jack WORD wVersionRequested = MAKEWORD(2, 2); WSADATA wsaData; - if (WSAStartup(wVersionRequested, &wsaData) != 0) - { + if (WSAStartup(wVersionRequested, &wsaData) != 0) { jack_error("WSAStartup error : %s", strerror(NET_ERROR_CODE)); return -1; } - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) - { + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { jack_error("Could not find a useable version of Winsock.dll\n"); WSACleanup(); return -1; diff --git a/common/JackNetTool.h b/common/JackNetTool.h index 375aa376..315ab66b 100644 --- a/common/JackNetTool.h +++ b/common/JackNetTool.h @@ -39,13 +39,16 @@ using namespace std; #endif #endif -#define MASTER_PROTOCOL 4 -#define SLAVE_PROTOCOL 4 +#define MASTER_PROTOCOL 5 +#define SLAVE_PROTOCOL 5 #define NET_PACKET_ERROR -2 #define OPTIMIZED_PROTOCOL +#define HEADER_SIZE (sizeof(packet_header_t)) +#define PACKET_AVAILABLE_SIZE(params) ((params)->fMtu - sizeof(packet_header_t)) + namespace Jack { typedef struct _session_params session_params_t; @@ -101,7 +104,7 @@ namespace Jack uint32_t fSampleEncoder; //samples encoder uint32_t fKBps; //KB per second for CELT encoder uint32_t fSlaveSyncMode; //is the slave in sync mode ? - char fNetworkMode; //fast, normal or slow mode + uint32_t fNetworkLatency; //network latency }; //net status ********************************************************************************** @@ -232,11 +235,12 @@ namespace Jack int fNPorts; size_t fMaxBufsize; int fMaxPcktSize; + char* fBuffer; char* fNetBuffer; JackMidiBuffer** fPortBuffer; - size_t fCycleSize; // needed size in bytes ofr an entire cycle + size_t fCycleBytesSize; // needed size in bytes ofr an entire cycle public: @@ -247,9 +251,11 @@ namespace Jack // needed size in bytes for an entire cycle size_t GetCycleSize(); - int GetNumPackets(int data_sizen, int max_size); + void SetBuffer(int index, JackMidiBuffer* buffer); + JackMidiBuffer* GetBuffer(int index); + //utility void DisplayEvents(); @@ -261,8 +267,6 @@ namespace Jack void RenderFromNetwork(int sub_cycle, size_t copy_size); int RenderToNetwork(int sub_cycle, size_t total_size); - void SetBuffer(int index, JackMidiBuffer* buffer); - JackMidiBuffer* GetBuffer(int index); }; // audio data ********************************************************************************* @@ -270,12 +274,33 @@ namespace Jack class SERVER_EXPORT NetAudioBuffer { + protected: + + int fNPorts; + int fLastSubCycle; + + char* fNetBuffer; + sample_t** fPortBuffer; + bool* fConnectedPorts; + + jack_nframes_t fPeriodSize; + jack_nframes_t fSubPeriodSize; + size_t fSubPeriodBytesSize; + + float fCycleDuration; // in sec + size_t fCycleBytesSize; // needed size in bytes for an entire cycle + + int CheckPacket(int cycle, int sub_cycle); + void NextCycle(); + void Cleanup(); + public: - NetAudioBuffer() - {} - virtual ~NetAudioBuffer() - {} + NetAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer); + virtual ~NetAudioBuffer(); + + bool GetConnected(int port_index) { return fConnectedPorts[port_index]; } + void SetConnected(int port_index, bool state) { fConnectedPorts[port_index] = state; } // needed syze in bytes ofr an entire cycle virtual size_t GetCycleSize() = 0; @@ -283,414 +308,55 @@ namespace Jack // cycle duration in sec virtual float GetCycleDuration() = 0; - virtual int GetNumPackets() = 0; + virtual int GetNumPackets(int active_ports) = 0; + + virtual void SetBuffer(int index, sample_t* buffer); + virtual sample_t* GetBuffer(int index); //jack<->buffer - virtual void RenderFromJackPorts() = 0; - virtual void RenderToJackPorts() = 0; + virtual int RenderFromJackPorts(); + virtual void RenderToJackPorts(); //network<->buffer - virtual int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num) = 0; - virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num) {} - - virtual int RenderToNetwork(int sub_cycle, uint32_t& port_num) = 0; - virtual void ActivePortsToNetwork(char* net_buffer, uint32_t& port_num) {} - - virtual void SetBuffer(int index, sample_t* buffer) = 0; - virtual sample_t* GetBuffer(int index) = 0; - }; - - /** - \Brief Audio buffer and operations class - - This class is a toolset to manipulate audio buffers. - The manipulation of audio buffers is similar to midi buffer, except those buffers have fixed size. - The interleaving/uninterleaving operations are simplier here because audio buffers have fixed size, - So there is no need of an intermediate buffer as in NetMidiBuffer. - - */ - - struct JackPortList { - - // "[---Header---|--audio data--|--audio data--]..." - - jack_nframes_t fPeriodSize; - jack_nframes_t fSubPeriodSize; - size_t fSubPeriodBytesSize; - sample_t** fPortBuffer; - int fPacketSize; - int fNPorts; - size_t fCycleSize; // needed size in bytes for an entire cycle - float fCycleDuration; // in sec - - int fLastSubCycle; - - JackPortList(session_params_t* params, uint32_t nports) - { - fNPorts = nports; - fPeriodSize = params->fPeriodSize; - fPacketSize = params->fMtu - sizeof(packet_header_t); - - if (params->fSendAudioChannels == 0 && params->fReturnAudioChannels == 0) { - fSubPeriodSize = params->fPeriodSize; - } else { - jack_nframes_t period = (int) powf(2.f,(int)(log(float(fPacketSize) - / (max(params->fReturnAudioChannels, params->fSendAudioChannels) * sizeof(sample_t))) / log(2.))); - fSubPeriodSize = (period > fPeriodSize) ? fPeriodSize : period; - } - - fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t); - - fPortBuffer = new sample_t* [fNPorts]; - for (int port_index = 0; port_index < fNPorts; port_index++) { - fPortBuffer[port_index] = NULL; - } - - fCycleDuration = float(fSubPeriodSize) / float(params->fSampleRate); - fCycleSize = params->fMtu * (fPeriodSize / fSubPeriodSize); - - fLastSubCycle = -1; - } - - virtual int GetNumPackets() - { - jack_info("GetNumPackets packet = %d fPeriodSize = %d fSubPeriodSize = %d fSubPeriodBytesSize = %d", - fPeriodSize / fSubPeriodSize, fPeriodSize, fSubPeriodSize, fSubPeriodBytesSize); - return fPeriodSize / fSubPeriodSize; - } - - JackPortList() - { - fNPorts = 0; - fPeriodSize = 0; - fSubPeriodSize = 0; - fSubPeriodBytesSize = 0; - fPortBuffer = 0; - } - - virtual ~JackPortList() - { - delete [] fPortBuffer; - } - - void SetBuffer(int index, sample_t* buffer) - { - fPortBuffer[index] = buffer; - } - - sample_t* GetBuffer(int index) - { - return fPortBuffer[index]; - } - - void Copy(sample_t** buffers) - { - for (int port_index = 0; port_index < fNPorts; port_index++) - memcpy(buffers[port_index], fPortBuffer[port_index], fPeriodSize * sizeof(float)); - } - - // needed syze in bytes for an entire cycle - size_t GetCycleSize() - { - return fCycleSize; - } - - // cycle duration in sec - float GetCycleDuration() - { - return fCycleDuration; - } - - #ifdef __BIG_ENDIAN__ - - static inline float SwapFloat(float f) - { - union - { - float f; - unsigned char b[4]; - } dat1, dat2; - - dat1.f = f; - dat2.b[0] = dat1.b[3]; - dat2.b[1] = dat1.b[2]; - dat2.b[2] = dat1.b[1]; - dat2.b[3] = dat1.b[0]; - return dat2.f; - } - - virtual void RenderFromJackPorts() - {} - - virtual void RenderToJackPorts() - {} - - //network<->buffer - virtual int RenderFromNetwork(char* net_buffer, int cycle, int sub_cycle, size_t copy_size, uint32_t port_num) - { - int res = 0; - - for (int port_index = 0; port_index < fNPorts; port_index++) { - float* src = (float*)(net_buffer + port_index * fSubPeriodBytesSize); - float* dst = (float*)(fPortBuffer[port_index] + sub_cycle * fSubPeriodSize); - for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { - dst[sample] = SwapFloat(src[sample]); - } - } - if (sub_cycle != fLastSubCycle + 1) { - jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle); - res = NET_PACKET_ERROR; - } - - fLastSubCycle = sub_cycle; - return res; - } - - virtual int RenderToNetwork(char* net_buffer, int sub_cycle, uint32_t& port_num) - { - for (int port_index = 0; port_index < fNPorts; port_index++) { - float* src = (float*)(fPortBuffer[port_index] + sub_cycle * fSubPeriodSize); - float* dst = (float*)(net_buffer + port_index * fSubPeriodBytesSize); - for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { - dst[sample] = SwapFloat(src[sample]); - } - } - - port_num = fNPorts; - return fNPorts * fSubPeriodBytesSize; - } - - #else - - virtual void RenderFromJackPorts() - {} - - virtual void RenderToJackPorts() - { - // reset for next cycle - fLastSubCycle = -1; - } - - //network<->buffer - virtual int RenderFromNetwork(char* net_buffer, int cycle, int sub_cycle, size_t copy_size, uint32_t port_num) - { - int res = 0; - - for (int port_index = 0; port_index < fNPorts; port_index++) { - memcpy(fPortBuffer[port_index] + sub_cycle * fSubPeriodSize, net_buffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); - } - if (sub_cycle != fLastSubCycle + 1) { - jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle); - res = NET_PACKET_ERROR; - } - - fLastSubCycle = sub_cycle; - return res; - } - - virtual int RenderToNetwork(char* net_buffer, int sub_cycle, uint32_t& port_num) - { - for (int port_index = 0; port_index < fNPorts; port_index++) { - memcpy(net_buffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize); - } - port_num = fNPorts; - return fNPorts * fSubPeriodBytesSize; - } - - #endif - - virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num) - {} - - virtual void ActivePortsToNetwork(char* net_buffer, uint32_t& port_num) - { - port_num = fNPorts; - } + virtual int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num) = 0; + virtual int RenderToNetwork(int sub_cycle, uint32_t port_num) = 0; - }; + virtual void RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle, size_t copy_size) {} + virtual void RenderToNetwork(char* net_buffer, int active_port, int sub_cycle, size_t copy_size) {} - struct JackOptimizedPortList : JackPortList { - - // Consuming port list is transmitted in the Sync packed - // "[---Header---|--active_port_num---audio data--|--active_port_num---audio data--]..." - - JackOptimizedPortList(session_params_t* params, uint32_t nports) - :JackPortList(params, nports) - {} - - virtual ~JackOptimizedPortList() - {} - - int GetNumPackets() - { - // Count active ports - int active_ports = 0; - for (int port_index = 0; port_index < fNPorts; port_index++) { - if (fPortBuffer[port_index]) active_ports++; - } - - if (active_ports == 0) { - fSubPeriodSize = fPeriodSize; - } else { - jack_nframes_t period = (int) powf(2.f, (int)(log(float(fPacketSize) / (active_ports * sizeof(sample_t))) / log(2.))); - fSubPeriodSize = (period > fPeriodSize) ? fPeriodSize : period; - } - - fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t) + sizeof(uint32_t); // The port number in coded on 4 bytes - return fPeriodSize / fSubPeriodSize; // At least one packet - } - - #ifdef __BIG_ENDIAN__ - - // TODO - - #else - - //network<->buffer - virtual int RenderFromNetwork(char* net_buffer, int cycle, int sub_cycle, size_t copy_size, uint32_t port_num) - { - int res = 0; - - // Cleanup all JACK ports at the beginning of the cycle - if (sub_cycle == 0) { - for (int port_index = 0; port_index < fNPorts; port_index++) { - if (fPortBuffer[port_index]) - memset(fPortBuffer[port_index], 0, fPeriodSize * sizeof(sample_t)); - } - } - - if (port_num > 0) { - - /// Setup rendering parameters - int sub_period_size, sub_period_bytes_size; - if (port_num == 0) { - sub_period_size = fPeriodSize; - } else { - jack_nframes_t period = (int) powf(2.f, (int)(log(float(fPacketSize) / (port_num * sizeof(sample_t))) / log(2.))); - sub_period_size = (period > fPeriodSize) ? fPeriodSize : period; - } - sub_period_bytes_size = sub_period_size * sizeof(sample_t) + sizeof(uint32_t); // The port number in coded on 4 bytes - - for (uint32_t port_index = 0; port_index < port_num; port_index++) { - // Only copy to active ports : read the active port number then audio data - int* active_port_address = (int*)(net_buffer + port_index * sub_period_bytes_size); - int active_port = (int)(*active_port_address); - if (fPortBuffer[port_index]) - memcpy(fPortBuffer[active_port] + sub_cycle * sub_period_size, (char*)(active_port_address + 1), sub_period_bytes_size - sizeof(int)); - } - - if (sub_cycle != fLastSubCycle + 1) { - jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle); - res = NET_PACKET_ERROR; - } - - fLastSubCycle = sub_cycle; - } - - return res; - } - - virtual int RenderToNetwork(char* net_buffer,int sub_cycle, uint32_t& port_num) - { - // Init active port count - port_num = 0; - - for (int port_index = 0; port_index < fNPorts; port_index++) { - // Only copy from active ports : write the active port number then audio data - if (fPortBuffer[port_index]) { - int* active_port_address = (int*)(net_buffer + port_num * fSubPeriodBytesSize); - *active_port_address = port_index; - memcpy((char*)(active_port_address + 1), fPortBuffer[port_index] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize - sizeof(uint32_t)); - port_num++; - } - } - - return port_num * fSubPeriodBytesSize; - } - - #endif - - virtual void ActivePortsToNetwork(char* net_buffer, uint32_t& port_num) - { - // Init active port count - port_num = 0; - short* active_port_address = (short*)net_buffer; - - for (int port_index = 0; port_index < fNPorts; port_index++) { - // Write the active port number - if (fPortBuffer[port_index]) { - *active_port_address = port_index; - active_port_address++; - port_num++; - assert(port_num < 512); - } - } - } - - virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num) - { - short* active_port_address = (short*)net_buffer; - - for (int port_index = 0; port_index < fNPorts; port_index++) { - fPortBuffer[port_index] = NULL; - } - - for (uint port_index = 0; port_index < port_num; port_index++) { - // Use -1 when port is actually connected on other side - if (*active_port_address >= 0 && *active_port_address < fNPorts) { - fPortBuffer[*active_port_address] = (sample_t*)-1; - } else { - jack_error("ActivePortsFromNetwork: incorrect port = %d", *active_port_address); - } - active_port_address++; - } - } + virtual int ActivePortsToNetwork(char* net_buffer); + virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num); }; class SERVER_EXPORT NetFloatAudioBuffer : public NetAudioBuffer { + private: - #ifdef OPTIMIZED_PROTOCOL - JackOptimizedPortList fPortBuffer; - #else - JackPortList fPortBuffer; - #endif - char* fNetBuffer; + int fPacketSize; + + void UpdateParams(int active_ports); public: NetFloatAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer); - ~NetFloatAudioBuffer(); + virtual ~NetFloatAudioBuffer(); // needed size in bytes for an entire cycle size_t GetCycleSize(); // cycle duration in sec - float GetCycleDuration() - { - return fPortBuffer.GetCycleDuration(); - } - - int GetNumPackets() - { - return fPortBuffer.GetNumPackets(); - } + float GetCycleDuration(); + int GetNumPackets(int active_ports); //jack<->buffer - void RenderFromJackPorts(); - void RenderToJackPorts(); + int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num); + int RenderToNetwork(int sub_cycle, uint32_t port_num); - void SetBuffer(int index, sample_t* buffer); - sample_t* GetBuffer(int index); + void RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle); + void RenderToNetwork(char* net_buffer, int active_port, int sub_cycle); - //network<->buffer - int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num); - void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num); - - int RenderToNetwork(int sub_cycle, uint32_t& ort_num); - void ActivePortsToNetwork(char* net_buffer, uint32_t& port_num); }; #if HAVE_CELT @@ -706,45 +372,33 @@ namespace Jack CELTDecoder** fCeltDecoder; int fCompressedSizeByte; - jack_nframes_t fPeriodSize; int fNumPackets; - float fCycleDuration; // in sec - size_t fCycleSize; // needed size in bytes for an entire cycle - size_t fSubPeriodBytesSize; size_t fLastSubPeriodBytesSize; - sample_t** fPortBuffer; - char* fNetBuffer; unsigned char** fCompressedBuffer; - int fNPorts; - int fLastSubCycle; - void FreeCelt(); public: NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps); - ~NetCeltAudioBuffer(); + virtual ~NetCeltAudioBuffer(); // needed size in bytes for an entire cycle size_t GetCycleSize(); // cycle duration in sec float GetCycleDuration(); - int GetNumPackets(); - - void SetBuffer(int index, sample_t* buffer); - sample_t* GetBuffer(int index); + int GetNumPackets(int active_ports); //jack<->buffer - void RenderFromJackPorts(); + int RenderFromJackPorts(); void RenderToJackPorts(); //network<->buffer - int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num); - int RenderToNetwork(int sub_cycle, uint32_t& port_num); + int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num); + int RenderToNetwork(int sub_cycle, uint32_t port_num); }; #endif @@ -754,133 +408,33 @@ namespace Jack private: int fCompressedSizeByte; - jack_nframes_t fPeriodSize; - int fNumPackets; - float fCycleDuration; // in sec - size_t fCycleSize; // needed size in bytes for an entire cycle - size_t fSubPeriodSize; - size_t fSubPeriodBytesSize; - size_t fLastSubPeriodSize;; size_t fLastSubPeriodBytesSize; - sample_t** fPortBuffer; - char* fNetBuffer; - short ** fIntBuffer; - - int fNPorts; - int fLastSubCycle; + short** fIntBuffer; public: NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer); - ~NetIntAudioBuffer(); + virtual ~NetIntAudioBuffer(); // needed size in bytes for an entire cycle size_t GetCycleSize(); // cycle duration in sec float GetCycleDuration(); - int GetNumPackets(); - - void SetBuffer(int index, sample_t* buffer); - sample_t* GetBuffer(int index); + int GetNumPackets(int active_ports); //jack<->buffer - void RenderFromJackPorts(); + int RenderFromJackPorts(); void RenderToJackPorts(); //network<->buffer - int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num); - int RenderToNetwork(int sub_cycle, uint32_t& port_num); + int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num); + int RenderToNetwork(int sub_cycle, uint32_t port_num); }; - /* - #define AUDIO_BUFFER_SIZE 8 - - struct JackPortListAllocate : public JackPortList { - - JackPortListAllocate() - { - fNPorts = 0; - fPeriodSize = 0; - fSubPeriodSize = 0; - fSubPeriodBytesSize = 0; - fPortBuffer = 0; - } - - ~JackPortListAllocate() - { - for (int port_index = 0; port_index < fNPorts; port_index++) - delete [] fPortBuffer[port_index]; - delete [] fPortBuffer; - } - - void Init(session_params_t* params, uint32_t nports) - { - fNPorts = nports; - fPeriodSize = params->fPeriodSize; - - if (params->fSendAudioChannels == 0 && params->fReturnAudioChannels == 0) { - fSubPeriodSize = params->fPeriodSize; - } else { - jack_nframes_t period = (int) powf(2.f, (int)(log(float((params->fMtu - sizeof(packet_header_t))) - / (max(params->fReturnAudioChannels, params->fSendAudioChannels) * sizeof(sample_t))) / log(2.))); - fSubPeriodSize = (period > params->fPeriodSize) ? params->fPeriodSize : period; - } - - fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t); - fPortBuffer = new sample_t* [fNPorts]; - for (int port_index = 0; port_index < fNPorts; port_index++) - fPortBuffer[port_index] = new sample_t[fPeriodSize]; - } - - }; - - class SERVER_EXPORT NetBufferedAudioBuffer : public NetAudioBuffer - { - - private: - char* fNetBuffer; - JackPortListAllocate fPortBuffer[AUDIO_BUFFER_SIZE]; - sample_t** fJackPortBuffer; - int fMaxCycle; - - public: - NetBufferedAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer); - ~NetBufferedAudioBuffer(); - - // needed syze in bytes ofr an entire cycle - size_t GetCycleSize(); - - // cycle duration in sec - float GetCycleDuration() - { - return fPortBuffer[0].GetCycleDuration(); - } - - //jack<->buffer - void RenderFromJackPorts(int sub_cycle); - void RenderToJackPorts(int cycle, int sub_cycle); - //void FinishRenderToJackPorts(int cycle); - - //network<->buffer - void RenderFromNetwork(int sub_cycle, size_t copy_size) - { - // TODO - } - int RenderToNetwork(int sub_cycle, size_t total_size) - { - // TODO - return 0; - } - - void SetBuffer(int index, sample_t* buffer); - sample_t* GetBuffer(int index); - }; - */ - //utility ************************************************************************************* //socket API management diff --git a/common/JackPort.cpp b/common/JackPort.cpp index 8e3be740..9bc53d83 100644 --- a/common/JackPort.cpp +++ b/common/JackPort.cpp @@ -35,6 +35,7 @@ JackPort::JackPort() bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type, JackPortFlags flags) { jack_port_type_id_t id = GetPortTypeId(port_type); + assert(id >= 0 && id <= PORT_TYPES_MAX); if (id == PORT_TYPES_MAX) return false; fTypeId = id; diff --git a/common/JackRequest.h b/common/JackRequest.h index f5e86543..07ec219c 100644 --- a/common/JackRequest.h +++ b/common/JackRequest.h @@ -149,11 +149,12 @@ struct JackClientCheckRequest : public JackRequest int fProtocol; int fOptions; int fUUID; + int fOpen; JackClientCheckRequest() {} - JackClientCheckRequest(const char* name, int protocol, int options, int uuid) - : JackRequest(JackRequest::kClientCheck), fProtocol(protocol), fOptions(options), fUUID(uuid) + JackClientCheckRequest(const char* name, int protocol, int options, int uuid, int open = false) + : JackRequest(JackRequest::kClientCheck), fProtocol(protocol), fOptions(options), fUUID(uuid), fOpen(open) { snprintf(fName, sizeof(fName), "%s", name); } @@ -163,7 +164,8 @@ struct JackClientCheckRequest : public JackRequest CheckRes(trans->Read(&fName, sizeof(fName))); CheckRes(trans->Read(&fProtocol, sizeof(int))); CheckRes(trans->Read(&fOptions, sizeof(int))); - return trans->Read(&fUUID, sizeof(int)); + CheckRes(trans->Read(&fUUID, sizeof(int))); + return trans->Read(&fOpen, sizeof(int)); } int Write(JackChannelTransaction* trans) @@ -172,7 +174,8 @@ struct JackClientCheckRequest : public JackRequest CheckRes(trans->Write(&fName, sizeof(fName))); CheckRes(trans->Write(&fProtocol, sizeof(int))); CheckRes(trans->Write(&fOptions, sizeof(int))); - return trans->Write(&fUUID, sizeof(int)); + CheckRes(trans->Write(&fUUID, sizeof(int))); + return trans->Write(&fOpen, sizeof(int)); } }; diff --git a/common/JackServer.cpp b/common/JackServer.cpp index 22027c9c..0c270165 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -22,7 +22,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackServerGlobals.h" #include "JackTime.h" #include "JackFreewheelDriver.h" -#include "JackDummyDriver.h" #include "JackThreadedDriver.h" #include "JackGlobals.h" #include "JackLockedEngine.h" diff --git a/common/JackServerAPI.cpp b/common/JackServerAPI.cpp index e5a0b057..3f637445 100644 --- a/common/JackServerAPI.cpp +++ b/common/JackServerAPI.cpp @@ -33,17 +33,14 @@ extern "C" { #endif - jack_client_t * jack_client_new_aux (const char *client_name, - jack_options_t options, - jack_status_t *status); - jack_client_t * jack_client_open_aux (const char *client_name, - jack_options_t options, - jack_status_t *status, va_list ap); - LIB_EXPORT jack_client_t * jack_client_open (const char *client_name, + jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t options, jack_status_t* status); + jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t options, jack_status_t* status, va_list ap); + + SERVER_EXPORT jack_client_t * jack_client_open (const char *client_name, jack_options_t options, jack_status_t *status, ...); - LIB_EXPORT int jack_client_close (jack_client_t *client); - LIB_EXPORT int jack_get_client_pid (const char *name); + SERVER_EXPORT int jack_client_close (jack_client_t *client); + SERVER_EXPORT int jack_get_client_pid (const char *name); #ifdef __cplusplus } @@ -153,7 +150,7 @@ jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t opti } } -LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) +SERVER_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_client_open"); @@ -176,7 +173,7 @@ LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_opt } } -LIB_EXPORT int jack_client_close(jack_client_t* ext_client) +SERVER_EXPORT int jack_client_close(jack_client_t* ext_client) { #ifdef __CLIENTDEBUG__ JackGlobals::CheckContext("jack_client_close"); @@ -198,7 +195,7 @@ LIB_EXPORT int jack_client_close(jack_client_t* ext_client) return res; } -LIB_EXPORT int jack_get_client_pid(const char *name) +SERVER_EXPORT int jack_get_client_pid(const char *name) { return (JackServerGlobals::fInstance != NULL) ? JackServerGlobals::fInstance->GetEngine()->GetClientPID(name) diff --git a/common/JackShmMem.h b/common/JackShmMem.h index 619e81f6..13d1c43a 100644 --- a/common/JackShmMem.h +++ b/common/JackShmMem.h @@ -156,11 +156,12 @@ class JackShmReadWritePtr { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmReadWritePtr::Init %ld %ld", index, fInfo.index); - if (jack_initialize_shm(server_name) < 0) - throw - 1; + if (jack_initialize_shm(server_name) < 0) { + throw std::bad_alloc(); + } fInfo.index = index; if (jack_attach_lib_shm(&fInfo)) { - throw - 2; + throw std::bad_alloc(); } GetShmAddress()->LockMemory(); } @@ -237,11 +238,12 @@ class JackShmReadWritePtr1 { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmReadWritePtr1::Init %ld %ld", index, fInfo.index); - if (jack_initialize_shm(server_name) < 0) - throw - 1; + if (jack_initialize_shm(server_name) < 0) { + throw std::bad_alloc(); + } fInfo.index = index; if (jack_attach_lib_shm(&fInfo)) { - throw - 2; + throw std::bad_alloc(); } /* nobody else needs to access this shared memory any more, so @@ -324,11 +326,12 @@ class JackShmReadPtr { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmPtrRead::Init %ld %ld", index, fInfo.index); - if (jack_initialize_shm(server_name) < 0) - throw - 1; + if (jack_initialize_shm(server_name) < 0) { + throw std::bad_alloc(); + } fInfo.index = index; if (jack_attach_lib_shm_read(&fInfo)) { - throw - 2; + throw std::bad_alloc(); } GetShmAddress()->LockMemory(); } diff --git a/common/JackThreadedDriver.cpp b/common/JackThreadedDriver.cpp index 29fab30f..9500dadb 100644 --- a/common/JackThreadedDriver.cpp +++ b/common/JackThreadedDriver.cpp @@ -21,6 +21,7 @@ #include "JackSystemDeps.h" #include "JackThreadedDriver.h" #include "JackError.h" +#include "JackTools.h" #include "JackGlobals.h" #include "JackEngineControl.h" @@ -67,11 +68,6 @@ int JackThreadedDriver::Process() return fDriver->Process(); } -int JackThreadedDriver::ProcessNull() -{ - return fDriver->ProcessNull(); -} - int JackThreadedDriver::Attach() { return fDriver->Attach(); @@ -228,22 +224,30 @@ bool JackThreadedDriver::Execute() bool JackThreadedDriver::Init() { if (fDriver->Initialize()) { - if (fDriver->IsRealTime()) { - jack_log("JackThreadedDriver::Init IsRealTime"); - // Will do "something" on OSX only... - GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000; - GetEngineControl()->fComputation = ComputationMicroSec(GetEngineControl()->fBufferSize) * 1000; - fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); - if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) { - jack_error("AcquireSelfRealTime error"); - } else { - set_threaded_log_function(); - } - } + SetRealTime(); return true; } else { return false; } } +void JackThreadedDriver::SetRealTime() +{ + if (fDriver->IsRealTime()) { + jack_log("JackThreadedDriver::Init real-time"); + // Will do "something" on OSX only... + GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000; + GetEngineControl()->fComputation = JackTools::ComputationMicroSec(GetEngineControl()->fBufferSize) * 1000; + fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); + if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) { + jack_error("AcquireSelfRealTime error"); + } else { + set_threaded_log_function(); + } + } else { + jack_log("JackThreadedDriver::Init non non-realtime "); + } +} + + } // end of namespace diff --git a/common/JackThreadedDriver.h b/common/JackThreadedDriver.h index 83d09faf..12d77471 100644 --- a/common/JackThreadedDriver.h +++ b/common/JackThreadedDriver.h @@ -39,6 +39,8 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi JackThread fThread; JackDriver* fDriver; + void SetRealTime(); + public: JackThreadedDriver(JackDriver* driver); @@ -72,7 +74,6 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi virtual int Close(); virtual int Process(); - virtual int ProcessNull(); virtual int Attach(); virtual int Detach(); @@ -110,18 +111,6 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi virtual bool Execute(); virtual bool Init(); - // For OSX only - int ComputationMicroSec(int buffer_size) - { - if (buffer_size < 128) { - return 500; - } else if (buffer_size < 256) { - return 300; - } else { - return 100; - } - } - }; } // end of namespace diff --git a/common/JackTimedDriver.cpp b/common/JackTimedDriver.cpp new file mode 100644 index 00000000..68b98b6f --- /dev/null +++ b/common/JackTimedDriver.cpp @@ -0,0 +1,86 @@ +/* +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. + +*/ + +#include "JackTimedDriver.h" +#include "JackEngineControl.h" +#include "JackTime.h" +#include "JackCompilerDeps.h" +#include <iostream> +#include <unistd.h> +#include <math.h> + +namespace Jack +{ + +int JackTimedDriver::FirstCycle(jack_time_t cur_time) +{ + fAnchorTime = cur_time; + return int((double(fEngineControl->fBufferSize) * 1000000) / double(fEngineControl->fSampleRate)); +} + +int JackTimedDriver::CurrentCycle(jack_time_t cur_time) +{ + return int((double(fCycleCount) * double(fEngineControl->fBufferSize) * 1000000.) / double(fEngineControl->fSampleRate)) - (cur_time - fAnchorTime); +} + +int JackTimedDriver::ProcessAux() +{ + jack_time_t cur_time = GetMicroSeconds(); + int wait_time; + + if (fCycleCount++ == 0) { + wait_time = FirstCycle(cur_time); + } else { + wait_time = CurrentCycle(cur_time); + } + + if (wait_time < 0) { + NotifyXRun(cur_time, float(cur_time -fBeginDateUst)); + fCycleCount = 0; + wait_time = 0; + } + + //jack_log("JackTimedDriver::Process wait_time = %d", wait_time); + JackSleep(wait_time); + return 0; +} + +int JackTimedDriver::Process() +{ + JackDriver::CycleTakeBeginTime(); + JackAudioDriver::Process(); + + return ProcessAux(); +} + +int JackTimedDriver::ProcessNull() +{ + JackDriver::CycleTakeBeginTime(); + + if (fEngineControl->fSyncMode) { + ProcessGraphSyncMaster(); + } else { + ProcessGraphAsyncMaster(); + } + + return ProcessAux(); +} + +} // end of namespace diff --git a/common/JackTimedDriver.h b/common/JackTimedDriver.h new file mode 100644 index 00000000..987bfab4 --- /dev/null +++ b/common/JackTimedDriver.h @@ -0,0 +1,66 @@ +/* +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 __JackTimedDriver__ +#define __JackTimedDriver__ + +#include "JackAudioDriver.h" + +namespace Jack +{ + +/*! +\brief The timed driver. +*/ + +class SERVER_EXPORT JackTimedDriver : public JackAudioDriver +{ + private: + + int fCycleCount; + jack_time_t fAnchorTime; + + int FirstCycle(jack_time_t cur_time); + int CurrentCycle(jack_time_t cur_time); + + int ProcessAux(); + + public: + + JackTimedDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) + : JackAudioDriver(name, alias, engine, table), fCycleCount(0), fAnchorTime(0) + {} + virtual ~JackTimedDriver() + {} + + virtual int Process(); + virtual int ProcessNull(); + + // BufferSize can be changed + bool IsFixedBufferSize() + { + return false; + } + +}; + +} // end of namespace + +#endif diff --git a/common/JackTools.h b/common/JackTools.h index 50451e04..4b312563 100644 --- a/common/JackTools.h +++ b/common/JackTools.h @@ -68,8 +68,20 @@ namespace Jack static void CleanupFiles ( const char* server_name ); static int GetTmpdir(); static void RewriteName ( const char* name, char* new_name ); - + static void ThrowJackNetException(); + + // For OSX only + static int ComputationMicroSec(int buffer_size) + { + if (buffer_size < 128) { + return 500; + } else if (buffer_size < 256) { + return 300; + } else { + return 100; + } + } }; /*! diff --git a/common/JackWaitThreadedDriver.cpp b/common/JackWaitThreadedDriver.cpp index 76637440..dd52a9d9 100644 --- a/common/JackWaitThreadedDriver.cpp +++ b/common/JackWaitThreadedDriver.cpp @@ -25,6 +25,7 @@ #include "JackEngineControl.h" #include "JackException.h" #include "JackError.h" +#include "JackTools.h" namespace Jack { @@ -37,44 +38,44 @@ bool JackWaitThreadedDriver::Init() bool JackWaitThreadedDriver::Execute() { try { + + SetRealTime(); + // Process a null cycle until NetDriver has started while (!fStarter.fRunning && fThread.GetStatus() == JackThread::kRunning) { - fDriver->ProcessNull(); - } - - // Set RT - if (fDriver->IsRealTime()) { - jack_log("JackWaitThreadedDriver::Init IsRealTime"); - // Will do "something" on OSX only... - GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000; - GetEngineControl()->fComputation = ComputationMicroSec(GetEngineControl()->fBufferSize) * 1000; - fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); - if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) { - jack_error("AcquireSelfRealTime error"); - } else { - set_threaded_log_function(); - } + // Use the base method + assert(static_cast<JackTimedDriver*>(fDriver)); + static_cast<JackTimedDriver*>(fDriver)->ProcessNull(); } // Switch to keep running even in case of error while (fThread.GetStatus() == JackThread::kRunning) { fDriver->Process(); } + return false; + } catch (JackNetException& e) { + e.PrintMessage(); jack_info("Driver is restarted"); fThread.DropSelfRealTime(); + + // Thread has been stopped... + if (fThread.GetStatus() == JackThread::kIdle) { + return false; + } + // Thread in kIniting status again... fThread.SetStatus(JackThread::kIniting); if (Init()) { // Thread in kRunning status again... fThread.SetStatus(JackThread::kRunning); return true; - } else { - return false; } - } + + return false; + } } } // end of namespace diff --git a/common/JackWaitThreadedDriver.h b/common/JackWaitThreadedDriver.h index 83a8e351..f98a4e4a 100644 --- a/common/JackWaitThreadedDriver.h +++ b/common/JackWaitThreadedDriver.h @@ -22,7 +22,7 @@ #define __JackWaitThreadedDriver__ #include "JackThreadedDriver.h" -#include "JackDriver.h" +#include "JackTimedDriver.h" namespace Jack { @@ -31,7 +31,7 @@ namespace Jack \brief To be used as a wrapper of JackNetDriver. The idea is to behave as the "dummy" driver, until the network connection is really started and processing starts. -The Execute method will call the ProcessNull method until the decorated driver Init method returns. +The Execute method will call the Process method from the base JackTimedDriver, until the decorated driver Init method returns. A helper JackDriverStarter thread is used for that purpose. */ @@ -81,7 +81,7 @@ class SERVER_EXPORT JackWaitThreadedDriver : public JackThreadedDriver public: JackWaitThreadedDriver(JackDriver* net_driver) - :JackThreadedDriver(net_driver), fStarter(net_driver) + : JackThreadedDriver(net_driver), fStarter(net_driver) {} virtual ~JackWaitThreadedDriver() {} diff --git a/common/driver_interface.h b/common/driver_interface.h index fad24137..4645c2f0 100644 --- a/common/driver_interface.h +++ b/common/driver_interface.h @@ -115,16 +115,16 @@ typedef struct { } jack_driver_desc_filler_t; -LIB_EXPORT int jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr); +SERVER_EXPORT int jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr); -LIB_EXPORT jack_driver_desc_t * /* newlly allocated driver descriptor, NULL on failure */ +SERVER_EXPORT jack_driver_desc_t * /* newlly allocated driver descriptor, NULL on failure */ jack_driver_descriptor_construct( const char * name, /* driver name */ const char * description, /* driver description */ jack_driver_desc_filler_t * filler); /* Pointer to stack var to be supplied to jack_driver_descriptor_add_parameter() as well. Can be NULL for drivers that have no parameters. */ -LIB_EXPORT int /* 0 on failure */ +SERVER_EXPORT int /* 0 on failure */ jack_driver_descriptor_add_parameter( jack_driver_desc_t * driver_descr, /* pointer to driver descriptor as returned by jack_driver_descriptor_construct() */ jack_driver_desc_filler_t * filler, /* Pointer to the stack var that was supplied to jack_driver_descriptor_add_parameter(). */ diff --git a/common/jack/jack.h b/common/jack/jack.h index 3177a795..03d601b0 100644 --- a/common/jack/jack.h +++ b/common/jack/jack.h @@ -735,7 +735,6 @@ int jack_port_unregister (jack_client_t *, jack_port_t *) JACK_OPTIONAL_WEAK_EXP * 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; -void * jack_port_get_buffer_nulled(jack_port_t* port, jack_nframes_t frames) JACK_OPTIONAL_WEAK_EXPORT; /** * @return the full name of the jack_port_t (including the @a diff --git a/common/jack/net.h b/common/jack/net.h index 001868be..4c9a389b 100644 --- a/common/jack/net.h +++ b/common/jack/net.h @@ -28,25 +28,18 @@ extern "C" #include <jack/systemdeps.h> #include <jack/types.h> -#define DEFAULT_MULTICAST_IP "225.3.19.154" -#define DEFAULT_PORT 19000 -#define DEFAULT_MTU 1500 -#define MASTER_NAME_SIZE 256 +#define DEFAULT_MULTICAST_IP "225.3.19.154" +#define DEFAULT_PORT 19000 +#define DEFAULT_MTU 1500 +#define MASTER_NAME_SIZE 256 #define SOCKET_ERROR -1 -enum JackNetMode { - - JackFastMode = 'f', - JackNormalMode = 'n', - JackSlowMode = 's', -}; - enum JackNetEncoder { - JackFloatEncoder = 0, // Samples are transmitted as float - JackIntEncoder = 1, // Samples are transmitted as 16 bits integer - JackCeltEncoder = 2, // Samples are transmitted using CELT codec (http://www.celt-codec.org/) + JackFloatEncoder = 0, // samples are transmitted as float + JackIntEncoder = 1, // samples are transmitted as 16 bits integer + JackCeltEncoder = 2, // samples are transmitted using CELT codec (http://www.celt-codec.org/) }; typedef struct { @@ -57,9 +50,9 @@ typedef struct { int midi_output; // to master or from slave (-1 for get master MIDI physical inputs) int mtu; // network Maximum Transmission Unit int time_out; // in second, -1 means in infinite - int encoder; // Encoder type (one of JackNetEncoder) + int encoder; // encoder type (one of JackNetEncoder) int kbps; // KB per second for CELT encoder - char mode; // one of JackNetMode + int latency; // network latency } jack_slave_t; @@ -111,7 +104,7 @@ int jack_net_slave_close(jack_net_slave_t* net); * @param audio_output_buffer an array of audio output buffers (to master) * @param midi_output number of MIDI outputs * @param midi_output_buffer an array of MIDI output buffers (to master) - * @param arg pointer to a client supplied structure supplied by jack_set_net_process_callback(). + * @param arg pointer to a client supplied structure supplied by jack_set_net_process_callback() * * @return zero on success, non-zero on error */ @@ -155,16 +148,16 @@ int jack_net_slave_deactivate(jack_net_slave_t* net); /** * Prototype for BufferSize callback. * @param nframes buffer size - * @param arg pointer to a client supplied structure supplied by jack_set_net_buffer_size_callback(). + * @param arg pointer to a client supplied structure supplied by jack_set_net_buffer_size_callback() * * @return zero on success, non-zero on error */ typedef int (*JackNetSlaveBufferSizeCallback)(jack_nframes_t nframes, void *arg); /** - * Prototype for SampleRate callback + * Prototype for SampleRate callback. * @param nframes sample rate - * @param arg pointer to a client supplied structure supplied by jack_set_net_sample_rate_callback(). + * @param arg pointer to a client supplied structure supplied by jack_set_net_sample_rate_callback() * * @return zero on success, non-zero on error */ @@ -191,8 +184,8 @@ int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveB int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg); /** - * Prototype for server Shutdown callback (if not set, the client will just restart, waiting for an available master again.) - * @param arg pointer to a client supplied structure supplied by jack_set_net_shutdown_callback(). + * Prototype for server Shutdown callback (if not set, the client will just restart, waiting for an available master again). + * @param arg pointer to a client supplied structure supplied by jack_set_net_shutdown_callback() */ typedef void (*JackNetSlaveShutdownCallback)(void* data); @@ -207,8 +200,7 @@ typedef void (*JackNetSlaveShutdownCallback)(void* data); int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg); /** - * jack_net_master_t is an opaque type. You may only access it using the - * API provided. + * jack_net_master_t is an opaque type, you may only access it using the API provided. */ typedef struct _jack_net_master jack_net_master_t; @@ -224,7 +216,7 @@ typedef struct _jack_net_master jack_net_master_t; jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result); /** - * Close the network connection with the master machine. + * Close the network connection with the slave machine. * @param net the network connection to be closed * * @return 0 on success, otherwise a non-zero error code @@ -232,7 +224,7 @@ jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* na int jack_net_master_close(jack_net_master_t* net); /** - * Receive sync and data from the network + * Receive sync and data from the network. * @param net the network connection * @param audio_input number of audio inputs * @param audio_input_buffer an array of audio input buffers @@ -244,7 +236,7 @@ int jack_net_master_close(jack_net_master_t* net); int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); /** - * Send sync and data to the network + * Send sync and data to the network. * @param net the network connection * @param audio_output number of audio outputs * @param audio_output_buffer an array of audio output buffers @@ -258,8 +250,7 @@ int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio // Experimental Adapter API /** - * jack_adapter_t is an opaque type. You may only access it using the - * API provided. + * jack_adapter_t is an opaque type, you may only access it using the API provided. */ typedef struct _jack_adapter jack_adapter_t; @@ -297,7 +288,7 @@ int jack_destroy_adapter(jack_adapter_t* adapter); void jack_flush_adapter(jack_adapter_t* adapter); /** - * Push input to and pull output from adapter ringbuffer + * Push input to and pull output from adapter ringbuffer. * @param adapter the adapter * @param input an array of audio input buffers * @param output an array of audio ouput buffers @@ -308,7 +299,7 @@ void jack_flush_adapter(jack_adapter_t* adapter); int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); /** - * Pull input to and push output from adapter ringbuffer + * Pull input to and push output from adapter ringbuffer. * @param adapter the adapter * @param input an array of audio input buffers * @param output an array of audio ouput buffers diff --git a/common/wscript b/common/wscript index 96e48b08..9a63c15a 100644 --- a/common/wscript +++ b/common/wscript @@ -114,6 +114,7 @@ def build(bld): serverlib.source = [] + common_libsources serverlib.source += [ 'JackAudioDriver.cpp', + 'JackTimedDriver.cpp', 'JackMidiDriver.cpp', 'JackDriver.cpp', 'JackEngine.cpp', diff --git a/example-clients/alias.c b/example-clients/alias.c index 87a19b88..cb2b3f99 100644 --- a/example-clients/alias.c +++ b/example-clients/alias.c @@ -55,7 +55,7 @@ main (int argc, char *argv[]) int option_index; extern int optind; jack_port_t* port; - + struct option long_options[] = { { "unalias", 0, 0, 'u' }, { "help", 0, 0, 'h' }, @@ -129,5 +129,5 @@ main (int argc, char *argv[]) jack_client_close (client); return ret; - + } diff --git a/example-clients/bufsize.c b/example-clients/bufsize.c index c6407c20..771fd5a8 100644 --- a/example-clients/bufsize.c +++ b/example-clients/bufsize.c @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) jack_on_shutdown(client, jack_shutdown, 0); if (just_print_bufsize) { - fprintf(stdout, "%d\n", jack_get_buffer_size( client ) ); + fprintf(stdout, "buffer size = %d sample rate = %d\n", jack_get_buffer_size(client), jack_get_sample_rate(client)); rc=0; } else diff --git a/example-clients/capture_client.c b/example-clients/capture_client.c index 72a2467f..08585051 100644 --- a/example-clients/capture_client.c +++ b/example-clients/capture_client.c @@ -1,7 +1,7 @@ /* Copyright (C) 2001 Paul Davis 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 @@ -100,7 +100,7 @@ disk_thread (void *arg) info->status = EIO; /* write failed */ goto done; } - + if (++total_captured >= info->duration) { printf ("disk thread finished\n"); goto done; @@ -116,7 +116,7 @@ disk_thread (void *arg) free (framebuf); return 0; } - + static int process (jack_nframes_t nframes, void *arg) { @@ -168,10 +168,10 @@ setup_disk_thread (jack_thread_info_t *info) { SF_INFO sf_info; int short_mask; - + sf_info.samplerate = jack_get_sample_rate (info->client); sf_info.channels = info->channels; - + switch (info->bitdepth) { case 8: short_mask = SF_FORMAT_PCM_U8; break; @@ -183,7 +183,7 @@ setup_disk_thread (jack_thread_info_t *info) break; default: short_mask = SF_FORMAT_PCM_16; break; - } + } sf_info.format = SF_FORMAT_WAV|short_mask; if ((info->sf = sf_open (info->path, SFM_WRITE, &sf_info)) == NULL) { @@ -253,7 +253,7 @@ setup_ports (int sources, char *source_names[], jack_thread_info_t *info) fprintf (stderr, "cannot connect input port %s to %s\n", jack_port_name (ports[i]), source_names[i]); jack_client_close (info->client); exit (1); - } + } } info->can_process = 1; /* process() can start, now */ @@ -315,7 +315,7 @@ main (int argc, char *argv[]) } if ((client = jack_client_open ("jackrec", JackNullOption, NULL)) == 0) { - fprintf (stderr, "jack server not running?\n"); + fprintf (stderr, "JACK server not running?\n"); exit (1); } @@ -333,7 +333,7 @@ main (int argc, char *argv[]) } setup_ports (argc - optind, &argv[optind], &thread_info); - + /* install a signal handler to properly quits jack client */ signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); diff --git a/example-clients/connect.c b/example-clients/connect.c index 3c6de6b9..5ed112b0 100644 --- a/example-clients/connect.c +++ b/example-clients/connect.c @@ -133,7 +133,7 @@ main (int argc, char *argv[]) /* try to become a client of the JACK server */ if ((client = jack_client_open (my_name, options, &status, server_name)) == 0) { - fprintf (stderr, "jack server not running?\n"); + fprintf (stderr, "JACK server not running?\n"); return 1; } diff --git a/example-clients/freewheel.c b/example-clients/freewheel.c index c0892833..a59a8cec 100644 --- a/example-clients/freewheel.c +++ b/example-clients/freewheel.c @@ -2,7 +2,7 @@ * freewheel - start/stop JACK "freewheeling" mode * * Copyright (C) 2003 Paul Davis. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -58,7 +58,7 @@ static void parse_arguments(int argc, char *argv[]) } } -int +int main (int argc, char *argv[]) { parse_arguments (argc, argv); diff --git a/example-clients/impulse_grabber.c b/example-clients/impulse_grabber.c index 0a1fd706..80006c0b 100644 --- a/example-clients/impulse_grabber.c +++ b/example-clients/impulse_grabber.c @@ -36,7 +36,7 @@ unsigned long response_duration; unsigned long response_pos; int grab_finished = 0; jack_client_t *client; - + static void signal_handler(int sig) { jack_client_close(client); @@ -60,7 +60,7 @@ process (jack_nframes_t nframes, void *arg) } if (response_pos >= response_duration) { grab_finished = 1; - } + } for (i=0; i<nframes; i++) { out[i] = 0.0f;; } @@ -72,7 +72,7 @@ process (jack_nframes_t nframes, void *arg) impulse_sent = 1; } - return 0; + return 0; } static void @@ -132,7 +132,7 @@ main (int argc, char *argv[]) /* try to become a client of the JACK server */ if ((client = jack_client_open("impulse_grabber", JackNullOption, NULL)) == 0) { - fprintf (stderr, "jack server not running?\n"); + fprintf (stderr, "JACK server not running?\n"); return 1; } @@ -149,7 +149,7 @@ main (int argc, char *argv[]) jack_on_shutdown (client, jack_shutdown, 0); - /* display the current sample rate. once the client is activated + /* 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. */ @@ -187,7 +187,7 @@ main (int argc, char *argv[]) } free (ports); - + if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) { fprintf(stderr, "Cannot find any physical playback ports"); exit(1); @@ -198,7 +198,7 @@ main (int argc, char *argv[]) } free (ports); - + /* install a signal handler to properly quits jack client */ signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); diff --git a/example-clients/ipunload.c b/example-clients/ipunload.c index baedfc1e..2ce3d0c8 100644 --- a/example-clients/ipunload.c +++ b/example-clients/ipunload.c @@ -85,9 +85,9 @@ main (int argc, char *argv[]) } else { fprintf (stdout, "%s unloaded.\n", client_name); } - + jack_client_close(client); return 0; } - - + + diff --git a/example-clients/lsp.c b/example-clients/lsp.c index ee18f5ba..81700cdc 100644 --- a/example-clients/lsp.c +++ b/example-clients/lsp.c @@ -20,7 +20,7 @@ #include <unistd.h> #endif #include <string.h> -#include <getopt.h>
+#include <getopt.h> #include <inttypes.h> #include <jack/jack.h> @@ -246,3 +246,4 @@ error: jack_client_close (client); exit (0); } + diff --git a/example-clients/metro.c b/example-clients/metro.c index d2daaa7f..feaa144a 100644 --- a/example-clients/metro.c +++ b/example-clients/metro.c @@ -1,6 +1,6 @@ /* Copyright (C) 2002 Anthony Van Groningen - + 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 @@ -69,18 +69,21 @@ usage () } static void -process_silence (jack_nframes_t nframes) +process_silence (jack_nframes_t nframes) { sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); memset (buffer, 0, sizeof (jack_default_audio_sample_t) * nframes); } +jack_nframes_t last_time; +jack_time_t last_micro_time; + static void -process_audio (jack_nframes_t nframes) +process_audio (jack_nframes_t nframes) { sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); jack_nframes_t frames_left = nframes; - + while (wave_length - offset < frames_left) { memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * (wave_length - offset)); frames_left -= wave_length - offset; @@ -90,6 +93,15 @@ process_audio (jack_nframes_t nframes) memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * frames_left); offset += frames_left; } + + /* + jack_nframes_t cur_time = jack_frame_time(client); + jack_time_t cur_micro_time = jack_get_time(); + + printf("jack_frame_timed %lld micro %lld delta %d\n", cur_time, (cur_micro_time - last_micro_time), cur_time - last_time); + last_time = cur_time; + last_micro_time = cur_micro_time; + */ } static int @@ -141,7 +153,7 @@ main (int argc, char *argv[]) {"verbose", 0, 0, 'v'}, {0, 0, 0, 0} }; - + while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { switch (opt) { case 'f': @@ -193,7 +205,7 @@ main (int argc, char *argv[]) transport_aware = 1; break; default: - fprintf (stderr, "unknown option %c\n", opt); + fprintf (stderr, "unknown option %c\n", opt); case 'h': usage (); return -1; @@ -211,7 +223,7 @@ main (int argc, char *argv[]) strcpy (client_name, "metro"); } if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) { - fprintf (stderr, "jack server not running?\n"); + fprintf (stderr, "JACK server not running?\n"); return 1; } jack_set_process_callback (client, process, 0); @@ -259,7 +271,7 @@ main (int argc, char *argv[]) fprintf (stderr, "cannot activate client\n"); goto error; } - + /* install a signal handler to properly quits jack client */ #ifdef WIN32 signal(SIGINT, signal_handler); @@ -280,9 +292,9 @@ main (int argc, char *argv[]) sleep(1); #endif }; - + jack_client_close(client); - + error: free(amp); free(wave); diff --git a/example-clients/midiseq.c b/example-clients/midiseq.c index 10a37b2a..60b3e483 100644 --- a/example-clients/midiseq.c +++ b/example-clients/midiseq.c @@ -1,6 +1,6 @@ /* Copyright (C) 2004 Ian Esten - + 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 @@ -93,7 +93,7 @@ int main(int narg, char **args) } if((client = jack_client_open (args[1], JackNullOption, NULL)) == 0) { - fprintf (stderr, "jack server not running?\n"); + fprintf (stderr, "JACK server not running?\n"); return 1; } jack_set_process_callback (client, process, 0); @@ -117,7 +117,7 @@ int main(int narg, char **args) fprintf (stderr, "cannot activate client"); return 1; } - + /* install a signal handler to properly quits jack client */ signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); @@ -128,7 +128,7 @@ int main(int narg, char **args) while (1) { sleep(1); }; - + jack_client_close(client); exit (0); } diff --git a/example-clients/midisine.c b/example-clients/midisine.c index 89ff7f75..ce830019 100644 --- a/example-clients/midisine.c +++ b/example-clients/midisine.c @@ -1,6 +1,6 @@ /* Copyright (C) 2004 Ian Esten - + 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 @@ -76,7 +76,7 @@ static int process(jack_nframes_t nframes, void *arg) if ((in_event.time == i) && (event_index < event_count)) { if (((*(in_event.buffer) & 0xf0)) == 0x90) - { + { /* note on */ note = *(in_event.buffer + 1); if (*(in_event.buffer + 2) == 0) { @@ -99,7 +99,7 @@ static int process(jack_nframes_t nframes, void *arg) ramp = (ramp > 1.0) ? ramp - 2.0 : ramp; out[i] = note_on*sin(2*M_PI*ramp); } - return 0; + return 0; } static int srate(jack_nframes_t nframes, void *arg) @@ -118,10 +118,10 @@ int main(int narg, char **args) { if ((client = jack_client_open("midisine", JackNullOption, NULL)) == 0) { - fprintf(stderr, "jack server not running?\n"); + fprintf(stderr, "JACK server not running?\n"); return 1; } - + calc_note_frqs(jack_get_sample_rate (client)); jack_set_process_callback (client, process, 0); @@ -138,7 +138,7 @@ int main(int narg, char **args) fprintf(stderr, "cannot activate client"); return 1; } - + /* install a signal handler to properly quits jack client */ signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); diff --git a/example-clients/monitor_client.c b/example-clients/monitor_client.c index 0a89b17c..36f61d6f 100644 --- a/example-clients/monitor_client.c +++ b/example-clients/monitor_client.c @@ -42,7 +42,7 @@ main (int argc, char *argv[]) } if ((client = jack_client_open ("input monitoring", JackNullOption, NULL)) == 0) { - fprintf (stderr, "jack server not running?\n"); + fprintf (stderr, "JACK server not running?\n"); return 1; } diff --git a/example-clients/netmaster.c b/example-clients/netmaster.c index be7eb0e6..c9dd42ae 100644 --- a/example-clients/netmaster.c +++ b/example-clients/netmaster.c @@ -108,7 +108,7 @@ main (int argc, char *argv[]) printf("Waiting for a slave...\n"); if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "net_master", &request, &result)) == 0) { - fprintf(stderr, "jack server not running?\n"); + fprintf(stderr, "NetJack master can not be opened\n"); return 1; } diff --git a/example-clients/netslave.c b/example-clients/netslave.c index 446d1561..2c136de9 100644 --- a/example-clients/netslave.c +++ b/example-clients/netslave.c @@ -1,6 +1,6 @@ /* Copyright (C) 2009 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 @@ -55,18 +55,18 @@ static void net_shutdown(void* data) } static int net_process(jack_nframes_t buffer_size, - int audio_input, - float** audio_input_buffer, + int audio_input, + float** audio_input_buffer, int midi_input, void** midi_input_buffer, int audio_output, - float** audio_output_buffer, - int midi_output, - void** midi_output_buffer, + float** audio_output_buffer, + int midi_output, + void** midi_output_buffer, void* data) { int i; - + // Copy input to output for (i = 0; i < audio_input; i++) { memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); @@ -84,7 +84,7 @@ main (int argc, char *argv[]) const char *options = "C:P:a:p:"; int option_index; int opt; - + struct option long_options[] = { {"audio input", 1, 0, 'C'}, @@ -93,53 +93,53 @@ main (int argc, char *argv[]) {"port", 1, 0, 'p'}, {0, 0, 0, 0} }; - + while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { - + switch (opt) { - + case 'C': audio_input = atoi(optarg); break; - + case 'P': audio_output = atoi(optarg); break; - + case 'a': multicast_ip = strdup(optarg); break; - + case 'p': port = atoi(optarg); break; - + case 'h': usage(); return -1; } } - jack_slave_t request = { audio_input, audio_output, 0, 0, DEFAULT_MTU, -1, JackSlowMode }; + jack_slave_t request = { audio_input, audio_output, 0, 0, DEFAULT_MTU, -1, JackFloatEncoder, 0, 2 }; jack_master_t result; - + printf("Waiting for a master...\n"); if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "net_slave", &request, &result)) == 0) { - fprintf(stderr, "jack server not running?\n"); + fprintf(stderr, "JACK server not running?\n"); return 1; } - printf("Slave is found and running...\n"); + printf("Master is found and running...\n"); jack_set_net_slave_process_callback(net, net_process, NULL); jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL); if (jack_net_slave_activate(net) != 0) { - fprintf(stderr, "Cannot sactivate client\n"); + fprintf(stderr, "Cannot activate slave client\n"); return 1; } - + /* install a signal handler to properly quits jack client */ #ifdef WIN32 signal(SIGINT, signal_handler); @@ -160,9 +160,9 @@ main (int argc, char *argv[]) sleep(1); #endif }; - + // Wait for application end jack_net_slave_deactivate(net); jack_net_slave_close(net); - exit (0); + exit(0); } diff --git a/example-clients/showtime.c b/example-clients/showtime.c index af413e89..fbbb94b7 100644 --- a/example-clients/showtime.c +++ b/example-clients/showtime.c @@ -34,7 +34,7 @@ showtime () transport_state = jack_transport_query (client, ¤t); frame_time = jack_frame_time (client); - + printf ("frame = %u frame_time = %u usecs = %lld \t", current.frame, frame_time, current.usecs); switch (transport_state) { @@ -81,7 +81,7 @@ main (int argc, char *argv[]) /* try to become a client of the JACK server */ if ((client = jack_client_open ("showtime", JackNullOption, NULL)) == 0) { - fprintf (stderr, "jack server not running?\n"); + fprintf (stderr, "JACK server not running?\n"); return 1; } @@ -103,7 +103,7 @@ main (int argc, char *argv[]) fprintf (stderr, "cannot activate client"); return 1; } - + while (1) { usleep (20); showtime (); diff --git a/example-clients/zombie.c b/example-clients/zombie.c index fb3cd24e..c982cfa8 100644 --- a/example-clients/zombie.c +++ b/example-clients/zombie.c @@ -54,7 +54,7 @@ main (int argc, char *argv[]) jack_client_t* client = NULL; /* try to become a client of the JACK server */ if ((client = jack_client_open ("zombie", JackNullOption, NULL)) == 0) { - fprintf (stderr, "jack server not running?\n"); + fprintf (stderr, "JACK server not running?\n"); goto error; } diff --git a/linux/JackLinuxTime.c b/linux/JackLinuxTime.c index c80eb17d..18e616eb 100644 --- a/linux/JackLinuxTime.c +++ b/linux/JackLinuxTime.c @@ -143,7 +143,7 @@ static jack_time_t jack_get_mhz (void) exit(1); } - for ( ; ; ) + for (;;) { jack_time_t mhz; int ret; diff --git a/macosx/Jackdmp.xcodeproj/project.pbxproj b/macosx/Jackdmp.xcodeproj/project.pbxproj index 5b93588c..b9693086 100644 --- a/macosx/Jackdmp.xcodeproj/project.pbxproj +++ b/macosx/Jackdmp.xcodeproj/project.pbxproj @@ -123,6 +123,12 @@ 4B19B31C0E2362E800DD4A82 /* JackLibSampleRateResampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19B30F0E2362E700DD4A82 /* JackLibSampleRateResampler.h */; }; 4B19B31F0E2362E800DD4A82 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B3120E2362E700DD4A82 /* JackResampler.cpp */; }; 4B20220A133A9C1C0019E213 /* midi_latency_test.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B202209133A9C1C0019E213 /* midi_latency_test.c */; }; + 4B21794F13E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */; }; + 4B21795013E2EEA60095B3E5 /* JackTimedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */; }; + 4B21795113E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */; }; + 4B21795213E2EEA60095B3E5 /* JackTimedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */; }; + 4B21795313E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */; }; + 4B21795413E2EEA60095B3E5 /* JackTimedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */; }; 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 */; }; @@ -590,6 +596,32 @@ 4B6C738A0CC60A85001AFFD4 /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6C737D0CC60A6D001AFFD4 /* thread.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B6C738B0CC60A86001AFFD4 /* transport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6C737E0CC60A6D001AFFD4 /* transport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B6F7AEE0CD0CDBD00F48A9D /* JackEngineControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6F7AEC0CD0CDBD00F48A9D /* JackEngineControl.cpp */; }; + 4B6FE13A13DDABE000B4B943 /* JackSocketServerNotifyChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B60E703B8D0066E42F /* JackSocketServerNotifyChannel.h */; }; + 4B6FE13B13DDABE700B4B943 /* JackSocketServerNotifyChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B50E703B8D0066E42F /* JackSocketServerNotifyChannel.cpp */; }; + 4B6FE13C13DDABF100B4B943 /* JackSocketServerChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B40E703B8D0066E42F /* JackSocketServerChannel.h */; }; + 4B6FE13D13DDABFA00B4B943 /* JackSocketServerChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B30E703B8D0066E42F /* JackSocketServerChannel.cpp */; }; + 4B6FE13E13DDAC0500B4B943 /* JackSocketNotifyChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B20E703B8D0066E42F /* JackSocketNotifyChannel.h */; }; + 4B6FE13F13DDAC0C00B4B943 /* JackSocketNotifyChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B10E703B8D0066E42F /* JackSocketNotifyChannel.cpp */; }; + 4B6FE14413DDAC4700B4B943 /* JackSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6AD0E703B8D0066E42F /* JackSocket.cpp */; }; + 4B6FE14513DDAC4C00B4B943 /* JackSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6AE0E703B8D0066E42F /* JackSocket.h */; }; + 4B6FE14D13DDACCC00B4B943 /* JackMidiAsyncQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193931133F311400547810 /* JackMidiAsyncQueue.cpp */; }; + 4B6FE14E13DDACD200B4B943 /* JackMidiAsyncQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193932133F311400547810 /* JackMidiAsyncQueue.h */; }; + 4B6FE15313DDACEF00B4B943 /* JackMidiBufferWriteQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193968133F319000547810 /* JackMidiBufferWriteQueue.cpp */; }; + 4B6FE15413DDACF300B4B943 /* JackMidiBufferWriteQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193969133F319000547810 /* JackMidiBufferWriteQueue.h */; }; + 4B6FE15B13DDAD3D00B4B943 /* JackMidiWriteQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19397A133F31CB00547810 /* JackMidiWriteQueue.h */; }; + 4B6FE15C13DDAD4600B4B943 /* JackMidiWriteQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193979133F31CB00547810 /* JackMidiWriteQueue.cpp */; }; + 4B6FE15D13DDAD4E00B4B943 /* JackMidiUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193978133F31CB00547810 /* JackMidiUtil.h */; }; + 4B6FE15E13DDAD5300B4B943 /* JackMidiUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193977133F31CB00547810 /* JackMidiUtil.cpp */; }; + 4B6FE15F13DDAD5900B4B943 /* JackMidiSendQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193976133F31CB00547810 /* JackMidiSendQueue.h */; }; + 4B6FE16013DDAD5F00B4B943 /* JackMidiSendQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193975133F31CB00547810 /* JackMidiSendQueue.cpp */; }; + 4B6FE16113DDAD6600B4B943 /* JackMidiReceiveQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193974133F31CB00547810 /* JackMidiReceiveQueue.h */; }; + 4B6FE16213DDAD6F00B4B943 /* JackMidiReceiveQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193973133F31CB00547810 /* JackMidiReceiveQueue.cpp */; }; + 4B6FE16313DDAD7700B4B943 /* JackMidiReadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193946133F315200547810 /* JackMidiReadQueue.h */; }; + 4B6FE16413DDAD7F00B4B943 /* JackMidiReadQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193945133F315200547810 /* JackMidiReadQueue.cpp */; }; + 4B6FE16513DDAD8800B4B943 /* JackMidiBufferReadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19395E133F317300547810 /* JackMidiBufferReadQueue.h */; }; + 4B6FE16613DDAD8F00B4B943 /* JackMidiBufferReadQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19395D133F317300547810 /* JackMidiBufferReadQueue.cpp */; }; + 4B6FE16713DDAD9700B4B943 /* JackMidiAsyncWaitQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19393C133F313000547810 /* JackMidiAsyncWaitQueue.h */; }; + 4B6FE16813DDAD9F00B4B943 /* JackMidiAsyncWaitQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19393B133F313000547810 /* JackMidiAsyncWaitQueue.cpp */; }; 4B80D7E80BA0D17400F035BB /* JackMidiPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B80D7E50BA0D17400F035BB /* JackMidiPort.h */; }; 4B80D7E90BA0D17400F035BB /* JackMidiPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */; }; 4B80D7EA0BA0D17400F035BB /* JackMidiAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E70BA0D17400F035BB /* JackMidiAPI.cpp */; }; @@ -1578,6 +1610,8 @@ 4B19B3120E2362E700DD4A82 /* JackResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackResampler.cpp; path = ../common/JackResampler.cpp; sourceTree = SOURCE_ROOT; }; 4B2021E6133A9BA40019E213 /* jack_midi_latency_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midi_latency_test; sourceTree = BUILT_PRODUCTS_DIR; }; 4B202209133A9C1C0019E213 /* midi_latency_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = midi_latency_test.c; path = "../example-clients/midi_latency_test.c"; sourceTree = SOURCE_ROOT; }; + 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackTimedDriver.cpp; path = ../common/JackTimedDriver.cpp; sourceTree = SOURCE_ROOT; }; + 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackTimedDriver.h; path = ../common/JackTimedDriver.h; sourceTree = SOURCE_ROOT; }; 4B2C28F908DAD01E00249230 /* JackGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobals.cpp; path = ../common/JackGlobals.cpp; sourceTree = SOURCE_ROOT; }; 4B3224E510A3156800838A8E /* jack_netone.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = jack_netone.so; sourceTree = BUILT_PRODUCTS_DIR; }; 4B3224E810A315B100838A8E /* JackNetOneDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetOneDriver.cpp; path = ../common/JackNetOneDriver.cpp; sourceTree = SOURCE_ROOT; }; @@ -3048,6 +3082,8 @@ 4BF8D1B60834EEE400C94B91 /* JackDriver.cpp */, 4BC3988A08B3CF6C00B6F371 /* JackDummyDriver.h */, 4BC3988908B3CF6C00B6F371 /* JackDummyDriver.cpp */, + 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */, + 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */, 4BF3390D0F8B86AF0080FB5B /* MIDI */, 4B19B3010E23629800DD4A82 /* Adapter */, BA222AEA0DC88379001A17F4 /* Net */, @@ -3496,6 +3532,7 @@ 4B97B6781344B50800794F57 /* JackMidiSendQueue.h in Headers */, 4B97B67A1344B51600794F57 /* JackMidiUtil.h in Headers */, 4B97B67C1344B52800794F57 /* JackMidiWriteQueue.h in Headers */, + 4B21795213E2EEA60095B3E5 /* JackTimedDriver.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3968,6 +4005,7 @@ 4B97B65B1344B45600794F57 /* JackMidiSendQueue.h in Headers */, 4B97B65D1344B46400794F57 /* JackMidiUtil.h in Headers */, 4B97B65F1344B47100794F57 /* JackMidiWriteQueue.h in Headers */, + 4B21795013E2EEA60095B3E5 /* JackTimedDriver.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4172,6 +4210,20 @@ 4BC2CA60113C6CD20076717C /* JackNetUnixSocket.h in Headers */, 4B5160AE13215EF900BB7DCB /* systemdeps.h in Headers */, 4B193996133F321500547810 /* JackFilters.h in Headers */, + 4B6FE13A13DDABE000B4B943 /* JackSocketServerNotifyChannel.h in Headers */, + 4B6FE13C13DDABF100B4B943 /* JackSocketServerChannel.h in Headers */, + 4B6FE13E13DDAC0500B4B943 /* JackSocketNotifyChannel.h in Headers */, + 4B6FE14513DDAC4C00B4B943 /* JackSocket.h in Headers */, + 4B6FE14E13DDACD200B4B943 /* JackMidiAsyncQueue.h in Headers */, + 4B6FE15413DDACF300B4B943 /* JackMidiBufferWriteQueue.h in Headers */, + 4B6FE15B13DDAD3D00B4B943 /* JackMidiWriteQueue.h in Headers */, + 4B6FE15D13DDAD4E00B4B943 /* JackMidiUtil.h in Headers */, + 4B6FE15F13DDAD5900B4B943 /* JackMidiSendQueue.h in Headers */, + 4B6FE16113DDAD6600B4B943 /* JackMidiReceiveQueue.h in Headers */, + 4B6FE16313DDAD7700B4B943 /* JackMidiReadQueue.h in Headers */, + 4B6FE16513DDAD8800B4B943 /* JackMidiBufferReadQueue.h in Headers */, + 4B6FE16713DDAD9700B4B943 /* JackMidiAsyncWaitQueue.h in Headers */, + 4B21795413E2EEA60095B3E5 /* JackTimedDriver.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6972,6 +7024,7 @@ 4B97B6721344B4F000794F57 /* JackMidiSendQueue.cpp in Sources */, 4B97B6791344B50F00794F57 /* JackMidiUtil.cpp in Sources */, 4B97B67B1344B51D00794F57 /* JackMidiWriteQueue.cpp in Sources */, + 4B21795113E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7433,6 +7486,7 @@ 4B97B65A1344B44F00794F57 /* JackMidiSendQueue.cpp in Sources */, 4B97B65C1344B45D00794F57 /* JackMidiUtil.cpp in Sources */, 4B97B65E1344B46B00794F57 /* JackMidiWriteQueue.cpp in Sources */, + 4B21794F13E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7642,6 +7696,20 @@ 4BA339A410B2E36800190E3B /* JackArgParser.cpp in Sources */, 4BC2CA5D113C6CC90076717C /* JackNetInterface.cpp in Sources */, 4BC2CA5F113C6CD10076717C /* JackNetUnixSocket.cpp in Sources */, + 4B6FE13B13DDABE700B4B943 /* JackSocketServerNotifyChannel.cpp in Sources */, + 4B6FE13D13DDABFA00B4B943 /* JackSocketServerChannel.cpp in Sources */, + 4B6FE13F13DDAC0C00B4B943 /* JackSocketNotifyChannel.cpp in Sources */, + 4B6FE14413DDAC4700B4B943 /* JackSocket.cpp in Sources */, + 4B6FE14D13DDACCC00B4B943 /* JackMidiAsyncQueue.cpp in Sources */, + 4B6FE15313DDACEF00B4B943 /* JackMidiBufferWriteQueue.cpp in Sources */, + 4B6FE15C13DDAD4600B4B943 /* JackMidiWriteQueue.cpp in Sources */, + 4B6FE15E13DDAD5300B4B943 /* JackMidiUtil.cpp in Sources */, + 4B6FE16013DDAD5F00B4B943 /* JackMidiSendQueue.cpp in Sources */, + 4B6FE16213DDAD6F00B4B943 /* JackMidiReceiveQueue.cpp in Sources */, + 4B6FE16413DDAD7F00B4B943 /* JackMidiReadQueue.cpp in Sources */, + 4B6FE16613DDAD8F00B4B943 /* JackMidiBufferReadQueue.cpp in Sources */, + 4B6FE16813DDAD9F00B4B943 /* JackMidiAsyncWaitQueue.cpp in Sources */, + 4B21795313E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16793,6 +16861,7 @@ ); OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\""; OTHER_LDFLAGS = ( + libcelt.a, "-framework", Carbon, "-framework", @@ -16865,6 +16934,7 @@ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\""; OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2 = "-DLIB_DIR=\\\"lib\\\""; OTHER_LDFLAGS = ( + libcelt.a, "-framework", Carbon, "-framework", diff --git a/macosx/coreaudio/JackCoreAudioAdapter.cpp b/macosx/coreaudio/JackCoreAudioAdapter.cpp index fef7d4d8..319e1ddf 100644 --- a/macosx/coreaudio/JackCoreAudioAdapter.cpp +++ b/macosx/coreaudio/JackCoreAudioAdapter.cpp @@ -391,27 +391,35 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra fPlaying = true; } - if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0) - throw -1; + if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0) { + throw std::bad_alloc(); + } - if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0) - throw -1; + if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0) { + throw std::bad_alloc(); + } - if (SetupBufferSize(fAdaptedBufferSize) < 0) - throw -1; + if (SetupBufferSize(fAdaptedBufferSize) < 0) { + throw std::bad_alloc(); + } - if (SetupSampleRate(fAdaptedSampleRate) < 0) - throw -1; + if (SetupSampleRate(fAdaptedSampleRate) < 0) { + throw std::bad_alloc(); + } - if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) - throw -1; + if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) { + throw std::bad_alloc(); + } - if (fCapturing && fCaptureChannels > 0) - if (SetupBuffers(fCaptureChannels) < 0) - throw -1; + if (fCapturing && fCaptureChannels > 0) { + if (SetupBuffers(fCaptureChannels) < 0) { + throw std::bad_alloc(); + } + } - if (AddListeners() < 0) - throw -1; + if (AddListeners() < 0) { + throw std::bad_alloc(); + } } OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id) diff --git a/macosx/coreaudio/JackCoreAudioDriver.cpp b/macosx/coreaudio/JackCoreAudioDriver.cpp index f3ff2fb2..bad5801f 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.cpp +++ b/macosx/coreaudio/JackCoreAudioDriver.cpp @@ -29,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackCompilerDeps.h" #include "JackLockedEngine.h" +#include <sstream> #include <iostream> #include <CoreServices/CoreServices.h> #include <CoreFoundation/CFNumber.h> @@ -137,15 +138,17 @@ static OSStatus DisplayDeviceNames() CFStringRef UIname; err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable); - if (err != noErr) + if (err != noErr) { return err; + } deviceNum = size / sizeof(AudioDeviceID); AudioDeviceID devices[deviceNum]; err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices); - if (err != noErr) + if (err != noErr) { return err; + } for (i = 0; i < deviceNum; i++) { char device_name[256]; @@ -162,8 +165,9 @@ static OSStatus DisplayDeviceNames() size = 256; err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name); - if (err != noErr) + if (err != noErr) { return err; + } jack_info("Device name = \'%s\', internal name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name); } @@ -171,8 +175,9 @@ static OSStatus DisplayDeviceNames() return noErr; error: - if (UIname != NULL) + if (UIname != NULL) { CFRelease(UIname); + } return err; } @@ -184,6 +189,20 @@ static CFStringRef GetDeviceName(AudioDeviceID id) return (err == noErr) ? UIname : NULL; } +static void ParseChannelList(const string& list, vector<int>& result) +{ + stringstream ss(list); + string token; + int chan; + + while (ss >> token) { + istringstream ins; + ins.str(token); + ins >> chan; + result.push_back(chan); + } +} + OSStatus JackCoreAudioDriver::Render(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, @@ -241,8 +260,9 @@ int JackCoreAudioDriver::Write() int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize; memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size); // Monitor ports - if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) + if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) { memcpy(GetMonitorBuffer(i), buffer, size); + } } else { memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); } @@ -349,8 +369,9 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, Float64 sample_rate = 0; UInt32 outsize = sizeof(Float64); OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate); - if (err != noErr) + if (err != noErr) { return kAudioHardwareUnsupportedOperationError; + } char device_name[256]; const char* digidesign_name = "Digidesign"; @@ -420,11 +441,13 @@ OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id) AudioDeviceID inDefault; AudioDeviceID outDefault; - if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) + if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) { return res; + } - if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) + if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) { return res; + } jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault); @@ -447,8 +470,9 @@ OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id) UInt32 theSize = sizeof(UInt32); AudioDeviceID inDefault; - if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) + if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) { return res; + } if (inDefault == 0) { jack_error("Error : input device is 0, please select a correct one !!"); @@ -465,8 +489,9 @@ OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id) UInt32 theSize = sizeof(UInt32); AudioDeviceID outDefault; - if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) + if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) { return res; + } if (outDefault == 0) { jack_error("Error : output device is 0, please select a correct one !!"); @@ -495,8 +520,9 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channe AudioBufferList bufferList[outSize]; err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList); if (err == noErr) { - for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++) + for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++) { channelCount += bufferList->mBuffers[i].mNumberChannels; + } } } return err; @@ -526,7 +552,7 @@ OSStatus JackCoreAudioDriver::DestroyAggregateDevice() pluginAOPA.mElement = kAudioObjectPropertyElementMaster; UInt32 outDataSize; - if (fPluginID > 0) { + if (fPluginID > 0) { osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); if (osErr != noErr) { @@ -771,8 +797,9 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap vector<CFStringRef> captureDeviceUID; for (UInt32 i = 0; i < captureDeviceID.size(); i++) { CFStringRef ref = GetDeviceName(captureDeviceID[i]); - if (ref == NULL) + if (ref == NULL) { return -1; + } captureDeviceUID.push_back(ref); // input sub-devices in this example, so append the sub-device's UID to the CFArray CFArrayAppendValue(subDevicesArray, ref); @@ -781,8 +808,9 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap vector<CFStringRef> playbackDeviceUID; for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { CFStringRef ref = GetDeviceName(playbackDeviceID[i]); - if (ref == NULL) + if (ref == NULL) { return -1; + } playbackDeviceUID.push_back(ref); // output sub-devices in this example, so append the sub-device's UID to the CFArray CFArrayAppendValue(subDevicesArray, ref); @@ -908,8 +936,9 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap CFRelease(aggDeviceDict); CFRelease(subDevicesArray); - if (subDevicesArrayClock) + if (subDevicesArrayClock) { CFRelease(subDevicesArrayClock); + } // release the device UID for (UInt32 i = 0; i < captureDeviceUID.size(); i++) { @@ -977,8 +1006,9 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, } } - if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) + if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) { return -1; + } } // Capture only @@ -1036,8 +1066,9 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, } } - if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) + if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) { return -1; + } } } @@ -1081,14 +1112,16 @@ int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchan if (inchannels > in_nChannels) { jack_error("This device hasn't required input channels inchannels = %d in_nChannels = %d", inchannels, in_nChannels); - if (strict) + if (strict) { return -1; + } } if (outchannels > out_nChannels) { jack_error("This device hasn't required output channels outchannels = %d out_nChannels = %d", outchannels, out_nChannels); - if (strict) + if (strict) { return -1; + } } if (inchannels == -1) { @@ -1261,6 +1294,8 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, int outchannels, int in_nChannels, int out_nChannels, + const vector<int>& chan_in_list, + const vector<int>& chan_out_list, jack_nframes_t buffer_size, jack_nframes_t sample_rate) { @@ -1270,7 +1305,8 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, AudioDeviceID currAudioDeviceID; UInt32 size; - jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels); + jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d chan_in_list = %d chan_out_list = %d", + capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, chan_in_list.size(), chan_out_list.size()); if (inchannels == 0 && outchannels == 0) { jack_error("No input and output channels..."); @@ -1363,34 +1399,69 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, } } - // Setup channel map - if (capturing && inchannels > 0 && inchannels < in_nChannels) { + // Setup input channel map + if (capturing && inchannels > 0 && inchannels <= in_nChannels) { SInt32 chanArr[in_nChannels]; for (int i = 0; i < in_nChannels; i++) { chanArr[i] = -1; } - for (int i = 0; i < inchannels; i++) { - chanArr[i] = i; + // Explicit mapping + if (chan_in_list.size() > 0) { + for (uint i = 0; i < chan_in_list.size(); i++) { + int chan = chan_in_list[i]; + if (chan < out_nChannels) { + // The wanted JACK input index for the 'chan' channel value + chanArr[chan] = i; + jack_info("Input channel = %d ==> JACK input port = %d", chan, i); + } else { + jack_info("Error input channel number is incorrect : %d", chan); + goto error; + } + } + } else { + for (int i = 0; i < inchannels; i++) { + chanArr[i] = i; + jack_info("Input channel = %d ==> JACK input port = %d", chanArr[i], i); + } } + AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels); if (err1 != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1"); + jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input"); printError(err1); goto error; } } - if (playing && outchannels > 0 && outchannels < out_nChannels) { + // Setup output channel map + if (playing && outchannels > 0 && outchannels <= out_nChannels) { SInt32 chanArr[out_nChannels]; for (int i = 0; i < out_nChannels; i++) { chanArr[i] = -1; } - for (int i = 0; i < outchannels; i++) { - chanArr[i] = i; + // Explicit mapping + if (chan_out_list.size() > 0) { + for (uint i = 0; i < chan_out_list.size(); i++) { + int chan = chan_out_list[i]; + if (chan < out_nChannels) { + // The wanted JACK output index for the 'chan' channel value + chanArr[chan] = i; + jack_info("JACK output port = %d ==> output channel = %d", i, chan); + } else { + jack_info("Error output channel number is incorrect : %d", chan); + goto error; + } + } + } else { + for (int i = 0; i < outchannels; i++) { + chanArr[i] = i; + jack_info("JACK output port = %d ==> output channel = %d", i, chanArr[i]); + } } + err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels); if (err1 != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0"); + jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output"); printError(err1); goto error; } @@ -1588,6 +1659,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, bool playing, int inchannels, int outchannels, + const char* chan_in_list, + const char* chan_out_list, bool monitor, const char* capture_driver_uid, const char* playback_driver_uid, @@ -1618,6 +1691,21 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, Gestalt(gestaltSystemVersionMajor, &major); Gestalt(gestaltSystemVersionMinor, &minor); + vector<int> parsed_chan_in_list; + vector<int> parsed_chan_out_list; + + ParseChannelList(chan_in_list, parsed_chan_in_list); + if (parsed_chan_in_list.size() > 0) { + jack_info("Explicit input channel list size = %d", parsed_chan_in_list.size()); + inchannels = parsed_chan_in_list.size(); + } + + ParseChannelList(chan_out_list, parsed_chan_out_list); + if (parsed_chan_out_list.size() > 0) { + jack_info("Explicit output channel list size = %d", parsed_chan_out_list.size()); + outchannels = parsed_chan_out_list.size(); + } + // Starting with 10.6 systems, the HAL notification thread is created internally if (major == 10 && minor >= 6) { CFRunLoopRef theRunLoop = NULL; @@ -1629,31 +1717,47 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, } } - if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate) < 0) + if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate) < 0) { goto error; + } // Generic JackAudioDriver Open - if (JackAudioDriver::Open(buffer_size, sample_rate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) + if (JackAudioDriver::Open(buffer_size, sample_rate, + capturing, playing, + inchannels, outchannels, + monitor, + capture_driver_name, + playback_driver_name, + capture_latency, + playback_latency) != 0) { goto error; + } - if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0) + if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0) { goto error; + } - if (SetupBufferSize(buffer_size) < 0) + if (SetupBufferSize(buffer_size) < 0) { goto error; + } - if (SetupSampleRate(sample_rate) < 0) + if (SetupSampleRate(sample_rate) < 0) { goto error; + } - if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, sample_rate) < 0) + if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) { goto error; + } - if (capturing && inchannels > 0) - if (SetupBuffers(inchannels) < 0) + if (capturing && inchannels > 0) { + if (SetupBuffers(inchannels) < 0) { goto error; + } + } - if (AddListeners() < 0) + if (AddListeners() < 0) { goto error; + } // Core driver may have changed the in/out values fCaptureChannels = inchannels; @@ -1692,11 +1796,13 @@ void JackCoreAudioDriver::UpdateLatencies() UInt32 value1 = 0; UInt32 value2 = 0; err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1); - if (err != noErr) + if (err != noErr) { jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); + } err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2); - if (err != noErr) + if (err != noErr) { jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); + } range.min = range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency; fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range); @@ -1707,11 +1813,13 @@ void JackCoreAudioDriver::UpdateLatencies() UInt32 value1 = 0; UInt32 value2 = 0; err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1); - if (err != noErr) + if (err != noErr) { jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); + } err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2); - if (err != noErr) + if (err != noErr) { jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); + } // Add more latency if "async" mode is used... range.min = range.max @@ -1742,12 +1850,14 @@ int JackCoreAudioDriver::Attach() for (int i = 0; i < fCaptureChannels; i++) { err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable); - if (err != noErr) + if (err != noErr) { jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error"); + } if (err == noErr && size > 0) { err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name); - if (err != noErr) + if (err != noErr) { jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error"); + } snprintf(alias, sizeof(alias) - 1, "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1); } else { snprintf(alias, sizeof(alias) - 1, "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1); @@ -1768,12 +1878,14 @@ int JackCoreAudioDriver::Attach() for (int i = 0; i < fPlaybackChannels; i++) { err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable); - if (err != noErr) + if (err != noErr) { jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error"); + } if (err == noErr && size > 0) { err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name); - if (err != noErr) + if (err != noErr) { jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error"); + } snprintf(alias, sizeof(alias) - 1, "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1); } else { snprintf(alias, sizeof(alias) - 1, "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1); @@ -1854,8 +1966,9 @@ int JackCoreAudioDriver::Stop() int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size) { - if (SetupBufferSize(buffer_size) < 0) + if (SetupBufferSize(buffer_size) < 0) { return -1; + } JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails @@ -1950,8 +2063,12 @@ extern "C" value.i = -1; jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of channels", "Maximum number of channels. If -1, max possible number of channels will be used"); - jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used"); - jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used"); + jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used"); + jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used"); + + value.str[0] = 0; + jack_driver_descriptor_add_parameter(desc, &filler, "input-list", 'n', JackDriverParamString, &value, NULL, "Input channel list", "List of input channel number to be opened"); + jack_driver_descriptor_add_parameter(desc, &filler, "output-list", 'N', JackDriverParamString, &value, NULL, "Output channel list", "List of output channel number to be opened"); value.str[0] = 0; jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL); @@ -1966,7 +2083,7 @@ extern "C" value.ui = 44100U; jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); - value.ui = 128U; + value.ui = 256U; jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL); value.str[0] = 0; @@ -1997,11 +2114,13 @@ extern "C" 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; + jack_nframes_t frames_per_interrupt = 256; bool capture = false; bool playback = false; int chan_in = -1; // Default: if not explicitely set, then max possible will be used... int chan_out = -1; // Default: if not explicitely set, then max possible will be used... + const char* chan_in_list = ""; + const char* chan_out_list = ""; bool monitor = false; const char* capture_driver_uid = ""; const char* playback_driver_uid = ""; @@ -2030,15 +2149,23 @@ extern "C" break; case 'c': - chan_in = chan_out = (int)param->value.ui; + chan_in = chan_out = param->value.i; break; case 'i': - chan_in = (int)param->value.ui; + chan_in = param->value.i; break; case 'o': - chan_out = (int)param->value.ui; + chan_out = param->value.i; + break; + + case 'n': + chan_in_list = param->value.str; + break; + + case 'N': + chan_out_list = param->value.str; break; case 'C': @@ -2103,9 +2230,27 @@ extern "C" playback = true; } + if (strcmp(chan_in_list, "") != 0 && chan_in >= 0) { + printf("Input channel list and in channels are both specified, input channel list will take over...\n"); + } + + if (strcmp(chan_out_list, "") != 0 && chan_out >= 0) { + printf("Output channel list and out channels are both specified, output channel list will take over...\n"); + } + 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, - playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain, hogged, clock_drift) == 0) { + if (driver->Open(frames_per_interrupt, + srate, capture, + playback, chan_in, + chan_out, chan_in_list, + chan_out_list, 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 { delete driver; diff --git a/macosx/coreaudio/JackCoreAudioDriver.h b/macosx/coreaudio/JackCoreAudioDriver.h index 8f50d597..71b27a6e 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.h +++ b/macosx/coreaudio/JackCoreAudioDriver.h @@ -141,6 +141,8 @@ class JackCoreAudioDriver : public JackAudioDriver int outchannels, int in_nChannels, int out_nChannels, + const vector<int>& chan_in_list, + const vector<int>& chan_out_list, jack_nframes_t nframes, jack_nframes_t samplerate); void CloseAUHAL(); @@ -162,8 +164,10 @@ class JackCoreAudioDriver : public JackAudioDriver jack_nframes_t samplerate, bool capturing, bool playing, - int chan_in, - int chan_out, + int inchannels, + int outchannels, + const char* chan_in_list, + const char* chan_out_list, bool monitor, const char* capture_driver_name, const char* playback_driver_name, diff --git a/macosx/iphone/freeverb.mm b/macosx/iphone/freeverb.mm index 3daabc9a..1d1517d7 100644 --- a/macosx/iphone/freeverb.mm +++ b/macosx/iphone/freeverb.mm @@ -25,7 +25,7 @@ #include <pwd.h> #include <sys/types.h> #include <assert.h> -#include <pthread.h> +#include <pthread.h> #include <sys/wait.h> #include <libgen.h> #include <jack/net.h> @@ -52,7 +52,7 @@ using namespace std; #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000) #endif #else - #define AVOIDDENORMALS + #define AVOIDDENORMALS #endif //#define BENCHMARKMODE @@ -61,7 +61,7 @@ struct Meta : map<const char*, const char*> { void declare (const char* key, const char* value) { (*this)[key]=value; } }; - + #define max(x,y) (((x)>(y)) ? (x) : (y)) #define min(x,y) (((x)<(y)) ? (x) : (y)) @@ -91,37 +91,37 @@ class UI { bool fStopped; public: - + UI() : fStopped(false) {} virtual ~UI() {} - + // -- active widgets - + virtual void addButton(const char* label, float* zone) = 0; virtual void addToggleButton(const char* label, float* zone) = 0; virtual void addCheckButton(const char* label, float* zone) = 0; virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0; virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0; virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0; - + // -- passive widgets - + virtual void addNumDisplay(const char* label, float* zone, int precision) = 0; virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) = 0; virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0; virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0; - + // -- frames and labels - + virtual void openFrameBox(const char* label) = 0; virtual void openTabBox(const char* label) = 0; virtual void openHorizontalBox(const char* label) = 0; virtual void openVerticalBox(const char* label) = 0; virtual void closeBox() = 0; - + virtual void show() = 0; virtual void run() = 0; - + void stop() { fStopped = true; } bool stopped() { return fStopped; } @@ -132,24 +132,24 @@ struct param { float* fZone; float fMin; float fMax; param(float* z, float a, float b) : fZone(z), fMin(a), fMax(b) {} }; - + class CMDUI : public UI { int fArgc; char** fArgv; stack<string> fPrefix; map<string, param> fKeyParam; - + void addOption(const char* label, float* zone, float min, float max) { string fullname = fPrefix.top() + label; fKeyParam.insert(make_pair(fullname, param(zone, min, max))); } - + void openAnyBox(const char* label) { string prefix; - + if (label && label[0]) { prefix = fPrefix.top() + "-" + label; } else { @@ -157,21 +157,21 @@ class CMDUI : public UI } fPrefix.push(prefix); } - + public: - + CMDUI(int argc, char *argv[]) : UI(), fArgc(argc), fArgv(argv) { fPrefix.push("--"); } virtual ~CMDUI() {} - + virtual void addButton(const char* label, float* zone) {}; virtual void addToggleButton(const char* label, float* zone) {}; virtual void addCheckButton(const char* label, float* zone) {}; - + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) { addOption(label,zone,min,max); } - + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) { addOption(label,zone,min,max); @@ -181,9 +181,9 @@ public: { addOption(label,zone,min,max); } - + // -- passive widgets - + virtual void addNumDisplay(const char* label, float* zone, int precision) {} virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) {} virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) {} @@ -193,11 +193,11 @@ public: virtual void openTabBox(const char* label) { openAnyBox(label); } virtual void openHorizontalBox(const char* label) { openAnyBox(label); } virtual void openVerticalBox(const char* label) { openAnyBox(label); } - + virtual void closeBox() { fPrefix.pop(); } - + virtual void show() {} - virtual void run() + virtual void run() { char c; printf("Type 'q' to quit\n"); @@ -205,8 +205,8 @@ public: sleep(1); } } - - void print() + + void print() { map<string, param>::iterator i; cout << fArgc << "\n"; @@ -215,13 +215,13 @@ public: cout << "[ " << i->first << " " << i->second.fMin << ".." << i->second.fMax <<" ] "; } } - + void process_command() { map<string, param>::iterator p; for (int i = 1; i < fArgc; i++) { if (fArgv[i][0] == '-') { - p = fKeyParam.find(fArgv[i]); + p = fKeyParam.find(fArgv[i]); if (p == fKeyParam.end()) { cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n"; print(); @@ -233,13 +233,13 @@ public: } } } - + void process_init() { map<string, param>::iterator p; for (int i = 1; i < fArgc; i++) { if (fArgv[i][0] == '-') { - p = fKeyParam.find(fArgv[i]); + p = fKeyParam.find(fArgv[i]); if (p == fKeyParam.end()) { cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n"; exit(1); @@ -256,14 +256,14 @@ public: //---------------------------------------------------------------- // Signal processor definition //---------------------------------------------------------------- - + class dsp { protected: int fSamplingFreq; public: dsp() {} virtual ~dsp() {} - + virtual int getNumInputs() = 0; virtual int getNumOutputs() = 0; virtual void buildUserInterface(UI* interface) = 0; @@ -271,12 +271,12 @@ class dsp { virtual void compute(int len, float** inputs, float** outputs) = 0; virtual void conclude() {} }; - + //---------------------------------------------------------------------------- // FAUST generated code //---------------------------------------------------------------------------- - + class mydsp : public dsp { private: @@ -349,7 +349,7 @@ class mydsp : public dsp { float fVec23[256]; float fRec24[2]; public: - static void metadata(Meta* m) { + static void metadata(Meta* m) { m->declare("name", "freeverb"); m->declare("version", "1.0"); m->declare("author", "Grame"); @@ -580,8 +580,8 @@ class mydsp : public dsp { }; - - + + mydsp DSP; @@ -601,7 +601,7 @@ int gNumInChans; int gNumOutChans; //---------------------------------------------------------------------------- -// Jack Callbacks +// Jack Callbacks //---------------------------------------------------------------------------- static void net_shutdown(void *) @@ -633,7 +633,7 @@ void printstats() low = hi = tot = (stops[KSKIP] - starts[KSKIP]); if (mesure < KMESURE) { - + for (int i = KSKIP+1; i<mesure; i++) { unsigned long long int m = stops[i] - starts[i]; if (m<low) low = m; @@ -643,7 +643,7 @@ void printstats() cout << low << ' ' << tot/(mesure-KSKIP) << ' ' << hi << endl; } else { - + for (int i = KSKIP+1; i<KMESURE; i++) { unsigned long long int m = stops[i] - starts[i]; if (m<low) low = m; @@ -652,7 +652,7 @@ void printstats() } cout << low << ' ' << tot/(KMESURE-KSKIP) << ' ' << hi << endl; - } + } } #else @@ -663,20 +663,20 @@ void printstats() #endif static int net_process(jack_nframes_t buffer_size, - int audio_input, - float** audio_input_buffer, + int audio_input, + float** audio_input_buffer, int midi_input, void** midi_input_buffer, int audio_output, - float** audio_output_buffer, - int midi_output, - void** midi_output_buffer, + float** audio_output_buffer, + int midi_output, + void** midi_output_buffer, void* data) { AVOIDDENORMALS; STARTMESURE DSP.compute(buffer_size, audio_input_buffer, audio_output_buffer); - STOPMESURE + STOPMESURE return 0; } @@ -687,68 +687,68 @@ static int net_process(jack_nframes_t buffer_size, ******************************************************************************* *******************************************************************************/ - + //------------------------------------------------------------------------- // MAIN //------------------------------------------------------------------------- #define TEST_MASTER "194.5.49.5" - + int main(int argc, char *argv[]) { - + UI* interface = new CMDUI(argc, argv); jack_net_slave_t* net; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - + //Jack::JackAudioQueueAdapter audio(2, 2, 1024, 44100, NULL); - + gNumInChans = DSP.getNumInputs(); gNumOutChans = DSP.getNumOutputs(); - - jack_slave_t request = { gNumInChans, gNumOutChans, 0, 0, DEFAULT_MTU, -1, JackSlowMode }; + + jack_slave_t request = { gNumInChans, gNumOutChans, 0, 0, DEFAULT_MTU, -1, 2 }; jack_master_t result; - + printf("Network\n"); - + //if (audio.Open() < 0) { // fprintf(stderr, "Cannot open audio\n"); // return 1; //} - + //audio.Start(); - + // Hang around forever... //while(1) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); - + if ((net = jack_net_slave_open(TEST_MASTER, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { fprintf(stderr, "jack remote server not running ?\n"); return 1; } - + jack_set_net_slave_process_callback(net, net_process, NULL); - + // We want to restart (that is "wait for available master" again) //jack_set_net_shutdown_callback(net, net_shutdown, 0); - + DSP.init(result.sample_rate); DSP.buildUserInterface(interface); - + if (jack_net_slave_activate(net) != 0) { fprintf(stderr, "cannot activate net"); return 1; } - + int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; - + // Wait for application end jack_net_slave_deactivate(net); jack_net_slave_close(net); - + //if (audio.Close() < 0) { // fprintf(stderr, "Cannot close audio\n"); //} - + return retVal; } diff --git a/macosx/iphone/main_master.mm b/macosx/iphone/main_master.mm index 7ec618b3..ae71f227 100644 --- a/macosx/iphone/main_master.mm +++ b/macosx/iphone/main_master.mm @@ -24,7 +24,7 @@ int buffer_size = 1024; int sample_rate = 22050; //int sample_rate = 32000; -jack_master_t request = { buffer_size, sample_rate, "master" }; +jack_master_t request = { -1, -1, -1, -1, buffer_size, sample_rate, "master" }; jack_slave_t result; static void MixAudio(float** dst, float** src1, float** src2, int channels, int buffer_size) @@ -38,33 +38,33 @@ static void MixAudio(float** dst, float** src1, float** src2, int channels, int static void MasterAudioCallback(int frames, float** inputs, float** outputs, void* arg) { - int i; - + int i; + // Copy from iPod input to network buffers for (i = 0; i < result.audio_input; i++) { memcpy(audio_input_buffer[i], inputs[i], buffer_size * sizeof(float)); } - + /* // Copy from network out buffers to network in buffers (audio thru) for (i = 0; i < result.audio_input; i++) { memcpy(audio_input_buffer[i], audio_output_buffer[i], buffer_size * sizeof(float)); } */ - + // Mix iPod input and network in buffers to network out buffers //MixAudio(audio_input_buffer, inputs, audio_output_buffer, result.audio_input, buffer_size); - + // Send network buffers if (jack_net_master_send(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) { printf("jack_net_master_send error..\n"); } - + // Recv network buffers if (jack_net_master_recv(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { printf("jack_net_master_recv error..\n"); } - + // Copy from network buffers to iPod output for (i = 0; i < result.audio_output; i++) { memcpy(outputs[i], audio_output_buffer[i], buffer_size * sizeof(float)); @@ -72,17 +72,17 @@ static void MasterAudioCallback(int frames, float** inputs, float** outputs, voi } int main(int argc, char *argv[]) { - + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int i; - + if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { printf("jack_net_master_open error..\n"); return -1; } - + TiPhoneCoreAudioRenderer audio_device(result.audio_input, result.audio_output); - + // Allocate buffers if (result.audio_input > 0) { audio_input_buffer = (float**)calloc(result.audio_input, sizeof(float*)); @@ -90,66 +90,66 @@ int main(int argc, char *argv[]) { audio_input_buffer[i] = (float*)(calloc(buffer_size, sizeof(float))); } } - + if (result.audio_output > 0) { audio_output_buffer = (float**)calloc(result.audio_output, sizeof(float*)); for (i = 0; i < result.audio_output; i++) { audio_output_buffer[i] = (float*)(calloc(buffer_size, sizeof(float))); } } - + if (audio_device.Open(buffer_size, sample_rate) < 0) { return -1; } - + audio_device.SetAudioCallback(MasterAudioCallback, NULL); - + if (audio_device.Start() < 0) { return -1; } - + /* // Quite brutal way, the application actually does not start completely, the netjack audio processing loop is used instead... - // Run until interrupted - + // Run until interrupted + int wait_usec = (unsigned long)((((float)buffer_size) / ((float)sample_rate)) * 1000000.0f); - + while (1) { - + // Copy input to output for (i = 0; i < result.audio_input; i++) { memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); } - + if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { printf("jack_net_master_send error..\n"); } - + if (jack_net_master_recv(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) { printf("jack_net_master_recv error..\n"); } usleep(wait_usec); }; */ - + int retVal = UIApplicationMain(argc, argv, nil, nil); - + audio_device.Stop(); audio_device.Close(); - + // Wait for application end jack_net_master_close(net); - + for (i = 0; i < result.audio_input; i++) { free(audio_input_buffer[i]); } free(audio_input_buffer); - + for (i = 0; i < result.audio_output; i++) { free(audio_output_buffer[i]); } free(audio_output_buffer); - + [pool release]; return retVal; } diff --git a/macosx/iphone/main_slave.mm b/macosx/iphone/main_slave.mm index b4ef278b..b9875c32 100644 --- a/macosx/iphone/main_slave.mm +++ b/macosx/iphone/main_slave.mm @@ -21,18 +21,18 @@ int buffer_size; int sample_rate; static int net_process(jack_nframes_t buffer_size, - int audio_input, - float** audio_input_buffer, + int audio_input, + float** audio_input_buffer, int midi_input, void** midi_input_buffer, int audio_output, - float** audio_output_buffer, - int midi_output, - void** midi_output_buffer, + float** audio_output_buffer, + int midi_output, + void** midi_output_buffer, void* data) { jack_adapter_pull_and_push(adapter, audio_output_buffer, audio_input_buffer, buffer_size); - + // Process input, produce output if (audio_input == audio_output) { // Copy net input to net output @@ -59,52 +59,53 @@ static void SlaveAudioCallback(int frames, float** inputs, float** outputs, void #define WIFI_MTU 1500 int main(int argc, char *argv[]) { - + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - jack_slave_t request = { NUM_OUTPUT, NUM_INPUT, 0, 0, WIFI_MTU, -1, JackCeltEncoder, 128, JackSlowMode }; + + jack_slave_t request = { NUM_OUTPUT, NUM_INPUT, 0, 0, WIFI_MTU, -1, JackCeltEncoder, 128, 2 }; jack_master_t result; //if ((net = jack_net_slave_open("169.254.112.119", DEFAULT_PORT, "iPhone", &request, &result)) == 0) { if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPod", &request, &result)) == 0) { - printf("jack_net_slave_open error..\n"); + printf("jack_net_slave_open error...\n"); return -1; } - - if ((adapter = jack_create_adapter(NUM_INPUT, - NUM_OUTPUT, - result.buffer_size, - result.sample_rate, - result.buffer_size, + + if ((adapter = jack_create_adapter(NUM_INPUT, + NUM_OUTPUT, + result.buffer_size, + result.sample_rate, + result.buffer_size, result.sample_rate)) == 0) { return -1; } - + TiPhoneCoreAudioRenderer audio_device(NUM_INPUT, NUM_OUTPUT); - + jack_set_net_slave_process_callback(net, net_process, NULL); jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL); - + if (jack_net_slave_activate(net) != 0) { + printf("Cannot activate slave client\n"); return -1; } - + if (audio_device.Open(result.buffer_size, result.sample_rate) < 0) { return -1; } - + audio_device.SetAudioCallback(SlaveAudioCallback, NULL); - + if (audio_device.Start() < 0) { return -1; } - + int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; - + audio_device.Stop(); audio_device.Close(); - + // Wait for application end jack_net_slave_deactivate(net); jack_net_slave_close(net); diff --git a/man/jack_connect.0 b/man/jack_connect.0 index 602ac39b..5ee8f8b5 100644 --- a/man/jack_connect.0 +++ b/man/jack_connect.0 @@ -5,7 +5,7 @@ \fB jack_connect\fR [ \fI-s\fR | \fI--server servername\fR ] [\fI-h\fR | \fI--help\fR ] port1 port2 \fB jack_disconnect\fR [ \fI-s\fR | \fI--server servername\fR ] [\fI-h\fR | \fI--help\fR ] port1 port2 .SH DESCRIPTION -\fBjack_connect\fR connects the two named ports. \fBjack_connect\fR disconnects the two named ports. +\fBjack_connect\fR connects the two named ports. \fBjack_disconnect\fR disconnects the two named ports. .SH RETURNS The exit status is zero if successful, 1 otherwise diff --git a/posix/JackPosixSemaphore.cpp b/posix/JackPosixSemaphore.cpp index 0be9fdb5..91e9d601 100644 --- a/posix/JackPosixSemaphore.cpp +++ b/posix/JackPosixSemaphore.cpp @@ -187,7 +187,7 @@ bool JackPosixSemaphore::ConnectOutput(const char* name, const char* server_name bool JackPosixSemaphore::Disconnect() { if (fSemaphore) { - jack_log("JackPosixSemaphore::Disconnect name = %s", fName); + jack_log("JackPosixSemaphore::Disconnect name = %s", fName); if (sem_close(fSemaphore) != 0) { jack_error("Disconnect: can't disconnect named semaphore name = %s err = %s", fName, strerror(errno)); return false; diff --git a/posix/JackSocket.cpp b/posix/JackSocket.cpp index 6d7d6879..2157a455 100644 --- a/posix/JackSocket.cpp +++ b/posix/JackSocket.cpp @@ -188,6 +188,7 @@ int JackClientSocket::Read(void* data, int len) jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno)); return 0; } else { + jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno)); return -1; } } else { @@ -232,6 +233,7 @@ int JackClientSocket::Write(void* data, int len) jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno)); return 0; } else { + jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno)); return -1; } } else { diff --git a/posix/JackSocketClientChannel.cpp b/posix/JackSocketClientChannel.cpp index 23d62e98..f40ae39a 100644 --- a/posix/JackSocketClientChannel.cpp +++ b/posix/JackSocketClientChannel.cpp @@ -62,13 +62,14 @@ int JackSocketClientChannel::Open(const char* server_name, const char* name, int } // Check name in server - ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); + ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true); if (result < 0) { int status1 = *status; - if (status1 & JackVersionError) + if (status1 & JackVersionError) { jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION); - else + } else { jack_error("Client name = %s conflits with another running client", name); + } goto error; } @@ -141,9 +142,9 @@ void JackSocketClientChannel::ServerAsyncCall(JackRequest* req, JackResult* res, } } -void JackSocketClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) +void JackSocketClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) { - JackClientCheckRequest req(name, protocol, options, uuid); + JackClientCheckRequest req(name, protocol, options, uuid, open); JackClientCheckResult res; ServerSyncCall(&req, &res, result); *status = res.fStatus; diff --git a/posix/JackSocketClientChannel.h b/posix/JackSocketClientChannel.h index 8e2b0e30..50da7de7 100644 --- a/posix/JackSocketClientChannel.h +++ b/posix/JackSocketClientChannel.h @@ -60,7 +60,7 @@ class JackSocketClientChannel : public detail::JackClientChannelInterface, publi int ServerCheck(const char* server_name); - void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result); + void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open); void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result); void ClientOpen(const char* name, int* ref, int uuid, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, int* result) {} diff --git a/posix/JackSocketServerChannel.cpp b/posix/JackSocketServerChannel.cpp index caaac23c..73a16b16 100644 --- a/posix/JackSocketServerChannel.cpp +++ b/posix/JackSocketServerChannel.cpp @@ -164,7 +164,7 @@ bool JackSocketServerChannel::HandleRequest(int fd) JackRequest header; if (header.Read(socket) < 0) { jack_log("HandleRequest: cannot read header"); - ClientKill(fd); // TO CHECK SOLARIS + ClientKill(fd); return false; } @@ -185,6 +185,9 @@ bool JackSocketServerChannel::HandleRequest(int fd) res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus); if (res.Write(socket) < 0) jack_error("JackRequest::ClientCheck write error name = %s", req.fName); + // Atomic ClientCheck followed by ClientOpen on same socket + if (req.fOpen) + HandleRequest(fd); break; } diff --git a/windows/JackWinNamedPipeClientChannel.cpp b/windows/JackWinNamedPipeClientChannel.cpp index e866e80d..9bf5d0b9 100644 --- a/windows/JackWinNamedPipeClientChannel.cpp +++ b/windows/JackWinNamedPipeClientChannel.cpp @@ -55,10 +55,10 @@ int JackWinNamedPipeClientChannel::Open(const char* server_name, const char* nam /* 16/08/07: was called before doing "fRequestPipe.Connect" .... still necessary? - if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) { - jack_error("Cannot bind pipe"); - goto error; - } + if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) { + jack_error("Cannot bind pipe"); + goto error; + } */ if (fRequestPipe.Connect(jack_server_dir, server_name, 0) < 0) { @@ -67,10 +67,14 @@ int JackWinNamedPipeClientChannel::Open(const char* server_name, const char* nam } // Check name in server - ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); + ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true); if (result < 0) { - jack_error("Client name = %s conflits with another running client", name); - goto error; + int status1 = *status; + if (status1 & JackVersionError) { + jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION); + } else { + jack_error("Client name = %s conflits with another running client", name); + } } if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) { @@ -142,9 +146,9 @@ void JackWinNamedPipeClientChannel::ServerAsyncCall(JackRequest* req, JackResult } } -void JackWinNamedPipeClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) +void JackWinNamedPipeClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) { - JackClientCheckRequest req(name, protocol, options, uuid); + JackClientCheckRequest req(name, protocol, options, uuid, open); JackClientCheckResult res; ServerSyncCall(&req, &res, result); *status = res.fStatus; diff --git a/windows/JackWinNamedPipeClientChannel.h b/windows/JackWinNamedPipeClientChannel.h index 479e3271..7b84eba8 100644 --- a/windows/JackWinNamedPipeClientChannel.h +++ b/windows/JackWinNamedPipeClientChannel.h @@ -59,7 +59,7 @@ class JackWinNamedPipeClientChannel : public detail::JackClientChannelInterface, int ServerCheck(const char* server_name); - void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result); + void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open); void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result); void ClientOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, int* result) {} diff --git a/windows/JackWinNamedPipeServerChannel.cpp b/windows/JackWinNamedPipeServerChannel.cpp index a60c826a..b557a33c 100644 --- a/windows/JackWinNamedPipeServerChannel.cpp +++ b/windows/JackWinNamedPipeServerChannel.cpp @@ -117,6 +117,9 @@ bool JackClientPipeThread::HandleRequest() if (req.Read(fPipe) == 0) res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus); res.Write(fPipe); + // Atomic ClientCheck followed by ClientOpen on same pipe + if (req.fOpen) + HandleRequest(); break; } @@ -477,11 +480,11 @@ int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* ser void JackWinNamedPipeServerChannel::Close() { /* TODO : solve WIN32 thread Kill issue - This would hang the server... since we are quitting it, its not really problematic, - all ressources will be deallocated at the end. + This would hang the server... since we are quitting it, its not really problematic, + all ressources will be deallocated at the end. - fRequestListenPipe.Close(); - fThread.Stop(); + fRequestListenPipe.Close(); + fThread.Stop(); */ fThread.Kill(); diff --git a/windows/libjackserver.cbp b/windows/libjackserver.cbp index d2f9b490..17f64965 100644 --- a/windows/libjackserver.cbp +++ b/windows/libjackserver.cbp @@ -241,6 +241,7 @@ <Unit filename="..\common\JackActivationCount.cpp" /> <Unit filename="..\common\JackArgParser.cpp" /> <Unit filename="..\common\JackAudioDriver.cpp" /> + <Unit filename="..\common\JackTimedDriver.cpp" /> <Unit filename="..\common\JackAudioPort.cpp" /> <Unit filename="..\common\JackClient.cpp" /> <Unit filename="..\common\JackConnectionManager.cpp" /> |