@@ -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. | |||
@@ -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__ | |||
@@ -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 | |||
@@ -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) | |||
{ | |||
@@ -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(); | |||
@@ -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) | |||
{} | |||
@@ -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) { | |||
@@ -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); | |||
@@ -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); | |||
@@ -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: | |||
@@ -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; | |||
@@ -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(); | |||
@@ -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, | |||
@@ -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; | |||
@@ -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 | |||
@@ -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]); | |||
} | |||
@@ -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; | |||
@@ -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: | |||
@@ -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 | |||
@@ -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; | |||
} | |||
@@ -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); | |||
} | |||
@@ -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, ...); | |||
@@ -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; | |||
} | |||
@@ -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: | |||
@@ -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 | |||
@@ -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; | |||
} | |||
@@ -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(); | |||
@@ -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(); | |||
@@ -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) | |||
@@ -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; | |||
} | |||
} | |||
@@ -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 { | |||
@@ -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(); | |||
@@ -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 |
@@ -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 |
@@ -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(); | |||
}; | |||
} | |||
@@ -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, | |||
@@ -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; | |||
} | |||
@@ -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; | |||
@@ -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 | |||
@@ -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; | |||
@@ -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)); | |||
} | |||
}; | |||
@@ -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" | |||
@@ -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) | |||
@@ -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(); | |||
} | |||
@@ -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 |
@@ -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 | |||
@@ -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 |
@@ -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 |
@@ -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; | |||
} | |||
} | |||
}; | |||
/*! | |||
@@ -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 |
@@ -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() | |||
{} | |||
@@ -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(). */ | |||
@@ -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 | |||
@@ -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 | |||
@@ -114,6 +114,7 @@ def build(bld): | |||
serverlib.source = [] + common_libsources | |||
serverlib.source += [ | |||
'JackAudioDriver.cpp', | |||
'JackTimedDriver.cpp', | |||
'JackMidiDriver.cpp', | |||
'JackDriver.cpp', | |||
'JackEngine.cpp', | |||
@@ -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; | |||
} |
@@ -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 | |||
@@ -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); | |||
@@ -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; | |||
} | |||
@@ -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); | |||
@@ -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); | |||
@@ -85,9 +85,9 @@ main (int argc, char *argv[]) | |||
} else { | |||
fprintf (stdout, "%s unloaded.\n", client_name); | |||
} | |||
jack_client_close(client); | |||
return 0; | |||
} | |||
@@ -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); | |||
} | |||
@@ -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); | |||
@@ -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); | |||
} |
@@ -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); | |||
@@ -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; | |||
} | |||
@@ -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; | |||
} | |||
@@ -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); | |||
} |
@@ -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 (); | |||
@@ -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; | |||
} | |||
@@ -143,7 +143,7 @@ static jack_time_t jack_get_mhz (void) | |||
exit(1); | |||
} | |||
for ( ; ; ) | |||
for (;;) | |||
{ | |||
jack_time_t mhz; | |||
int ret; | |||
@@ -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", | |||
@@ -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) | |||
@@ -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; | |||
@@ -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, | |||
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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); | |||
@@ -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 | |||
@@ -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; | |||
@@ -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 { | |||
@@ -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; | |||
@@ -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) | |||
{} | |||
@@ -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; | |||
} | |||
@@ -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; | |||
@@ -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) | |||
{} | |||
@@ -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(); | |||
@@ -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" /> | |||