| @@ -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" /> | |||