Conflicts: common/JackControlAPI.cpptags/v1.9.10
@@ -31,11 +31,97 @@ David Garcia Garzon | |||
Valerio Pilo | |||
Chris Caudle | |||
John Emmas | |||
Robin Gareus | |||
--------------------------- | |||
Jackdmp changes log | |||
--------------------------- | |||
2012-11-21 Stephane Letz <letz@grame.fr> | |||
* Correct JackPortAudioDriver::Open : special case for ASIO drivers. | |||
2012-10-20 Stephane Letz <letz@grame.fr> | |||
* Correct JackEngine::NotifyGraphReorder : graph-order callback now notified after port latencies update. | |||
2012-09-22 Robin Gareus <robin@gareus.org> | |||
* netjack/opus: don't re-init en/decoders. | |||
2012-09-18 Nedko Arnaudov <nedko@arnaudov.name> | |||
* Use string ids in the alsa device list. | |||
2012-09-10 Nedko Arnaudov <nedko@arnaudov.name> | |||
* controlapi: fix double free on master switch. | |||
2012-09-10 Robin Gareus <robin@gareus.org> | |||
* netjack1/netone opus support. | |||
* netjack1/2 Opus: use only 2bytes for encoded-length. | |||
* wscript: add header defines and libs for example-clients/netsource. | |||
* fix duplicate prog.includes. | |||
2012-09-05 Stephane Letz <letz@grame.fr> | |||
* More robust channel mapping handling in JackCoreAudioDriver. | |||
2012-09-05 Robin Gareus <robin@gareus.org> | |||
* Add opus support to NetJack2. | |||
2012-08-21 Nedko Arnaudov <nedko@arnaudov.name> | |||
* jack_control: fix epr command. | |||
2012-08-21 Stephane Letz <letz@grame.fr> | |||
* Update JackCoreAudioDriver and JackCoreAudioAdapter with more recent API. | |||
2012-08-03 Stephane Letz <letz@grame.fr> | |||
* Change framework installation hierarchy for OSX Mountain Lion. | |||
2012-08-02 Stephane Letz <letz@grame.fr> | |||
* Devin Anderson patch for Jack/CoreMIDI duplicated messages. | |||
2012-07-24 Stephane Letz <letz@grame.fr> | |||
* Fix in ALSA adapter. | |||
2012-05-26 Nedko Arnaudov <nedko@arnaudov.name> | |||
* Fix alsa driver parameter order. | |||
* Control API: Enforce driver/internal parameter order. | |||
2012-05-24 Nedko Arnaudov <nedko@arnaudov.name> | |||
* Extend jack_control to have parameter reset commands. | |||
2012-03-24 Adrian Knoth <adi@drcomp.erfurt.thur.de> | |||
* Align buffers to 32 byte boundaries to allow AVX processing. | |||
2012-03-21 Stephane Letz <letz@grame.fr> | |||
* New jack_get_cycle_times() implementation from Fons Adriennsen. | |||
2012-03-17 Nedko Arnaudov <nedko@arnaudov.name> | |||
* Update waf. | |||
2012-03-17 Adrian Knoth <adi@drcomp.erfurt.thur.de> | |||
* [firewire] Introduce UpdateLatencies() in FFADO backend. | |||
* [firewire] Allow FFADO backend to change the buffer size. | |||
2012-03-16 Stephane Letz <letz@grame.fr> | |||
* Rework JackMessageBuffer. | |||
2012-03-15 Stephane Letz <letz@grame.fr> | |||
* POST_PACKED_STRUCTURE used for jack_latency_range_t type. | |||
@@ -81,7 +167,7 @@ John Emmas | |||
2012-01-20 Stephane Letz <letz@grame.fr> | |||
* Experimental system port alias use in WIndows JackRouter. | |||
* Experimental system port alias use in Windows JackRouter. | |||
2012-01-19 Stephane Letz <letz@grame.fr> | |||
@@ -214,6 +214,7 @@ Note : To experiment with the -S option, jackdmp must be launched in a console. | |||
1.9.6 : Improve JackCoreAudioDriver and JackCoreAudioAdapter : when no devices are described, takes default input and output and aggregate them.Correct JackGraphManager::DeactivatePort. Correct JackMachServerChannel::Execute : keep running even in error cases. Raise JACK_PROTOCOL_VERSION number. Arnold Krille firewire patch. Raise JACK_DRIVER_PARAM_STRING_MAX and JACK_PARAM_STRING_MAX to 127 otherwise some audio drivers cannot be loaded on OSX. Fix some file header to have library side code use LGPL. On Windows, now use TRE library for regexp (BSD license instead of GPL license). ffado-portname-sync.patch from ticket #163 applied. Remove call to exit in library code. Make jack_connect/jack_disconnect wait for effective port connection/disconnection. Add tests to validate intclient.h API. On Linux, inter-process synchronization primitive switched to POSIX semaphore. In JackCoreAudioDriver, move code called in MeasureCallback to be called once in IO thread. David Garcia Garzon netone patch. Fix from Fernando Lopez-Lezcano for compilation on fc13. Fix JackPosixSemaphore::TimedWait : same behavior as JackPosixSemaphore::Wait regarding EINTR. David Garcia Garzon unused_pkt_buf_field_jack2 netone patch. Arnold Krille firewire snooping patch. Jan Engelhardt patch for get_cycles on SPARC. Adrian Knoth hurd.patch, kfreebsd-fix.patch and alpha_ia64-sigsegv.patch from ticket 177. Adrian Knoth fix for linux cycle.h (ticket 188). In JackCoreAudioDriver, fix an issue when no value is given for input. | |||
1.9.7 : Sync JackAlsaDriver::alsa_driver_check_card_type with JACK1 backend. Correct JackServer::Open to avoid a race when control API is used on OSX. Improve backend error handling: fatal error returned by Read/Write now cause a Process failure (so a thread exit for blocking backends). Recoverable ones (XRuns..) are now treated internally in ALSA, FreeBob and FFADO backends. In jackdmp.cpp, jackctl_setup_signals moved before jackctl_server_start. Correct symbols export in backends on OSX. ALSA backend : suspend/resume handling. Correct dummy driver. Adrian Knoth jack_lsp patch. Remove JackPortIsActive flag. New latency API implementation. ComputeTotalLatencies now a client/server call. Add latent test client for latency API. Also print playback and capture latency in jack_lsp. jack_client_has_session_callback implementation. Check requested buffer size and limit to 1..8192 - avoids weird behaviour caused by jack_bufsize foobar. jack_port_type_get_buffer_size implementation. Stop using alloca and allocate buffer on the heap for alsa_io. Rename jdelay to jack_iodelay as per Fons' request. Call buffer size callback in activate (actually this is done on client side in the RT thread Init method). Add jack_midi_dump client. Synchronize net JACK1 with JACK1 version. Synchronize jack_connect/jack_disconnect with JACK1 version. Correct JackNetMaster::SetBufferSize. Use jack_default_audio_sample_t instead of float consistently, fix ticket #201. -X now allows to add several slave backends, add -I to load several internal clients. Rework internal slave driver management, JackServerGlobals now handle same parameters as jackdmp. Correct JackEngine::NotifyGraphReorder, update JackDebugClient with latest API. Devin Anderson server-ctl-proposal branch merged on trunk: improved control API, slave backend reworked. Implement renaming in JackDriver::Open to avoid name collision (thanks Devin Anderson). Correct alsa_driver_restart (thanks Devin Anderson). Correction of jack_connect/jack_disconnect: use of jack_activate and volatile keyword for thread shared variable. Correction of JackNetOneDriver for latest CELT API. Synchronize JackWeakAPI.cpp with new APIs. | |||
1.9.8 : Merge newer-midi branch (Devin Anderson redesign of the MIDI drivers: alsarawmidi, ffado, coremidi and winmme). Correction in jackdmp.cpp: notify_server_stop should be done after server destruction. Correct driver lifetime management. Add XRun detection in PortAudio driver. CELT code for NetJack2. Merge branch switch-master-port-registration-notifications: correct driver port registration. Libjacknet in progress. Correct MIDI in NetJack2. Correct OSX real-time thread setup. Correct rd_acquire in dbus code. Correct NetJack2 connection handling. SaveConnections/RestoreConnections in NetDriver and JackAudioDriver. Special version of jack_attach_shm/jack_release_shm on client side for POSIX shared memory, to solve a memory leak issue. Another round of code improvements to handle completely buggy Digidesign CoreAudio user-land driver. Special CATCH_CLOSE_EXCEPTION_RETURN to handle Close API calls. Add JACK_NETJACK_PORT and JACK_NETJACK_MULTICAST environment variables for NetJack2. NetJack2 now only send data on network only is ports are connected both sides. Fix for "starting two instances of same app in parallel does not work" bug. Enable explicit channel mapping in CoreAudio driver. New JackTimedDriver class to be used by JackDummyDriver, JackNetDriver and JackNetOneDriver classes. More robust code in synchronization primitives and in JackMessageBuffer. More robust Control API implementation. Add jackctl_driver_get_type in Control API. Singleton behaviour for JackCoreMidiDriver and JackWinMMEDriver. John Emmas patch for DSP CPU computation. John Emmas Windows server launching patch. Fix jack_set_port_name API. Enable local access in NetJack2 code. Dynamic port management in JACK/CoreMidi bridge. | |||
1.9.9 : Adrian Knoth fix in midiseq.c. Fix library symbols export issue. Cleanup drivers and internals loading code. jackctl_driver_params_parse API moved in public control.h. More general drivers/internals loading model on Windows. Factorize code the server/client request in JackRequestDecoder class. More robust server/client protocol. Implement shutdown for in server clients. Better time-out management in NetJack2. Experimental system port alias use in Windows JackRouter. Improve ShutDown in NetManager. Correct ShutDown in JackInternalClient and JackLibClient. Fix NetJack2 initialisation bug. Add EndTime function (especially for Windows). Rename JackProcessSync in JackPosixProcessSync. A bit more robust JackMessageBuffer implementation (in progress). Check server API callback from notification thread. Use a time-out in notification channel write function. Fix lock management in JackEngine. In control API, UNIX like sigset_t replaced by more abstract jackctl_sigmask_t * opaque struct. Improve libjacknet master mode. Remove JACK_32_64 flag, so POST_PACKED_STRUCTURE now always used. POST_PACKED_STRUCTURE used for jack_latency_range_t type. Rework JackMessageBuffer. [firewire] Introduce UpdateLatencies() in FFADO backend. [firewire] Allow FFADO backend to change the buffer size. Update waf. New jack_get_cycle_times() implementation from Fons Adriennsen. Align buffers to 32 byte boundaries to allow AVX processing. Extend jack_control to have parameter reset commands. Fix alsa driver parameter order. Control API: Enforce driver/internal parameter order. Fix in ALSA adapter. Devin Anderson patch for Jack/CoreMIDI duplicated messages. Change framework installation hierarchy for OSX Mountain Lion. Update JackCoreAudioDriver and JackCoreAudioAdapter with more recent API. jack_control: fix epr command. Add opus support to NetJack2. More robust channel mapping handling in JackCoreAudioDriver. netjack1/netone opus support. controlapi: fix double free on master switch. Use string ids in the alsa device list. netjack/opus: don't re-init en/decoders. Correct JackPortAudioDriver::Open : special case for ASIO drivers. | |||
This is a work in progress but the implementation is now stable enough to be tested. jackdmp has been used successfully with the following applications : Ardour, Hydrogen, Jamin, QjackCtl, Jack-Rack, SooperLooper, AlsaPlayer... | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
Copyright (C) 2008 Grame | |||
Copyright (C) 2008-2012 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 | |||
@@ -18,25 +18,31 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#include "JackAudioAdapter.h" | |||
#include "JackPlatformPlug.h" | |||
#include "JackArgParser.h" | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <assert.h> | |||
#ifdef __linux__ | |||
#include "JackAlsaAdapter.h" | |||
#endif | |||
#ifdef __APPLE__ | |||
#include "JackCoreAudioAdapter.h" | |||
#define JackPlatformAdapter JackCoreAudioAdapter | |||
#endif | |||
#ifdef WIN32 | |||
#include "JackPortAudioAdapter.h" | |||
#ifdef __linux__ | |||
#include "JackAlsaAdapter.h" | |||
#define JackPlatformAdapter JackAlsaAdapter | |||
#endif | |||
#if defined(__sun__) || defined(sun) | |||
#include "JackOSSAdapter.h" | |||
#define JackPlatformAdapter JackOSSAdapter | |||
#endif | |||
#ifdef WIN32 | |||
#include "JackPortAudioAdapter.h" | |||
#define JackPlatformAdapter JackPortAudioAdapter | |||
#endif | |||
#ifdef __cplusplus | |||
@@ -56,22 +62,7 @@ extern "C" | |||
try { | |||
#ifdef __linux__ | |||
adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackAlsaAdapter(buffer_size, sample_rate, params)); | |||
#endif | |||
#ifdef WIN32 | |||
adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackPortAudioAdapter(buffer_size, sample_rate, params)); | |||
#endif | |||
#ifdef __APPLE__ | |||
adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackCoreAudioAdapter(buffer_size, sample_rate, params)); | |||
#endif | |||
#if defined(__sun__) || defined(sun) | |||
adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackOSSAdapter(buffer_size, sample_rate, params)); | |||
#endif | |||
adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackPlatformAdapter(buffer_size, sample_rate, params)); | |||
assert(adapter); | |||
if (adapter->Open() == 0) { | |||
@@ -82,6 +73,7 @@ extern "C" | |||
} | |||
} catch (...) { | |||
jack_info("audioadapter allocation error"); | |||
return 1; | |||
} | |||
} | |||
@@ -24,7 +24,7 @@ | |||
#include "config.h" | |||
#endif | |||
#define VERSION "1.9.9" | |||
#define VERSION "1.9.9.5" | |||
#define BUFFER_SIZE_MAX 8192 | |||
@@ -113,7 +113,6 @@ struct jackctl_driver | |||
{ | |||
jack_driver_desc_t * desc_ptr; | |||
JSList * parameters; | |||
JSList * set_parameters; | |||
JSList * infos; | |||
}; | |||
@@ -121,7 +120,6 @@ struct jackctl_internal | |||
{ | |||
jack_driver_desc_t * desc_ptr; | |||
JSList * parameters; | |||
JSList * set_parameters; | |||
int refnum; | |||
}; | |||
@@ -139,7 +137,6 @@ struct jackctl_parameter | |||
union jackctl_parameter_value default_value; | |||
struct jackctl_driver * driver_ptr; | |||
char id; | |||
jack_driver_param_t * driver_parameter_ptr; | |||
jack_driver_param_constraint_desc_t * constraint_ptr; | |||
}; | |||
@@ -187,7 +184,6 @@ jackctl_add_parameter( | |||
*value_ptr = *default_value_ptr = value; | |||
parameter_ptr->driver_ptr = NULL; | |||
parameter_ptr->driver_parameter_ptr = NULL; | |||
parameter_ptr->id = 0; | |||
parameter_ptr->constraint_ptr = constraint_ptr; | |||
@@ -213,14 +209,6 @@ jackctl_free_driver_parameters( | |||
free(driver_ptr->parameters); | |||
driver_ptr->parameters = next_node_ptr; | |||
} | |||
while (driver_ptr->set_parameters) | |||
{ | |||
next_node_ptr = driver_ptr->set_parameters->next; | |||
free(driver_ptr->set_parameters->data); | |||
free(driver_ptr->set_parameters); | |||
driver_ptr->set_parameters = next_node_ptr; | |||
} | |||
} | |||
static | |||
@@ -295,6 +283,87 @@ fail: | |||
return false; | |||
} | |||
/* destroy jack_driver_param_desc_t list created by jackctl_create_param_list() */ | |||
static void | |||
jackctl_destroy_param_list( | |||
JSList * params) | |||
{ | |||
JSList * next; | |||
while (params) | |||
{ | |||
next = params->next; | |||
free(params->data); | |||
free(params); | |||
params = next; | |||
} | |||
} | |||
/* for drivers and internals are configured through jack_driver_param_t JSList */ | |||
/* this function creates such list from a jackctl_parameter list */ | |||
static | |||
bool | |||
jackctl_create_param_list( | |||
const JSList * paramlist, | |||
JSList ** retparamlist) | |||
{ | |||
jackctl_parameter * param_ptr; | |||
jack_driver_param_t * retparam_ptr; | |||
*retparamlist = NULL; | |||
while (paramlist != NULL) | |||
{ | |||
param_ptr = (jackctl_parameter *)paramlist->data; | |||
if (param_ptr->is_set) | |||
{ | |||
/* jack_info("setting driver parameter %p ...", parameter_ptr); */ | |||
retparam_ptr = (jack_driver_param_t *)malloc(sizeof(jack_driver_param_t)); | |||
if (retparam_ptr == NULL) | |||
{ | |||
jack_error ("Allocation of jack_driver_param_t structure failed"); | |||
goto destroy; | |||
} | |||
retparam_ptr->character = param_ptr->id; | |||
switch (param_ptr->type) | |||
{ | |||
case JackParamInt: | |||
retparam_ptr->value.i = param_ptr->value_ptr->i; | |||
break; | |||
case JackParamUInt: | |||
retparam_ptr->value.ui = param_ptr->value_ptr->ui; | |||
break; | |||
case JackParamChar: | |||
retparam_ptr->value.c = param_ptr->value_ptr->c; | |||
break; | |||
case JackParamString: | |||
strcpy(retparam_ptr->value.str, param_ptr->value_ptr->str); | |||
break; | |||
case JackParamBool: | |||
retparam_ptr->value.i = param_ptr->value_ptr->b; | |||
break; | |||
default: | |||
jack_error("Unknown parameter type %i", (int)param_ptr->type); | |||
assert(0); | |||
goto free; | |||
} | |||
*retparamlist = jack_slist_append(*retparamlist, retparam_ptr); | |||
} | |||
paramlist = paramlist->next; | |||
} | |||
return true; | |||
free: | |||
free(retparam_ptr); | |||
destroy: | |||
jackctl_destroy_param_list(*retparamlist); | |||
return false; | |||
} | |||
static int | |||
jackctl_drivers_load( | |||
struct jackctl_server * server_ptr) | |||
@@ -321,7 +390,6 @@ jackctl_drivers_load( | |||
driver_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data; | |||
driver_ptr->parameters = NULL; | |||
driver_ptr->set_parameters = NULL; | |||
driver_ptr->infos = NULL; | |||
if (!jackctl_add_driver_parameters(driver_ptr)) | |||
@@ -391,7 +459,6 @@ jackctl_internals_load( | |||
internal_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data; | |||
internal_ptr->parameters = NULL; | |||
internal_ptr->set_parameters = NULL; | |||
internal_ptr->refnum = -1; | |||
if (!jackctl_add_driver_parameters((struct jackctl_driver *)internal_ptr)) | |||
@@ -934,6 +1001,7 @@ jackctl_server_open( | |||
jackctl_driver *driver_ptr) | |||
{ | |||
JackSelfConnectMode self_connect_mode; | |||
JSList * paramlist = NULL; | |||
try { | |||
@@ -1011,7 +1079,9 @@ jackctl_server_open( | |||
goto fail_unregister; | |||
} | |||
rc = server_ptr->engine->Open(driver_ptr->desc_ptr, driver_ptr->set_parameters); | |||
if (!jackctl_create_param_list(driver_ptr->parameters, ¶mlist)) goto fail_delete; | |||
rc = server_ptr->engine->Open(driver_ptr->desc_ptr, paramlist); | |||
jackctl_destroy_param_list(paramlist); | |||
if (rc < 0) | |||
{ | |||
jack_error("JackServer::Open failed with %d", rc); | |||
@@ -1022,6 +1092,7 @@ jackctl_server_open( | |||
} catch (std::exception e) { | |||
jack_error("jackctl_server_open error..."); | |||
jackctl_destroy_param_list(paramlist); | |||
} | |||
fail_delete: | |||
@@ -1110,7 +1181,7 @@ SERVER_EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *para | |||
SERVER_EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr) | |||
{ | |||
if (!parameter_ptr) { | |||
return NULL; | |||
return 0; | |||
} | |||
if (!jackctl_parameter_has_enum_constraint(parameter_ptr)) | |||
@@ -1242,57 +1313,6 @@ SERVER_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, | |||
return NULL; | |||
} | |||
bool new_driver_parameter; | |||
/* for driver parameters, set the parameter by adding jack_driver_param_t in the set_parameters list */ | |||
if (parameter_ptr->driver_ptr != NULL) | |||
{ | |||
/* jack_info("setting driver parameter %p ...", parameter_ptr); */ | |||
new_driver_parameter = parameter_ptr->driver_parameter_ptr == NULL; | |||
if (new_driver_parameter) | |||
{ | |||
/* jack_info("new driver parameter..."); */ | |||
parameter_ptr->driver_parameter_ptr = (jack_driver_param_t *)malloc(sizeof(jack_driver_param_t)); | |||
if (parameter_ptr->driver_parameter_ptr == NULL) | |||
{ | |||
jack_error ("Allocation of jack_driver_param_t structure failed"); | |||
return false; | |||
} | |||
parameter_ptr->driver_parameter_ptr->character = parameter_ptr->id; | |||
parameter_ptr->driver_ptr->set_parameters = jack_slist_append(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr); | |||
} | |||
switch (parameter_ptr->type) | |||
{ | |||
case JackParamInt: | |||
parameter_ptr->driver_parameter_ptr->value.i = value_ptr->i; | |||
break; | |||
case JackParamUInt: | |||
parameter_ptr->driver_parameter_ptr->value.ui = value_ptr->ui; | |||
break; | |||
case JackParamChar: | |||
parameter_ptr->driver_parameter_ptr->value.c = value_ptr->c; | |||
break; | |||
case JackParamString: | |||
strcpy(parameter_ptr->driver_parameter_ptr->value.str, value_ptr->str); | |||
break; | |||
case JackParamBool: | |||
parameter_ptr->driver_parameter_ptr->value.i = value_ptr->b; | |||
break; | |||
default: | |||
jack_error("Unknown parameter type %i", (int)parameter_ptr->type); | |||
assert(0); | |||
if (new_driver_parameter) | |||
{ | |||
parameter_ptr->driver_ptr->set_parameters = jack_slist_remove(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr); | |||
} | |||
return false; | |||
} | |||
} | |||
parameter_ptr->is_set = true; | |||
*parameter_ptr->value_ptr = *value_ptr; | |||
@@ -1337,7 +1357,10 @@ SERVER_EXPORT bool jackctl_server_load_internal( | |||
int status; | |||
if (server_ptr->engine != NULL) { | |||
server_ptr->engine->InternalClientLoad2(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, -1, &status); | |||
JSList * paramlist; | |||
if (!jackctl_create_param_list(internal->parameters, ¶mlist)) return false; | |||
server_ptr->engine->InternalClientLoad2(internal->desc_ptr->name, internal->desc_ptr->name, paramlist, JackNullOption, &internal->refnum, -1, &status); | |||
jackctl_destroy_param_list(paramlist); | |||
return (internal->refnum > 0); | |||
} else { | |||
return false; | |||
@@ -1368,7 +1391,10 @@ SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl | |||
jack_error("Cannot add a slave in a running server"); | |||
return false; | |||
} else { | |||
JackDriverInfo* info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters); | |||
JSList * paramlist; | |||
if (!jackctl_create_param_list(driver_ptr->parameters, ¶mlist)) return false; | |||
JackDriverInfo* info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, paramlist); | |||
jackctl_destroy_param_list(paramlist); | |||
if (info) { | |||
driver_ptr->infos = jack_slist_append(driver_ptr->infos, info); | |||
return true; | |||
@@ -1407,7 +1433,11 @@ SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jack | |||
SERVER_EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr) | |||
{ | |||
if (server_ptr && server_ptr->engine) { | |||
return (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, driver_ptr->set_parameters) == 0); | |||
JSList * paramlist; | |||
if (!jackctl_create_param_list(driver_ptr->parameters, ¶mlist)) return false; | |||
bool ret = (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, paramlist) == 0); | |||
jackctl_destroy_param_list(paramlist); | |||
return ret; | |||
} else { | |||
return false; | |||
} | |||
@@ -205,6 +205,22 @@ Client that finish *after* the callback date are considered late even if their o | |||
correctly mixed in the time window: callbackUsecs <==> Read <==> Write. | |||
*/ | |||
static const char* State2String(jack_client_state_t state) | |||
{ | |||
switch (state) { | |||
case NotTriggered: | |||
return "NotTriggered"; | |||
case Triggered: | |||
return "Triggered"; | |||
case Running: | |||
return "Running"; | |||
case Finished: | |||
return "Finished"; | |||
default: | |||
return ""; | |||
} | |||
} | |||
void JackEngine::CheckXRun(jack_time_t callback_usecs) // REVOIR les conditions de fin | |||
{ | |||
for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) { | |||
@@ -215,7 +231,7 @@ void JackEngine::CheckXRun(jack_time_t callback_usecs) // REVOIR les conditions | |||
jack_time_t finished_date = timing->fFinishedAt; | |||
if (status != NotTriggered && status != Finished) { | |||
jack_error("JackEngine::XRun: client = %s was not run: state = %ld", client->GetClientControl()->fName, status); | |||
jack_error("JackEngine::XRun: client = %s was not finished, state = %s", client->GetClientControl()->fName, State2String(status)); | |||
fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); // Notify all clients | |||
} | |||
@@ -352,8 +368,8 @@ void JackEngine::NotifyXRun(int refnum) | |||
void JackEngine::NotifyGraphReorder() | |||
{ | |||
NotifyClients(kGraphOrderCallback, false, "", 0, 0); | |||
ComputeTotalLatencies(); | |||
NotifyClients(kGraphOrderCallback, false, "", 0, 0); | |||
} | |||
void JackEngine::NotifyBufferSize(jack_nframes_t buffer_size) | |||
@@ -27,10 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackServer.h" | |||
#include "JackEngineControl.h" | |||
#include "JackClientControl.h" | |||
#include "JackInternalClientChannel.h" | |||
#include "JackGenericClientChannel.h" | |||
#include "JackTools.h" | |||
#include <assert.h> | |||
@@ -166,7 +166,7 @@ static jack_client_t* jack_client_open_aux(const char* client_name, jack_options | |||
LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | |||
{ | |||
JackGlobals::CheckContext("jack_client_open"); | |||
JackGlobals::CheckContext("jack_client_open"); | |||
try { | |||
assert(JackGlobals::fOpenMutex); | |||
@@ -177,7 +177,7 @@ LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_opt | |||
va_end(ap); | |||
JackGlobals::fOpenMutex->Unlock(); | |||
return res; | |||
} catch(std::bad_alloc& e) { | |||
} catch (std::bad_alloc& e) { | |||
jack_error("Memory allocation error..."); | |||
return NULL; | |||
} catch (...) { | |||
@@ -41,7 +41,7 @@ catch (...) { | |||
*/ | |||
#define CATCH_EXCEPTION_RETURN \ | |||
} catch(std::bad_alloc& e) { \ | |||
} catch (std::bad_alloc& e) { \ | |||
jack_error("Memory allocation error..."); \ | |||
return -1; \ | |||
} catch (...) { \ | |||
@@ -50,10 +50,10 @@ catch (...) { | |||
} \ | |||
#define CATCH_CLOSE_EXCEPTION_RETURN \ | |||
} catch(std::bad_alloc& e) { \ | |||
} catch (std::bad_alloc& e) { \ | |||
jack_error("Memory allocation error..."); \ | |||
return -1; \ | |||
} catch(JackTemporaryException& e) { \ | |||
} catch (JackTemporaryException& e) { \ | |||
jack_error("JackTemporaryException : now quits..."); \ | |||
JackTools::KillServer(); \ | |||
return 0; \ | |||
@@ -63,7 +63,7 @@ catch (...) { | |||
} | |||
#define CATCH_EXCEPTION \ | |||
} catch(std::bad_alloc& e) { \ | |||
} catch (std::bad_alloc& e) { \ | |||
jack_error("Memory allocation error..."); \ | |||
} catch (...) { \ | |||
jack_error("Unknown error..."); \ | |||
@@ -327,8 +327,8 @@ class SERVER_EXPORT JackLockedEngine | |||
void NotifyQuit() | |||
{ | |||
// No lock needed | |||
TRY_CALL | |||
JackLock lock(&fEngine); | |||
return fEngine.NotifyQuit(); | |||
CATCH_EXCEPTION | |||
} | |||
@@ -136,9 +136,7 @@ int JackMidiDriver::SetBufferSize(jack_nframes_t buffer_size) | |||
int JackMidiDriver::ProcessReadSync() | |||
{ | |||
int res = 0; | |||
jack_log("JackMidiDriver::ProcessReadSync"); | |||
// Read input buffers for the current cycle | |||
if (Read() < 0) { | |||
jack_error("JackMidiDriver::ProcessReadSync: read error"); | |||
@@ -156,9 +154,7 @@ int JackMidiDriver::ProcessReadSync() | |||
int JackMidiDriver::ProcessWriteSync() | |||
{ | |||
int res = 0; | |||
jack_log("JackMidiDriver::ProcessWriteSync"); | |||
if (SuspendRefNum() < 0) { | |||
jack_error("JackMidiDriver::ProcessWriteSync: SuspendRefNum error"); | |||
res = -1; | |||
@@ -176,9 +172,7 @@ int JackMidiDriver::ProcessWriteSync() | |||
int JackMidiDriver::ProcessReadAsync() | |||
{ | |||
int res = 0; | |||
jack_log("JackMidiDriver::ProcessReadAsync"); | |||
// Read input buffers for the current cycle | |||
if (Read() < 0) { | |||
jack_error("JackMidiDriver::ProcessReadAsync: read error"); | |||
@@ -201,7 +195,6 @@ int JackMidiDriver::ProcessReadAsync() | |||
int JackMidiDriver::ProcessWriteAsync() | |||
{ | |||
jack_log("JackMidiDriver::ProcessWriteAsync"); | |||
return 0; | |||
} | |||
@@ -37,7 +37,7 @@ extern "C" | |||
JackFloatEncoder = 0, | |||
JackIntEncoder = 1, | |||
JackCeltEncoder = 2, | |||
JackMaxEncoder = 3 | |||
JackOpusEncoder = 3 | |||
}; | |||
typedef struct { | |||
@@ -551,6 +551,11 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
return -1; | |||
} | |||
if ((fParams.fSampleEncoder == JackOpusEncoder) && (fParams.fKBps == 0)) { | |||
jack_error("Opus encoder with 0 for kps..."); | |||
return -1; | |||
} | |||
// Check latency | |||
if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { | |||
jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY); | |||
@@ -101,6 +101,14 @@ namespace Jack | |||
fParams.fKBps = param->value.i; | |||
} | |||
break; | |||
#endif | |||
#if HAVE_OPUS | |||
case 'O': | |||
if (param->value.i > 0) { | |||
fParams.fSampleEncoder = JackOpusEncoder; | |||
fParams.fKBps = param->value.i; | |||
} | |||
break; | |||
#endif | |||
case 'l' : | |||
fParams.fNetworkLatency = param->value.i; | |||
@@ -404,7 +412,7 @@ extern "C" | |||
desc = jack_driver_descriptor_construct("netadapter", JackDriverNone, "netjack net <==> audio backend adapter", &filler); | |||
strcpy(value.str, DEFAULT_MULTICAST_IP); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address, or explicit IP of the master", NULL); | |||
value.i = DEFAULT_PORT; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||
@@ -421,6 +429,11 @@ extern "C" | |||
jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL); | |||
#endif | |||
#if HAVE_OPUS | |||
value.i = -1; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "opus", 'O', JackDriverParamInt, &value, NULL, "Set Opus encoding and number of kBits per channel", NULL); | |||
#endif | |||
strcpy(value.str, "'hostname'"); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); | |||
@@ -463,7 +476,7 @@ extern "C" | |||
} | |||
} catch (...) { | |||
jack_info("NetAdapter allocation error"); | |||
jack_info("netadapter allocation error"); | |||
return 1; | |||
} | |||
} | |||
@@ -29,7 +29,7 @@ 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, int network_latency, int celt_encoding) | |||
char* net_name, uint transport_sync, int network_latency, int celt_encoding, int opus_encoding) | |||
: JackWaiterDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) | |||
{ | |||
jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port); | |||
@@ -45,6 +45,9 @@ namespace Jack | |||
if (celt_encoding > 0) { | |||
fParams.fSampleEncoder = JackCeltEncoder; | |||
fParams.fKBps = celt_encoding; | |||
} else if (opus_encoding > 0) { | |||
fParams.fSampleEncoder = JackOpusEncoder; | |||
fParams.fKBps = opus_encoding; | |||
} else { | |||
fParams.fSampleEncoder = JackFloatEncoder; | |||
//fParams.fSampleEncoder = JackIntEncoder; | |||
@@ -600,7 +603,7 @@ namespace Jack | |||
desc = jack_driver_descriptor_construct("net", JackDriverMaster, "netjack slave backend component", &filler); | |||
strcpy(value.str, DEFAULT_MULTICAST_IP); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address, or explicit IP of the master", NULL); | |||
value.i = DEFAULT_PORT; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||
@@ -619,6 +622,10 @@ namespace Jack | |||
#if HAVE_CELT | |||
value.i = -1; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL); | |||
#endif | |||
#if HAVE_OPUS | |||
value.i = -1; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "opus", 'O', JackDriverParamInt, &value, NULL, "Set Opus encoding and number of kBits per channel", NULL); | |||
#endif | |||
strcpy(value.str, "'hostname'"); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); | |||
@@ -650,6 +657,7 @@ Deactivated for now.. | |||
int midi_input_ports = 0; | |||
int midi_output_ports = 0; | |||
int celt_encoding = -1; | |||
int opus_encoding = -1; | |||
bool monitor = false; | |||
int network_latency = 5; | |||
const JSList* node; | |||
@@ -699,6 +707,11 @@ Deactivated for now.. | |||
celt_encoding = param->value.i; | |||
break; | |||
#endif | |||
#if HAVE_OPUS | |||
case 'O': | |||
opus_encoding = param->value.i; | |||
break; | |||
#endif | |||
case 'n' : | |||
strncpy(net_name, param->value.str, JACK_CLIENT_NAME_SIZE); | |||
break; | |||
@@ -724,7 +737,7 @@ Deactivated for now.. | |||
new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, | |||
midi_input_ports, midi_output_ports, | |||
net_name, transport_sync, | |||
network_latency, celt_encoding)); | |||
network_latency, celt_encoding, opus_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 { | |||
@@ -69,7 +69,7 @@ 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, int network_latency, int celt_encoding); | |||
char* net_name, uint transport_sync, int network_latency, int celt_encoding, int opus_encoding); | |||
virtual ~JackNetDriver(); | |||
int Close(); | |||
@@ -243,6 +243,10 @@ namespace Jack | |||
case JackCeltEncoder: | |||
return new NetCeltAudioBuffer(&fParams, nports, buffer, fParams.fKBps); | |||
#endif | |||
#if HAVE_OPUS | |||
case JackOpusEncoder: | |||
return new NetOpusAudioBuffer(&fParams, nports, buffer, fParams.fKBps); | |||
#endif | |||
} | |||
return NULL; | |||
} | |||
@@ -823,7 +823,7 @@ extern "C" | |||
desc = jack_driver_descriptor_construct("netmanager", JackDriverNone, "netjack multi-cast master component", &filler); | |||
strcpy(value.str, DEFAULT_MULTICAST_IP); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address", NULL); | |||
value.i = DEFAULT_PORT; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||
@@ -39,6 +39,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include <celt/celt.h> | |||
#endif | |||
#if HAVE_OPUS | |||
#include <opus/opus.h> | |||
#include <opus/opus_custom.h> | |||
#endif | |||
#define MIN(x,y) ((x)<(y) ? (x) : (y)) | |||
using namespace std; | |||
@@ -146,6 +151,12 @@ int JackNetOneDriver::AllocPorts() | |||
#endif | |||
celt_mode_info(celt_mode, CELT_GET_LOOKAHEAD, &lookahead); | |||
netj.codec_latency = 2 * lookahead; | |||
#endif | |||
} else if (netj.bitdepth == OPUS_MODE) { | |||
#if HAVE_OPUS | |||
OpusCustomMode *opus_mode = opus_custom_mode_create(netj.sample_rate, netj.period_size, NULL); // XXX free me in the end | |||
OpusCustomDecoder *decoder = opus_custom_decoder_create( opus_mode, 1, NULL ); | |||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, decoder); | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
@@ -191,6 +202,21 @@ int JackNetOneDriver::AllocPorts() | |||
CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL); | |||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode)); | |||
#endif | |||
#endif | |||
} else if (netj.bitdepth == OPUS_MODE) { | |||
#if HAVE_OPUS | |||
const int kbps = netj.resample_factor; | |||
jack_error("NEW ONE OPUS ENCODER 128 <> %d!!", kbps); | |||
int err; | |||
OpusCustomMode *opus_mode = opus_custom_mode_create( netj.sample_rate, netj.period_size, &err ); // XXX free me in the end | |||
if (err != OPUS_OK) { jack_error("opus mode failed"); } | |||
OpusCustomEncoder *oe = opus_custom_encoder_create( opus_mode, 1, &err ); | |||
if (err != OPUS_OK) { jack_error("opus mode failed"); } | |||
opus_custom_encoder_ctl(oe, OPUS_SET_BITRATE(kbps*1024)); // bits per second | |||
opus_custom_encoder_ctl(oe, OPUS_SET_COMPLEXITY(10)); | |||
opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); | |||
opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_APPLICATION_RESTRICTED_LOWDELAY)); | |||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, oe); | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
@@ -450,6 +476,28 @@ JackNetOneDriver::FreePorts () | |||
celt_decoder_destroy(dec); | |||
} | |||
netj.capture_srcs = NULL; | |||
#endif | |||
} else if (netj.bitdepth == OPUS_MODE) { | |||
#if HAVE_OPUS | |||
node = netj.playback_srcs; | |||
while (node != NULL) { | |||
JSList *this_node = node; | |||
OpusCustomEncoder *enc = (OpusCustomEncoder *) node->data; | |||
node = jack_slist_remove_link(node, this_node); | |||
jack_slist_free_1(this_node); | |||
opus_custom_encoder_destroy(enc); | |||
} | |||
netj.playback_srcs = NULL; | |||
node = netj.capture_srcs; | |||
while (node != NULL) { | |||
JSList *this_node = node; | |||
OpusCustomDecoder *dec = (OpusCustomDecoder *) node->data; | |||
node = jack_slist_remove_link(node, this_node); | |||
jack_slist_free_1(this_node); | |||
opus_custom_decoder_destroy(dec); | |||
} | |||
netj.capture_srcs = NULL; | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
@@ -724,6 +772,98 @@ JackNetOneDriver::render_jack_ports_to_payload_celt (JSList *playback_ports, JSL | |||
} | |||
#endif | |||
#if HAVE_OPUS | |||
#define CDO (sizeof(short)) ///< compressed data offset (first 2 bytes are length) | |||
// render functions for Opus. | |||
void | |||
JackNetOneDriver::render_payload_to_jack_ports_opus (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes) | |||
{ | |||
int chn = 0; | |||
JSList *node = capture_ports; | |||
JSList *src_node = capture_srcs; | |||
unsigned char *packet_bufX = (unsigned char *)packet_payload; | |||
while (node != NULL) { | |||
jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data; | |||
JackPort *port = fGraphManager->GetPort(port_index); | |||
jack_default_audio_sample_t* buf = | |||
(jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | |||
const char *portname = port->GetType(); | |||
if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) { | |||
// audio port, decode opus data. | |||
OpusCustomDecoder *decoder = (OpusCustomDecoder*) src_node->data; | |||
if( !packet_payload ) | |||
memset(buf, 0, nframes * sizeof(float)); | |||
else { | |||
unsigned short len; | |||
memcpy(&len, packet_bufX, CDO); | |||
len = ntohs(len); | |||
opus_custom_decode_float( decoder, packet_bufX + CDO, len, buf, nframes ); | |||
} | |||
src_node = jack_slist_next (src_node); | |||
} else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) { | |||
// midi port, decode midi events | |||
// convert the data buffer to a standard format (uint32_t based) | |||
unsigned int buffer_size_uint32 = net_period_down / 2; | |||
uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | |||
if( packet_payload ) | |||
decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | |||
} | |||
packet_bufX = (packet_bufX + net_period_down); | |||
node = jack_slist_next (node); | |||
chn++; | |||
} | |||
} | |||
void | |||
JackNetOneDriver::render_jack_ports_to_payload_opus (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up) | |||
{ | |||
int chn = 0; | |||
JSList *node = playback_ports; | |||
JSList *src_node = playback_srcs; | |||
unsigned char *packet_bufX = (unsigned char *)packet_payload; | |||
while (node != NULL) { | |||
jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data; | |||
JackPort *port = fGraphManager->GetPort(port_index); | |||
jack_default_audio_sample_t* buf = | |||
(jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | |||
const char *portname = port->GetType(); | |||
if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) { | |||
// audio port, encode opus data. | |||
int encoded_bytes; | |||
jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes); | |||
memcpy(floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t)); | |||
OpusCustomEncoder *encoder = (OpusCustomEncoder*) src_node->data; | |||
encoded_bytes = opus_custom_encode_float( encoder, floatbuf, nframes, packet_bufX + CDO, net_period_up - CDO ); | |||
unsigned short len = htons(encoded_bytes); | |||
memcpy(packet_bufX, &len, CDO); | |||
src_node = jack_slist_next( src_node ); | |||
} else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) { | |||
// encode midi events from port to packet | |||
// convert the data buffer to a standard format (uint32_t based) | |||
unsigned int buffer_size_uint32 = net_period_up / 2; | |||
uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | |||
encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | |||
} | |||
packet_bufX = (packet_bufX + net_period_up); | |||
node = jack_slist_next (node); | |||
chn++; | |||
} | |||
} | |||
#endif | |||
/* Wrapper functions with bitdepth argument... */ | |||
void | |||
JackNetOneDriver::render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats) | |||
@@ -732,6 +872,11 @@ JackNetOneDriver::render_payload_to_jack_ports (int bitdepth, void *packet_paylo | |||
if (bitdepth == CELT_MODE) | |||
render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes); | |||
else | |||
#endif | |||
#if HAVE_OPUS | |||
if (bitdepth == OPUS_MODE) | |||
render_payload_to_jack_ports_opus (packet_payload, net_period_down, capture_ports, capture_srcs, nframes); | |||
else | |||
#endif | |||
render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats); | |||
} | |||
@@ -743,6 +888,11 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p | |||
if (bitdepth == CELT_MODE) | |||
render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up); | |||
else | |||
#endif | |||
#if HAVE_OPUS | |||
if (bitdepth == OPUS_MODE) | |||
render_jack_ports_to_payload_opus (playback_ports, playback_srcs, nframes, packet_payload, net_period_up); | |||
else | |||
#endif | |||
render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats); | |||
} | |||
@@ -791,6 +941,10 @@ extern "C" | |||
#if HAVE_CELT | |||
value.ui = 0U; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamUInt, &value, NULL, "Set CELT encoding and number of kbits per channel", NULL); | |||
#endif | |||
#if HAVE_OPUS | |||
value.ui = 0U; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "opus", 'P', JackDriverParamUInt, &value, NULL, "Set Opus encoding and number of kbits per channel", NULL); | |||
#endif | |||
value.ui = 0U; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "bit-depth", 'b', JackDriverParamUInt, &value, NULL, "Sample bit-depth (0 for float, 8 for 8bit and 16 for 16bit)", NULL); | |||
@@ -904,6 +1058,17 @@ extern "C" | |||
#endif | |||
break; | |||
case 'P': | |||
#if HAVE_OPUS | |||
bitdepth = OPUS_MODE; | |||
resample_factor = param->value.ui; | |||
jack_error("OPUS: %d\n", resample_factor); | |||
#else | |||
jack_error("not built with Opus support"); | |||
return NULL; | |||
#endif | |||
break; | |||
case 't': | |||
handle_transport_sync = param->value.ui; | |||
break; | |||
@@ -45,6 +45,12 @@ class JackNetOneDriver : public JackWaiterDriver | |||
render_payload_to_jack_ports_celt(void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes); | |||
void | |||
render_jack_ports_to_payload_celt(JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up); | |||
#endif | |||
#if HAVE_OPUS | |||
void | |||
render_payload_to_jack_ports_opus(void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes); | |||
void | |||
render_jack_ports_to_payload_opus(JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up); | |||
#endif | |||
void | |||
render_payload_to_jack_ports(int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats); | |||
@@ -709,6 +709,227 @@ namespace Jack | |||
#endif | |||
#if HAVE_OPUS | |||
#define CDO (sizeof(short)) ///< compressed data offset (first 2 bytes are length) | |||
NetOpusAudioBuffer::NetOpusAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps) | |||
:NetAudioBuffer(params, nports, net_buffer) | |||
{ | |||
fOpusMode = new OpusCustomMode *[fNPorts]; | |||
fOpusEncoder = new OpusCustomEncoder *[fNPorts]; | |||
fOpusDecoder = new OpusCustomDecoder *[fNPorts]; | |||
fCompressedSizesByte = new unsigned short [fNPorts]; | |||
memset(fOpusMode, 0, fNPorts * sizeof(OpusCustomMode*)); | |||
memset(fOpusEncoder, 0, fNPorts * sizeof(OpusCustomEncoder*)); | |||
memset(fOpusDecoder, 0, fNPorts * sizeof(OpusCustomDecoder*)); | |||
memset(fCompressedSizesByte, 0, fNPorts * sizeof(int)); | |||
int error = OPUS_OK; | |||
for (int i = 0; i < fNPorts; i++) { | |||
/* Allocate en/decoders */ | |||
fOpusMode[i] = opus_custom_mode_create( | |||
params->fSampleRate, params->fPeriodSize, &error); | |||
if (error != OPUS_OK) { | |||
goto error; | |||
} | |||
fOpusEncoder[i] = opus_custom_encoder_create(fOpusMode[i], 1,&error); | |||
if (error != OPUS_OK) { | |||
goto error; | |||
} | |||
fOpusDecoder[i] = opus_custom_decoder_create(fOpusMode[i], 1, &error); | |||
if (error != OPUS_OK) { | |||
goto error; | |||
} | |||
opus_custom_encoder_ctl(fOpusEncoder[i], OPUS_SET_BITRATE(kbps*1024)); // bits per second | |||
opus_custom_encoder_ctl(fOpusEncoder[i], OPUS_SET_COMPLEXITY(10)); | |||
opus_custom_encoder_ctl(fOpusEncoder[i], OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); | |||
opus_custom_encoder_ctl(fOpusEncoder[i], OPUS_SET_SIGNAL(OPUS_APPLICATION_RESTRICTED_LOWDELAY)); | |||
} | |||
{ | |||
fCompressedMaxSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8); | |||
fPeriodSize = params->fPeriodSize; | |||
jack_log("NetOpusAudioBuffer fCompressedMaxSizeByte %d", fCompressedMaxSizeByte); | |||
fCompressedBuffer = new unsigned char* [fNPorts]; | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
fCompressedBuffer[port_index] = new unsigned char[fCompressedMaxSizeByte]; | |||
memset(fCompressedBuffer[port_index], 0, fCompressedMaxSizeByte * sizeof(char)); | |||
} | |||
int res1 = (fNPorts * fCompressedMaxSizeByte + CDO) % PACKET_AVAILABLE_SIZE(params); | |||
int res2 = (fNPorts * fCompressedMaxSizeByte + CDO) / PACKET_AVAILABLE_SIZE(params); | |||
fNumPackets = (res1) ? (res2 + 1) : res2; | |||
jack_log("NetOpusAudioBuffer res1 = %d res2 = %d", res1, res2); | |||
fSubPeriodBytesSize = (fCompressedMaxSizeByte + CDO) / fNumPackets; | |||
fLastSubPeriodBytesSize = fSubPeriodBytesSize + (fCompressedMaxSizeByte + CDO) % fNumPackets; | |||
if (fNumPackets == 1) { | |||
fSubPeriodBytesSize = fLastSubPeriodBytesSize; | |||
} | |||
jack_log("NetOpusAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize); | |||
fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate); | |||
fCycleBytesSize = params->fMtu * fNumPackets; | |||
fLastSubCycle = -1; | |||
return; | |||
} | |||
error: | |||
FreeOpus(); | |||
throw std::bad_alloc(); | |||
} | |||
NetOpusAudioBuffer::~NetOpusAudioBuffer() | |||
{ | |||
FreeOpus(); | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
delete [] fCompressedBuffer[port_index]; | |||
} | |||
delete [] fCompressedBuffer; | |||
delete [] fCompressedSizesByte; | |||
} | |||
void NetOpusAudioBuffer::FreeOpus() | |||
{ | |||
for (int i = 0; i < fNPorts; i++) { | |||
if (fOpusEncoder[i]) { | |||
opus_custom_encoder_destroy(fOpusEncoder[i]); | |||
fOpusEncoder[i]=0; | |||
} | |||
if (fOpusDecoder[i]) { | |||
opus_custom_decoder_destroy(fOpusDecoder[i]); | |||
fOpusDecoder[i]=0; | |||
} | |||
if (fOpusMode[i]) { | |||
opus_custom_mode_destroy(fOpusMode[i]); | |||
fOpusMode[i]=0; | |||
} | |||
} | |||
delete [] fOpusEncoder; | |||
delete [] fOpusDecoder; | |||
delete [] fOpusMode; | |||
} | |||
size_t NetOpusAudioBuffer::GetCycleSize() | |||
{ | |||
return fCycleBytesSize; | |||
} | |||
float NetOpusAudioBuffer::GetCycleDuration() | |||
{ | |||
return fCycleDuration; | |||
} | |||
int NetOpusAudioBuffer::GetNumPackets(int active_ports) | |||
{ | |||
return fNumPackets; | |||
} | |||
int NetOpusAudioBuffer::RenderFromJackPorts() | |||
{ | |||
float buffer[BUFFER_SIZE_MAX]; | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
if (fPortBuffer[port_index]) { | |||
memcpy(buffer, fPortBuffer[port_index], fPeriodSize * sizeof(sample_t)); | |||
} else { | |||
memset(buffer, 0, fPeriodSize * sizeof(sample_t)); | |||
} | |||
int res = opus_custom_encode_float(fOpusEncoder[port_index], buffer, fPeriodSize, fCompressedBuffer[port_index], fCompressedMaxSizeByte); | |||
if (res <0 || res >= 65535) { | |||
fCompressedSizesByte[port_index] = 0; | |||
} else { | |||
fCompressedSizesByte[port_index] = res; | |||
} | |||
} | |||
// All ports active | |||
return fNPorts; | |||
} | |||
void NetOpusAudioBuffer::RenderToJackPorts() | |||
{ | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
if (fPortBuffer[port_index]) { | |||
int res = opus_custom_decode_float(fOpusDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizesByte[port_index], fPortBuffer[port_index], fPeriodSize); | |||
if (res < 0 || res != fPeriodSize) { | |||
jack_error("opus_decode_float error fCompressedSizeByte = %d res = %d", fCompressedSizesByte[port_index], res); | |||
} | |||
} | |||
} | |||
NextCycle(); | |||
} | |||
//network<->buffer | |||
int NetOpusAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num) | |||
{ | |||
// Cleanup all JACK ports at the beginning of the cycle | |||
if (sub_cycle == 0) { | |||
Cleanup(); | |||
} | |||
if (port_num > 0) { | |||
if (sub_cycle == 0) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
size_t len = *((size_t*)(fNetBuffer + port_index * fSubPeriodBytesSize)); | |||
fCompressedSizesByte[port_index] = ntohs(len); | |||
memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + CDO + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize - CDO); | |||
} | |||
} else if (sub_cycle == fNumPackets - 1) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize - CDO, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize); | |||
} | |||
} else { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize - CDO, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); | |||
} | |||
} | |||
} | |||
return CheckPacket(cycle, sub_cycle); | |||
} | |||
int NetOpusAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num) | |||
{ | |||
if (sub_cycle == 0) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
unsigned short len = htons(fCompressedSizesByte[port_index]); | |||
memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, &len, CDO); | |||
memcpy(fNetBuffer + port_index * fSubPeriodBytesSize + CDO, fCompressedBuffer[port_index], fSubPeriodBytesSize - CDO); | |||
} | |||
return fNPorts * fSubPeriodBytesSize; | |||
} else if (sub_cycle == fNumPackets - 1) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize - CDO, fLastSubPeriodBytesSize); | |||
} | |||
return fNPorts * fLastSubPeriodBytesSize; | |||
} else { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize - CDO, fSubPeriodBytesSize); | |||
} | |||
return fNPorts * fSubPeriodBytesSize; | |||
} | |||
} | |||
#endif | |||
NetIntAudioBuffer::NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer) | |||
: NetAudioBuffer(params, nports, net_buffer) | |||
{ | |||
@@ -840,6 +1061,7 @@ namespace Jack | |||
SERVER_EXPORT void SessionParamsHToN(session_params_t* src_params, session_params_t* dst_params) | |||
{ | |||
memcpy(dst_params, src_params, sizeof(session_params_t)); | |||
dst_params->fProtocolVersion = htonl(src_params->fProtocolVersion); | |||
dst_params->fPacketID = htonl(src_params->fPacketID); | |||
dst_params->fMtu = htonl(src_params->fMtu); | |||
dst_params->fID = htonl(src_params->fID); | |||
@@ -859,6 +1081,7 @@ namespace Jack | |||
SERVER_EXPORT void SessionParamsNToH(session_params_t* src_params, session_params_t* dst_params) | |||
{ | |||
memcpy(dst_params, src_params, sizeof(session_params_t)); | |||
dst_params->fProtocolVersion = ntohl(src_params->fProtocolVersion); | |||
dst_params->fPacketID = ntohl(src_params->fPacketID); | |||
dst_params->fMtu = ntohl(src_params->fMtu); | |||
dst_params->fID = ntohl(src_params->fID); | |||
@@ -889,6 +1112,9 @@ namespace Jack | |||
case JackCeltEncoder: | |||
strcpy(encoder, "CELT"); | |||
break; | |||
case JackOpusEncoder: | |||
strcpy(encoder, "OPUS"); | |||
break; | |||
} | |||
jack_info("**************** Network parameters ****************"); | |||
@@ -915,6 +1141,10 @@ namespace Jack | |||
jack_info("SampleEncoder : %s", "CELT"); | |||
jack_info("kBits : %d", params->fKBps); | |||
break; | |||
case (JackOpusEncoder): | |||
jack_info("SampleEncoder : %s", "OPUS"); | |||
jack_info("kBits : %d", params->fKBps); | |||
break; | |||
}; | |||
jack_info("Slave mode : %s", (params->fSlaveSyncMode) ? "sync" : "async"); | |||
jack_info("****************************************************"); | |||
@@ -967,6 +1197,8 @@ namespace Jack | |||
SERVER_EXPORT void PacketHeaderHToN(packet_header_t* src_header, packet_header_t* dst_header) | |||
{ | |||
memcpy(dst_header, src_header, sizeof(packet_header_t)); | |||
dst_header->fDataType = htonl(src_header->fDataType); | |||
dst_header->fDataStream = htonl(src_header->fDataStream); | |||
dst_header->fID = htonl(src_header->fID); | |||
dst_header->fNumPacket = htonl(src_header->fNumPacket); | |||
dst_header->fPacketSize = htonl(src_header->fPacketSize); | |||
@@ -979,6 +1211,8 @@ namespace Jack | |||
SERVER_EXPORT void PacketHeaderNToH(packet_header_t* src_header, packet_header_t* dst_header) | |||
{ | |||
memcpy(dst_header, src_header, sizeof(packet_header_t)); | |||
dst_header->fDataType = ntohl(src_header->fDataType); | |||
dst_header->fDataStream = ntohl(src_header->fDataStream); | |||
dst_header->fID = ntohl(src_header->fID); | |||
dst_header->fNumPacket = ntohl(src_header->fNumPacket); | |||
dst_header->fPacketSize = ntohl(src_header->fPacketSize); | |||
@@ -38,8 +38,8 @@ using namespace std; | |||
#endif | |||
#endif | |||
#define MASTER_PROTOCOL 5 | |||
#define SLAVE_PROTOCOL 5 | |||
#define MASTER_PROTOCOL 6 | |||
#define SLAVE_PROTOCOL 6 | |||
#define NET_PACKET_ERROR -2 | |||
@@ -62,6 +62,7 @@ namespace Jack | |||
JackFloatEncoder = 0, | |||
JackIntEncoder = 1, | |||
JackCeltEncoder = 2, | |||
JackOpusEncoder = 3, | |||
}; | |||
//session params ****************************************************************************** | |||
@@ -83,11 +84,12 @@ namespace Jack | |||
are kept in LITTLE_ENDIAN format (to avoid 2 conversions in the more common LITTLE_ENDIAN <==> LITTLE_ENDIAN connection case). | |||
*/ | |||
PRE_PACKED_STRUCTURE | |||
struct _session_params | |||
{ | |||
char fPacketType[7]; //packet type ('param') | |||
char fProtocolVersion; //version | |||
uint32_t fPacketID; //indicates the packet type | |||
char fPacketType[8]; //packet type ('param') | |||
uint32_t fProtocolVersion; //version | |||
int32_t fPacketID; //indicates the packet type | |||
char fName[JACK_CLIENT_NAME_SIZE]; //slave's name | |||
char fMasterNetName[256]; //master hostname (network) | |||
char fSlaveNetName[256]; //slave hostname (network) | |||
@@ -104,7 +106,7 @@ namespace Jack | |||
uint32_t fKBps; //KB per second for CELT encoder | |||
uint32_t fSlaveSyncMode; //is the slave in sync mode ? | |||
uint32_t fNetworkLatency; //network latency | |||
}; | |||
} POST_PACKED_STRUCTURE; | |||
//net status ********************************************************************************** | |||
@@ -165,11 +167,12 @@ namespace Jack | |||
*/ | |||
PRE_PACKED_STRUCTURE | |||
struct _packet_header | |||
{ | |||
char fPacketType[7]; //packet type ('headr') | |||
char fDataType; //a for audio, m for midi and s for sync | |||
char fDataStream; //s for send, r for return | |||
char fPacketType[8]; //packet type ('headr') | |||
uint32_t fDataType; //a for audio, m for midi and s for sync | |||
uint32_t fDataStream; //s for send, r for return | |||
uint32_t fID; //unique ID of the slave | |||
uint32_t fNumPacket; //number of data packets of the cycle | |||
uint32_t fPacketSize; //packet size in bytes | |||
@@ -177,7 +180,7 @@ namespace Jack | |||
uint32_t fCycle; //process cycle counter | |||
uint32_t fSubCycle; //midi/audio subcycle counter | |||
uint32_t fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n') | |||
}; | |||
} POST_PACKED_STRUCTURE; | |||
//net timebase master | |||
@@ -202,13 +205,14 @@ namespace Jack | |||
\Brief This structure contains transport data to be sent over the network | |||
*/ | |||
PRE_PACKED_STRUCTURE | |||
struct _net_transport_data | |||
{ | |||
uint32_t fNewState; //is it a state change | |||
uint32_t fTimebaseMaster; //is there a new timebase master | |||
int32_t fState; //current cycle state | |||
jack_position_t fPosition; //current cycle position | |||
}; | |||
} POST_PACKED_STRUCTURE; | |||
//midi data *********************************************************************************** | |||
@@ -400,6 +404,51 @@ namespace Jack | |||
int RenderToNetwork(int sub_cycle, uint32_t port_num); | |||
}; | |||
#endif | |||
#if HAVE_OPUS | |||
#include <opus/opus.h> | |||
#include <opus/opus_custom.h> | |||
class SERVER_EXPORT NetOpusAudioBuffer : public NetAudioBuffer | |||
{ | |||
private: | |||
OpusCustomMode** fOpusMode; | |||
OpusCustomEncoder** fOpusEncoder; | |||
OpusCustomDecoder** fOpusDecoder; | |||
unsigned short *fCompressedSizesByte; | |||
int fCompressedMaxSizeByte; | |||
int fNumPackets; | |||
size_t fLastSubPeriodBytesSize; | |||
unsigned char** fCompressedBuffer; | |||
void FreeOpus(); | |||
public: | |||
NetOpusAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps); | |||
virtual ~NetOpusAudioBuffer(); | |||
// needed size in bytes for an entire cycle | |||
size_t GetCycleSize(); | |||
// cycle duration in sec | |||
float GetCycleDuration(); | |||
int GetNumPackets(int active_ports); | |||
//jack<->buffer | |||
int RenderFromJackPorts(); | |||
void RenderToJackPorts(); | |||
//network<->buffer | |||
int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num); | |||
int RenderToNetwork(int sub_cycle, uint32_t port_num); | |||
}; | |||
#endif | |||
class SERVER_EXPORT NetIntAudioBuffer : public NetAudioBuffer | |||
@@ -58,7 +58,7 @@ class SERVER_EXPORT JackPort | |||
bool fInUse; | |||
jack_port_id_t fTied; // Locally tied source port | |||
jack_default_audio_sample_t fBuffer[BUFFER_SIZE_MAX + 4]; | |||
jack_default_audio_sample_t fBuffer[BUFFER_SIZE_MAX + 8]; | |||
bool IsUsed() const | |||
{ | |||
@@ -108,7 +108,7 @@ class SERVER_EXPORT JackPort | |||
// Since we are in shared memory, the resulting pointer cannot be cached, so align it here... | |||
jack_default_audio_sample_t* GetBuffer() | |||
{ | |||
return (jack_default_audio_sample_t*)((uintptr_t)fBuffer & ~15L) + 4; | |||
return (jack_default_audio_sample_t*)((uintptr_t)fBuffer & ~31L) + 8; | |||
} | |||
int GetRefNum() const; | |||
@@ -46,7 +46,7 @@ int JackRequestDecoder::HandleRequest(detail::JackChannelTransactionInterface* s | |||
{ | |||
JackRequest::RequestType type = (JackRequest::RequestType)type_aux; | |||
// Read data | |||
// Read data | |||
switch (type) { | |||
case JackRequest::kClientCheck: { | |||
@@ -82,7 +82,7 @@ int JackRequestDecoder::HandleRequest(detail::JackChannelTransactionInterface* s | |||
CheckRead(req, socket); | |||
res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum); | |||
CheckWriteRefNum("JackRequest::ClientClose", socket); | |||
fHandler->ClientRemove(socket, req.fRefNum); | |||
fHandler->ClientRemove(socket, req.fRefNum); | |||
// Will cause the wrapping thread to stop | |||
return -1; | |||
} | |||
@@ -134,7 +134,6 @@ fail_close1: | |||
int JackServer::Close() | |||
{ | |||
jack_log("JackServer::Close"); | |||
fEngine->NotifyQuit(); | |||
fChannel.Close(); | |||
fAudioDriver->Detach(); | |||
fAudioDriver->Close(); | |||
@@ -190,6 +189,7 @@ int JackServer::Start() | |||
int JackServer::Stop() | |||
{ | |||
jack_log("JackServer::Stop"); | |||
fEngine->NotifyQuit(); | |||
fChannel.Stop(); | |||
fEngine->ShutDown(); | |||
@@ -162,7 +162,7 @@ SERVER_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_ | |||
va_end(ap); | |||
JackGlobals::fOpenMutex->Unlock(); | |||
return res; | |||
} catch(std::bad_alloc& e) { | |||
} catch (std::bad_alloc& e) { | |||
jack_error("Memory allocation error..."); | |||
return NULL; | |||
} catch (...) { | |||
@@ -101,9 +101,7 @@ bool JackServerGlobals::Init() | |||
int client_timeout = 0; /* msecs; if zero, use period size. */ | |||
int realtime_priority = 10; | |||
int verbose_aux = 0; | |||
int do_mlock = 1; | |||
unsigned int port_max = 128; | |||
int do_unlock = 0; | |||
int temporary = 0; | |||
int opt = 0; | |||
@@ -234,14 +232,6 @@ bool JackServerGlobals::Init() | |||
port_max = (unsigned int)atol(optarg); | |||
break; | |||
case 'm': | |||
do_mlock = 0; | |||
break; | |||
case 'u': | |||
do_unlock = 1; | |||
break; | |||
case 'v': | |||
verbose_aux = 1; | |||
break; | |||
@@ -224,8 +224,6 @@ int main(int argc, char** argv) | |||
char* master_driver_name = NULL; | |||
char** master_driver_args = NULL; | |||
int master_driver_nargs = 1; | |||
int do_mlock = 1; | |||
int do_unlock = 0; | |||
int loopback = 0; | |||
bool show_version = false; | |||
jackctl_sigmask_t * sigmask; | |||
@@ -324,14 +322,6 @@ int main(int argc, char** argv) | |||
} | |||
break; | |||
case 'm': | |||
do_mlock = 0; | |||
break; | |||
case 'u': | |||
do_unlock = 1; | |||
break; | |||
case 'v': | |||
param = jackctl_get_parameter(server_parameters, "verbose"); | |||
if (param != NULL) { | |||
@@ -40,7 +40,7 @@ extern "C" | |||
* | |||
* @return NULL if unsuccessful, otherwise pointer to the internal | |||
* client name obtained from the heap via malloc(). The caller should | |||
* free() this storage when no longer needed. | |||
* jack_free() this storage when no longer needed. | |||
*/ | |||
char *jack_get_internal_client_name (jack_client_t *client, | |||
jack_intclient_t intclient); | |||
@@ -798,7 +798,7 @@ int jack_port_connected_to (const jack_port_t *port, | |||
* @return a null-terminated array of full port names to which the @a | |||
* port is connected. If none, returns NULL. | |||
* | |||
* The caller is responsible for calling jack_free(3) on any non-NULL | |||
* The caller is responsible for calling jack_free() on any non-NULL | |||
* returned value. | |||
* | |||
* @param port locally owned jack_port_t pointer. | |||
@@ -811,7 +811,7 @@ const char ** jack_port_get_connections (const jack_port_t *port) JACK_OPTIONAL_ | |||
* @return a null-terminated array of full port names to which the @a | |||
* port is connected. If none, returns NULL. | |||
* | |||
* The caller is responsible for calling jack_free(3) on any non-NULL | |||
* The caller is responsible for calling jack_free() on any non-NULL | |||
* returned value. | |||
* | |||
* This differs from jack_port_get_connections() in two important | |||
@@ -1220,7 +1220,7 @@ int jack_recompute_total_latency (jack_client_t*, jack_port_t* port) JACK_OPTION | |||
* If zero, no selection based on flags will be carried out. | |||
* | |||
* @return a NULL-terminated array of ports that match the specified | |||
* arguments. The caller is responsible for calling jack_free(3) any | |||
* arguments. The caller is responsible for calling jack_free() any | |||
* non-NULL returned value. | |||
* | |||
* @see jack_port_name_size(), jack_port_type_size() | |||
@@ -1400,7 +1400,7 @@ void jack_set_info_function (void (*func)(const char *)) JACK_OPTIONAL_WEAK_EXPO | |||
/** | |||
* The free function to be used on memory returned by jack_port_get_connections, | |||
* jack_port_get_all_connections and jack_get_ports functions. | |||
* jack_port_get_all_connections, jack_get_ports and jack_get_internal_client_name functions. | |||
* This is MANDATORY on Windows when otherwise all nasty runtime version related crashes can occur. | |||
* Developers are strongly encouraged to use this function instead of the standard "free" function in new code. | |||
* | |||
@@ -40,6 +40,7 @@ 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/) | |||
JackOpusEncoder = 3, // samples are transmitted using OPUS codec (http://www.opus-codec.org/) | |||
}; | |||
typedef struct { | |||
@@ -368,6 +368,11 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||
netj->codec_latency = 2 * lookahead; | |||
#endif | |||
} | |||
if( netj->bitdepth == OPUS_MODE ) { | |||
#if HAVE_OPUS | |||
netj->opus_mode = opus_custom_mode_create(netj->sample_rate, netj->period_size, NULL); | |||
#endif | |||
} | |||
if (netj->handle_transport_sync) | |||
jack_set_sync_callback(netj->client, (JackSyncCallback) net_driver_sync_cb, NULL); | |||
@@ -397,6 +402,11 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||
#else | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) ); | |||
#endif | |||
#endif | |||
} else if( netj->bitdepth == OPUS_MODE ) { | |||
#if HAVE_OPUS | |||
OpusCustomDecoder *decoder = opus_custom_decoder_create( netj->opus_mode, 1, NULL ); | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, decoder ); | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
@@ -448,6 +458,19 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||
CELTMode *celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); | |||
netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode ) ); | |||
#endif | |||
#endif | |||
} else if( netj->bitdepth == OPUS_MODE ) { | |||
#if HAVE_OPUS | |||
const int kbps = netj->resample_factor; | |||
jack_log( "OPUS %dkbps\n", kbps); | |||
OpusCustomMode *opus_mode = opus_custom_mode_create( netj->sample_rate, netj->period_size, NULL ); // XXX free me in the end | |||
OpusCustomEncoder *oe = opus_custom_encoder_create( opus_mode, 1, NULL ); | |||
opus_custom_encoder_ctl(oe, OPUS_SET_BITRATE(kbps*1024)); // bits per second | |||
opus_custom_encoder_ctl(oe, OPUS_SET_COMPLEXITY(10)); | |||
opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); | |||
opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_APPLICATION_RESTRICTED_LOWDELAY)); | |||
netj->playback_srcs = jack_slist_append(netj->playback_srcs, oe ); | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
@@ -492,6 +515,12 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||
CELTDecoder * decoder = node->data; | |||
celt_decoder_destroy(decoder); | |||
} else | |||
#endif | |||
#if HAVE_OPUS | |||
if ( netj->bitdepth == OPUS_MODE ) { | |||
OpusCustomDecoder * decoder = node->data; | |||
opus_custom_decoder_destroy(decoder); | |||
} else | |||
#endif | |||
{ | |||
#if HAVE_SAMPLERATE | |||
@@ -516,6 +545,12 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||
CELTEncoder * encoder = node->data; | |||
celt_encoder_destroy(encoder); | |||
} else | |||
#endif | |||
#if HAVE_OPUS | |||
if ( netj->bitdepth == OPUS_MODE ) { | |||
OpusCustomEncoder * encoder = node->data; | |||
opus_custom_encoder_destroy(encoder); | |||
} else | |||
#endif | |||
{ | |||
#if HAVE_SAMPLERATE | |||
@@ -531,6 +566,10 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||
if( netj->bitdepth == CELT_MODE ) | |||
celt_mode_destroy(netj->celt_mode); | |||
#endif | |||
#if HAVE_OPUS | |||
if( netj->bitdepth == OPUS_MODE ) | |||
opus_custom_mode_destroy(netj->opus_mode); | |||
#endif | |||
} | |||
@@ -588,7 +627,7 @@ netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | |||
netj->client = client; | |||
if ((bitdepth != 0) && (bitdepth != 8) && (bitdepth != 16) && (bitdepth != CELT_MODE)) { | |||
if ((bitdepth != 0) && (bitdepth != 8) && (bitdepth != 16) && (bitdepth != CELT_MODE) && (bitdepth != OPUS_MODE)) { | |||
jack_info ("Invalid bitdepth: %d (8, 16 or 0 for float) !!!", bitdepth); | |||
return NULL; | |||
} | |||
@@ -755,6 +794,11 @@ netjack_startup( netjack_driver_state_t *netj ) | |||
netj->net_period_down = netj->resample_factor; | |||
netj->net_period_up = netj->resample_factor_up; | |||
} else if( netj->bitdepth == OPUS_MODE ) { | |||
// Opus mode. | |||
// TODO: this is a hack. But i dont want to change the packet header, either | |||
netj->net_period_down = (netj->resample_factor * netj->period_size * 1024 / netj->sample_rate / 8) & (~1); | |||
netj->net_period_up = (netj->resample_factor_up * netj->period_size * 1024 / netj->sample_rate / 8) & (~1); | |||
} else { | |||
netj->net_period_down = (float) netj->period_size / (float) netj->resample_factor; | |||
netj->net_period_up = (float) netj->period_size / (float) netj->resample_factor_up; | |||
@@ -32,6 +32,11 @@ | |||
#include <celt/celt.h> | |||
#endif | |||
#if HAVE_OPUS | |||
#include <opus/opus.h> | |||
#include <opus/opus_custom.h> | |||
#endif | |||
#ifdef __cplusplus | |||
extern "C" | |||
{ | |||
@@ -111,6 +116,9 @@ extern "C" | |||
struct _packet_cache * packcache; | |||
#if HAVE_CELT | |||
CELTMode *celt_mode; | |||
#endif | |||
#if HAVE_OPUS | |||
OpusCustomMode* opus_mode; | |||
#endif | |||
}; | |||
@@ -72,6 +72,11 @@ | |||
#include <celt/celt.h> | |||
#endif | |||
#if HAVE_OPUS | |||
#include <opus/opus.h> | |||
#include <opus/opus_custom.h> | |||
#endif | |||
#include "netjack_packet.h" | |||
#include "JackError.h" | |||
@@ -129,6 +134,8 @@ int get_sample_size (int bitdepth) | |||
//JN: if the former, why not int16_t, if the latter, shouldn't it depend on -c N? | |||
if( bitdepth == CELT_MODE ) | |||
return sizeof( unsigned char ); | |||
if( bitdepth == OPUS_MODE ) | |||
return sizeof( unsigned char ); | |||
return sizeof (int32_t); | |||
} | |||
@@ -1347,6 +1354,91 @@ render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs | |||
} | |||
#endif | |||
#if HAVE_OPUS | |||
#define CDO (sizeof(short)) ///< compressed data offset (first 2 bytes are length) | |||
// render functions for Opus. | |||
void | |||
render_payload_to_jack_ports_opus (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes) | |||
{ | |||
int chn = 0; | |||
JSList *node = capture_ports; | |||
JSList *src_node = capture_srcs; | |||
unsigned char *packet_bufX = (unsigned char *)packet_payload; | |||
while (node != NULL) { | |||
jack_port_t *port = (jack_port_t *) node->data; | |||
jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) { | |||
// audio port, decode opus data. | |||
OpusCustomDecoder *decoder = (OpusCustomDecoder*) src_node->data; | |||
if( !packet_payload ) | |||
memset(buf, 0, nframes * sizeof(float)); | |||
else { | |||
unsigned short len; | |||
memcpy(&len, packet_bufX, CDO); | |||
len = ntohs(len); | |||
opus_custom_decode_float( decoder, packet_bufX + CDO, len, buf, nframes ); | |||
} | |||
src_node = jack_slist_next (src_node); | |||
} else if (jack_port_is_midi (porttype)) { | |||
// midi port, decode midi events | |||
// convert the data buffer to a standard format (uint32_t based) | |||
unsigned int buffer_size_uint32 = net_period_down / 2; | |||
uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | |||
if( packet_payload ) | |||
decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | |||
} | |||
packet_bufX = (packet_bufX + net_period_down); | |||
node = jack_slist_next (node); | |||
chn++; | |||
} | |||
} | |||
void | |||
render_jack_ports_to_payload_opus (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up) | |||
{ | |||
int chn = 0; | |||
JSList *node = playback_ports; | |||
JSList *src_node = playback_srcs; | |||
unsigned char *packet_bufX = (unsigned char *)packet_payload; | |||
while (node != NULL) { | |||
jack_port_t *port = (jack_port_t *) node->data; | |||
jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) { | |||
// audio port, encode opus data. | |||
int encoded_bytes; | |||
float *floatbuf = alloca (sizeof(float) * nframes ); | |||
memcpy( floatbuf, buf, nframes * sizeof(float) ); | |||
OpusCustomEncoder *encoder = (OpusCustomEncoder*) src_node->data; | |||
encoded_bytes = opus_custom_encode_float( encoder, floatbuf, nframes, packet_bufX + CDO, net_period_up - CDO ); | |||
unsigned short len = htons(encoded_bytes); | |||
memcpy(packet_bufX, &len, CDO); | |||
src_node = jack_slist_next( src_node ); | |||
} else if (jack_port_is_midi (porttype)) { | |||
// encode midi events from port to packet | |||
// convert the data buffer to a standard format (uint32_t based) | |||
unsigned int buffer_size_uint32 = net_period_up / 2; | |||
uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | |||
encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | |||
} | |||
packet_bufX = (packet_bufX + net_period_up); | |||
node = jack_slist_next (node); | |||
chn++; | |||
} | |||
} | |||
#endif | |||
/* Wrapper functions with bitdepth argument... */ | |||
void | |||
render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats) | |||
@@ -1358,6 +1450,10 @@ render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t | |||
#if HAVE_CELT | |||
else if (bitdepth == CELT_MODE) | |||
render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes); | |||
#endif | |||
#if HAVE_OPUS | |||
else if (bitdepth == OPUS_MODE) | |||
render_payload_to_jack_ports_opus (packet_payload, net_period_down, capture_ports, capture_srcs, nframes); | |||
#endif | |||
else | |||
render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats); | |||
@@ -1373,6 +1469,10 @@ render_jack_ports_to_payload (int bitdepth, JSList *playback_ports, JSList *play | |||
#if HAVE_CELT | |||
else if (bitdepth == CELT_MODE) | |||
render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up); | |||
#endif | |||
#if HAVE_OPUS | |||
else if (bitdepth == OPUS_MODE) | |||
render_jack_ports_to_payload_opus (playback_ports, playback_srcs, nframes, packet_payload, net_period_up); | |||
#endif | |||
else | |||
render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats); | |||
@@ -40,6 +40,7 @@ extern "C" | |||
// The Packet Header. | |||
#define CELT_MODE 1000 // Magic bitdepth value that indicates CELT compression | |||
#define OPUS_MODE 999 // Magic bitdepth value that indicates OPUS compression | |||
#define MASTER_FREEWHEELS 0x80000000 | |||
typedef struct _jacknet_packet_header jacknet_packet_header; | |||
@@ -5,6 +5,7 @@ | |||
* - common (interface-independent) code | |||
* - POSIX implementation | |||
* - System V implementation | |||
* - Windows implementation | |||
* | |||
* The implementation used is determined by whether USE_POSIX_SHM was | |||
* set in the ./configure step. | |||
@@ -12,7 +13,8 @@ | |||
/* | |||
Copyright (C) 2001-2003 Paul Davis | |||
Copyright (C) 2005-2012 Grame | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
@@ -1167,7 +1169,7 @@ jack_access_registry (jack_shm_info_t *ri) | |||
} | |||
} | |||
if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) { | |||
if ((ri->ptr.attached_at = shmat (registry_id, 0, 0)) < 0) { | |||
jack_error ("Cannot attach shm registry segment (%s)", | |||
strerror (errno)); | |||
return EINVAL; | |||
@@ -1175,7 +1177,7 @@ jack_access_registry (jack_shm_info_t *ri) | |||
/* set up global pointers */ | |||
ri->index = JACK_SHM_REGISTRY_INDEX; | |||
jack_shm_header = ri->attached_at; | |||
jack_shm_header = ri->ptr.attached_at; | |||
jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); | |||
return 0; | |||
} | |||
@@ -1199,7 +1201,7 @@ jack_create_registry (jack_shm_info_t *ri) | |||
return errno; | |||
} | |||
if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) { | |||
if ((ri->ptr.attached_at = shmat (registry_id, 0, 0)) < 0) { | |||
jack_error ("Cannot attach shm registry segment (%s)", | |||
strerror (errno)); | |||
return EINVAL; | |||
@@ -1207,7 +1209,7 @@ jack_create_registry (jack_shm_info_t *ri) | |||
/* set up global pointers */ | |||
ri->index = JACK_SHM_REGISTRY_INDEX; | |||
jack_shm_header = ri->attached_at; | |||
jack_shm_header = ri->ptr.attached_at; | |||
jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); | |||
/* initialize registry contents */ | |||
@@ -1226,8 +1228,8 @@ void | |||
jack_release_shm (jack_shm_info_t* si) | |||
{ | |||
/* registry may or may not be locked */ | |||
if (si->attached_at != MAP_FAILED) { | |||
shmdt (si->attached_at); | |||
if (si->ptr.attached_at != MAP_FAILED) { | |||
shmdt (si->ptr.attached_at); | |||
} | |||
} | |||
@@ -1261,7 +1263,7 @@ jack_shmalloc (const char* name_not_used, jack_shmsize_t size, | |||
registry->id = shmid; | |||
registry->allocator = getpid(); | |||
si->index = registry->index; | |||
si->attached_at = MAP_FAILED; /* not attached */ | |||
si->ptr.attached_at = MAP_FAILED; /* not attached */ | |||
rc = 0; | |||
} else { | |||
@@ -1277,7 +1279,19 @@ jack_shmalloc (const char* name_not_used, jack_shmsize_t size, | |||
int | |||
jack_attach_shm (jack_shm_info_t* si) | |||
{ | |||
if ((si->attached_at = shmat (jack_shm_registry[si->index].id, 0, 0)) < 0) { | |||
if ((si->ptr.attached_at = shmat (jack_shm_registry[si->index].id, 0, 0)) < 0) { | |||
jack_error ("Cannot attach shm segment (%s)", | |||
strerror (errno)); | |||
jack_release_shm_info (si->index); | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
int | |||
jack_attach_shm_read (jack_shm_info_t* si) | |||
{ | |||
if ((si->ptr.attached_at = shmat (jack_shm_registry[si->index].id, 0, SHM_RDONLY)) < 0) { | |||
jack_error ("Cannot attach shm segment (%s)", | |||
strerror (errno)); | |||
jack_release_shm_info (si->index); | |||
@@ -1,3 +1,36 @@ | |||
/* This module provides a set of abstract shared memory interfaces | |||
* with support using both System V and POSIX shared memory | |||
* implementations. The code is divided into three sections: | |||
* | |||
* - common (interface-independent) code | |||
* - POSIX implementation | |||
* - System V implementation | |||
* - Windows implementation | |||
* | |||
* The implementation used is determined by whether USE_POSIX_SHM was | |||
* set in the ./configure step. | |||
*/ | |||
/* | |||
Copyright (C) 2001-2003 Paul Davis | |||
Copyright (C) 2005-2012 Grame | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#ifndef __jack_shm_h__ | |||
#define __jack_shm_h__ | |||
@@ -38,7 +71,7 @@ extern "C" | |||
typedef char shm_name_t[SHM_NAME_MAX]; | |||
typedef shm_name_t jack_shm_id_t; | |||
#elif WIN32 // TO CHECK | |||
#elif WIN32 | |||
#define NAME_MAX 255 | |||
#ifndef SHM_NAME_MAX | |||
#define SHM_NAME_MAX NAME_MAX | |||
@@ -68,7 +68,7 @@ def build(bld): | |||
] | |||
includes = ['.', './jack', '..'] | |||
uselib = ["PTHREAD", "CELT"] | |||
uselib = ["PTHREAD", "CELT", "OPUS"] | |||
if bld.env['IS_LINUX']: | |||
common_libsources += [ | |||
@@ -193,7 +193,7 @@ def build(bld): | |||
netlib.includes = includes | |||
netlib.name = 'netlib' | |||
netlib.target = 'jacknet' | |||
netlib.use = ['SAMPLERATE', 'CELT', 'PTHREAD' , 'RT'] | |||
netlib.use = ['SAMPLERATE', 'CELT', 'OPUS', 'PTHREAD' , 'RT'] | |||
netlib.install_path = '${LIBDIR}' | |||
netlib.source = [ | |||
'JackNetAPI.cpp', | |||
@@ -226,7 +226,7 @@ def build(bld): | |||
clientlib.defines = 'HAVE_CONFIG_H' | |||
clientlib.use = uselib | |||
clientlib.install_path = '${LIBDIR}' | |||
if bld.env['BUILD_JACKDBUS'] == True and bld.env['BUILD_JACKD'] == False: | |||
if bld.env['AUTOSTART_METHOD'] == "dbus": | |||
clientlib.use.append('DBUS-1') | |||
clientlib.includes = includes | |||
clientlib.name = 'clientlib' | |||
@@ -76,6 +76,8 @@ SERVER_EXPORT bool audio_acquire(const char * device_name) | |||
assert(gReserveCount < DEVICE_MAX); | |||
dbus_error_init(&error); | |||
if ((ret= rd_acquire( | |||
&gReservedDevice[gReserveCount].reserved_device, | |||
gConnection, | |||
@@ -86,6 +88,7 @@ SERVER_EXPORT bool audio_acquire(const char * device_name) | |||
&error)) < 0) { | |||
jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret))); | |||
dbus_error_free(&error); | |||
return false; | |||
} | |||
@@ -377,6 +377,8 @@ on_device_acquire(const char * device_name) | |||
int ret; | |||
DBusError error; | |||
dbus_error_init(&error); | |||
ret = rd_acquire( | |||
&g_reserved_device[g_device_count].reserved_device, | |||
g_connection, | |||
@@ -388,6 +390,7 @@ on_device_acquire(const char * device_name) | |||
if (ret < 0) | |||
{ | |||
jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret))); | |||
dbus_error_free(&error); | |||
return false; | |||
} | |||
@@ -31,6 +31,11 @@ | |||
#include <stdint.h> | |||
#include "reserve.h" | |||
#include "jack/control.h" | |||
#define RESERVE_ERROR_NO_MEMORY "org.freedesktop.ReserveDevice1.Error.NoMemory" | |||
#define RESERVE_ERROR_PROTOCOL_VIOLATION "org.freedesktop.ReserveDevice1.Error.Protocol" | |||
#define RESERVE_ERROR_RELEASE_DENIED "org.freedesktop.ReserveDevice1.Error.ReleaseDenied" | |||
struct rd_device { | |||
int ref; | |||
@@ -371,34 +376,51 @@ int rd_acquire( | |||
dbus_bool_t good; | |||
vtable.message_function = object_handler; | |||
if (!error) | |||
if (!error) { | |||
error = &_error; | |||
dbus_error_init(error); | |||
} | |||
dbus_error_init(error); | |||
if (!_d) | |||
return -EINVAL; | |||
if (!_d) { | |||
assert(0); | |||
r = -EINVAL; | |||
goto fail; | |||
} | |||
if (!connection) | |||
return -EINVAL; | |||
if (!connection) { | |||
assert(0); | |||
r = -EINVAL; | |||
goto fail; | |||
} | |||
if (!device_name) | |||
return -EINVAL; | |||
if (!device_name) { | |||
assert(0); | |||
r = -EINVAL; | |||
goto fail; | |||
} | |||
if (!request_cb && priority != INT32_MAX) | |||
return -EINVAL; | |||
if (!request_cb && priority != INT32_MAX) { | |||
assert(0); | |||
r = -EINVAL; | |||
goto fail; | |||
} | |||
if (!(d = (rd_device *)calloc(sizeof(rd_device), 1))) | |||
return -ENOMEM; | |||
if (!(d = (rd_device *)calloc(sizeof(rd_device), 1))) { | |||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot allocate memory for rd_device struct"); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
d->ref = 1; | |||
if (!(d->device_name = strdup(device_name))) { | |||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot duplicate device name string"); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
if (!(d->application_name = strdup(application_name))) { | |||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot duplicate application name string"); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
@@ -408,12 +430,14 @@ int rd_acquire( | |||
d->request_cb = request_cb; | |||
if (!(d->service_name = (char*)malloc(sizeof(SERVICE_PREFIX) + strlen(device_name)))) { | |||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot allocate memory for service name string"); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
sprintf(d->service_name, SERVICE_PREFIX "%s", d->device_name); | |||
if (!(d->object_path = (char*)malloc(sizeof(OBJECT_PREFIX) + strlen(device_name)))) { | |||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot allocate memory for object path string"); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
@@ -425,20 +449,28 @@ int rd_acquire( | |||
DBUS_NAME_FLAG_DO_NOT_QUEUE| | |||
(priority < INT32_MAX ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT : 0), | |||
error)) < 0) { | |||
jack_error("dbus_bus_request_name() failed. (1)"); | |||
r = -EIO; | |||
goto fail; | |||
} | |||
if (k == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER || k == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER) | |||
switch (k) { | |||
case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: | |||
case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: | |||
goto success; | |||
if (k != DBUS_REQUEST_NAME_REPLY_EXISTS) { | |||
case DBUS_REQUEST_NAME_REPLY_EXISTS: | |||
break; | |||
case DBUS_REQUEST_NAME_REPLY_IN_QUEUE : /* DBUS_NAME_FLAG_DO_NOT_QUEUE was specified */ | |||
default: /* unknown reply returned */ | |||
jack_error("request name reply with unexpected value %d.", k); | |||
assert(0); | |||
r = -EIO; | |||
goto fail; | |||
} | |||
if (priority <= INT32_MIN) { | |||
r = -EBUSY; | |||
dbus_set_error(error, RESERVE_ERROR_RELEASE_DENIED, "Device reservation request with priority %"PRIi32" denied for \"%s\"", priority, device_name); | |||
goto fail; | |||
} | |||
@@ -447,6 +479,7 @@ int rd_acquire( | |||
d->object_path, | |||
"org.freedesktop.ReserveDevice1", | |||
"RequestRelease"))) { | |||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot allocate memory for RequestRelease method call"); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
@@ -455,6 +488,7 @@ int rd_acquire( | |||
m, | |||
DBUS_TYPE_INT32, &d->priority, | |||
DBUS_TYPE_INVALID)) { | |||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot append args for RequestRelease method call"); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
@@ -469,10 +503,12 @@ int rd_acquire( | |||
dbus_error_has_name(error, DBUS_ERROR_UNKNOWN_METHOD) || | |||
dbus_error_has_name(error, DBUS_ERROR_NO_REPLY)) { | |||
/* This must be treated as denied. */ | |||
jack_info("Device reservation request with priority %"PRIi32" denied for \"%s\": %s (%s)", priority, device_name, error->name, error->message); | |||
r = -EBUSY; | |||
goto fail; | |||
} | |||
jack_error("dbus_connection_send_with_reply_and_block(RequestRelease) failed."); | |||
r = -EIO; | |||
goto fail; | |||
} | |||
@@ -482,11 +518,13 @@ int rd_acquire( | |||
error, | |||
DBUS_TYPE_BOOLEAN, &good, | |||
DBUS_TYPE_INVALID)) { | |||
jack_error("RequestRelease() reply is invalid."); | |||
r = -EIO; | |||
goto fail; | |||
} | |||
if (!good) { | |||
dbus_set_error(error, RESERVE_ERROR_RELEASE_DENIED, "Device reservation request with priority %"PRIi32" denied for \"%s\" via RequestRelease()", priority, device_name); | |||
r = -EBUSY; | |||
goto fail; | |||
} | |||
@@ -498,11 +536,14 @@ int rd_acquire( | |||
(priority < INT32_MAX ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT : 0)| | |||
DBUS_NAME_FLAG_REPLACE_EXISTING, | |||
error)) < 0) { | |||
jack_error("dbus_bus_request_name() failed. (2)"); | |||
r = -EIO; | |||
goto fail; | |||
} | |||
if (k != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { | |||
/* this is racy, another contender may have acquired the device */ | |||
dbus_set_error(error, RESERVE_ERROR_PROTOCOL_VIOLATION, "request name reply is not DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER but %d.", k); | |||
r = -EIO; | |||
goto fail; | |||
} | |||
@@ -510,11 +551,13 @@ int rd_acquire( | |||
success: | |||
d->owning = 1; | |||
if (!(dbus_connection_register_object_path( | |||
if (!(dbus_connection_try_register_object_path( | |||
d->connection, | |||
d->object_path, | |||
&vtable, | |||
d))) { | |||
d, | |||
error))) { | |||
jack_error("cannot register object path \"%s\": %s", d->object_path, error->message); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
@@ -526,6 +569,7 @@ success: | |||
filter_handler, | |||
d, | |||
NULL)) { | |||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot add filter"); | |||
r = -ENOMEM; | |||
goto fail; | |||
} | |||
@@ -107,7 +107,9 @@ static void signal_segv(int signum, siginfo_t* info, void*ptr) { | |||
#if !defined(__alpha__) && !defined(__ia64__) && !defined(__FreeBSD_kernel__) && !defined(__arm__) && !defined(__hppa__) && !defined(__sh__) | |||
for(i = 0; i < NGREG; i++) | |||
jack_error("reg[%02d] = 0x" REGFORMAT, i, | |||
#if defined(__powerpc__) | |||
#if defined(__powerpc64__) | |||
ucontext->uc_mcontext.gp_regs[i] | |||
#elif defined(__powerpc__) | |||
ucontext->uc_mcontext.uc_regs[i] | |||
#elif defined(__sparc__) && defined(__arch64__) | |||
ucontext->uc_mcontext.mc_gregs[i] | |||
@@ -177,7 +179,9 @@ int setup_sigsegv() { | |||
memset(&action, 0, sizeof(action)); | |||
action.sa_sigaction = signal_segv; | |||
#ifdef SA_SIGINFO | |||
action.sa_flags = SA_SIGINFO; | |||
#endif | |||
if(sigaction(SIGSEGV, &action, NULL) < 0) { | |||
jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno)); | |||
return 0; | |||
@@ -67,7 +67,7 @@ def build(bld): | |||
] | |||
obj.use = ['serverlib'] | |||
if bld.env['IS_LINUX']: | |||
obj.use += ['PTHREAD', 'DL', 'RT', 'DBUS-1', 'EXPAT'] | |||
obj.use += ['PTHREAD', 'DL', 'RT', 'DBUS-1', 'EXPAT', 'STDC++'] | |||
if bld.env['IS_MACOSX']: | |||
obj.use += ['PTHREAD', 'DL', 'DBUS-1', 'EXPAT'] | |||
obj.target = 'jackdbus' | |||
@@ -27,7 +27,7 @@ static int Jack_Graph_Order_Callback(void *arg) | |||
for (i = 0; ports[i]; ++i) { | |||
printf("name: %s\n", ports[i]); | |||
} | |||
free(ports); | |||
jack_free(ports); | |||
} | |||
ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); | |||
@@ -35,7 +35,7 @@ static int Jack_Graph_Order_Callback(void *arg) | |||
for (i = 0; ports[i]; ++i) { | |||
printf("name: %s\n", ports[i]); | |||
} | |||
free(ports); | |||
jack_free(ports); | |||
} | |||
return 0; | |||
@@ -116,17 +116,20 @@ def main(): | |||
print " dp - get parameters of currently selected driver" | |||
print " dpd <param> - get long description for driver parameter" | |||
print " dps <param> <value> - set driver parameter" | |||
print " dpr <param> - reset driver parameter to its default value" | |||
print " asd <driver> - add slave driver" | |||
print " rsd <driver> - remove slave driver" | |||
print " il - get list of available internals" | |||
print " ip <name> - get parameters of given internal" | |||
print " ipd <name> <param> - get long description for internal parameter" | |||
print " ips <name> <param> <value> - set internal parameter" | |||
print " ipr <name> <param> - reset internal parameter to its default value" | |||
print " iload <name> - load internal" | |||
print " iunload <name> - unload internal" | |||
print " ep - get engine parameters" | |||
print " epd <param> - get long description for engine parameter" | |||
print " eps <param> <value> - set engine parameter" | |||
print " epr <param> - reset engine parameter to its default value" | |||
sys.exit(0) | |||
bus = dbus.SessionBus() | |||
@@ -213,6 +216,16 @@ def main(): | |||
type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['driver', param]) | |||
configure_iface.SetParameterValue(['driver', param], python_type_to_jackdbus_type(value, type_char)) | |||
elif arg == 'dpr': | |||
if index >= len(sys.argv): | |||
print "driver parameter reset command requires parameter name argument" | |||
sys.exit() | |||
param = sys.argv[index] | |||
index += 1 | |||
print "--- driver param reset \"%s\"" % param | |||
configure_iface.ResetParameterValue(['driver', param]) | |||
elif arg == 'ep': | |||
print "--- get engine parameters (type:isset:default:value)" | |||
get_parameters(configure_iface, ['engine']) | |||
@@ -242,6 +255,18 @@ def main(): | |||
type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['engine', param]) | |||
configure_iface.SetParameterValue(['engine', param], python_type_to_jackdbus_type(value, type_char)) | |||
elif arg == 'epr': | |||
if index >= len(sys.argv): | |||
print "engine parameter reset command requires parameter name" | |||
sys.exit() | |||
param = sys.argv[index] | |||
index += 1 | |||
print "--- engine param reset \"%s\"" % param | |||
type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['engine', param]) | |||
configure_iface.ResetParameterValue(['engine', param]) | |||
elif arg == 'il': | |||
print "--- internals list" | |||
is_leaf, internals = configure_iface.ReadContainer(['internals']) | |||
@@ -273,7 +298,7 @@ def main(): | |||
print long_descr | |||
elif arg == 'ips': | |||
if index + 2 >= len(sys.argv): | |||
print "get internal parameter long description command requires internal, parameter name and value arguments" | |||
print "internal parameter set command requires internal, parameter name and value arguments" | |||
sys.exit() | |||
internal_name = sys.argv[index] | |||
@@ -287,6 +312,19 @@ def main(): | |||
type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['internals', internal_name, param]) | |||
configure_iface.SetParameterValue(['internals', internal_name, param], python_type_to_jackdbus_type(value, type_char)) | |||
elif arg == 'ipr': | |||
if index + 1 >= len(sys.argv): | |||
print "reset internal parameter command requires internal and parameter name arguments" | |||
sys.exit() | |||
internal_name = sys.argv[index] | |||
index += 1 | |||
param = sys.argv[index] | |||
index += 1 | |||
print "--- internal param reset \"%s\"" % param | |||
configure_iface.ResetParameterValue(['internals', internal_name, param]) | |||
elif arg == 'iload': | |||
print "--- load internal" | |||
@@ -154,7 +154,7 @@ main (int argc, char *argv[]) | |||
{0, 0, 0, 0} | |||
}; | |||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | |||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != -1) { | |||
switch (opt) { | |||
case 'f': | |||
if ((freq = atoi (optarg)) <= 0) { | |||
@@ -73,7 +73,7 @@ main (int argc, char *argv[]) | |||
{0, 0, 0, 0} | |||
}; | |||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | |||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != -1) { | |||
switch (opt) { | |||
@@ -62,6 +62,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include <celt/celt.h> | |||
#endif | |||
#if HAVE_OPUS | |||
#include <opus/opus.h> | |||
#include <opus/opus_custom.h> | |||
#endif | |||
#include <math.h> | |||
JSList *capture_ports = NULL; | |||
@@ -147,6 +152,16 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int | |||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), 1, jack_get_buffer_size(client), NULL ); | |||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) ); | |||
#endif | |||
#endif | |||
} else if (bitdepth == 999) { | |||
#if HAVE_OPUS | |||
int err; | |||
OpusCustomMode *opus_mode = opus_custom_mode_create(jack_get_sample_rate( client ), jack_get_buffer_size(client), &err); | |||
if (err != OPUS_OK) { printf("OPUS MODE FAILED\n"); } | |||
OpusCustomDecoder *decoder = opus_custom_decoder_create(opus_mode, 1, &err); | |||
if (err != OPUS_OK) { printf("OPUS DECODER FAILED\n"); } | |||
opus_custom_decoder_init(decoder, opus_mode, 1); | |||
capture_srcs = jack_slist_append(capture_srcs, decoder); | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
@@ -189,6 +204,22 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int | |||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), 1, jack_get_buffer_size(client), NULL ); | |||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) ); | |||
#endif | |||
#endif | |||
} else if( bitdepth == 999 ) { | |||
#if HAVE_OPUS | |||
const int kbps = factor; | |||
printf("new opus encoder %d kbps\n", kbps); | |||
int err; | |||
OpusCustomMode *opus_mode = opus_custom_mode_create(jack_get_sample_rate (client), jack_get_buffer_size(client), &err ); // XXX free me | |||
if (err != OPUS_OK) { printf("OPUS MODE FAILED\n"); } | |||
OpusCustomEncoder *oe = opus_custom_encoder_create( opus_mode, 1, &err ); | |||
if (err != OPUS_OK) { printf("OPUS ENCODER FAILED\n"); } | |||
opus_custom_encoder_ctl(oe, OPUS_SET_BITRATE(kbps*1024)); // bits per second | |||
opus_custom_encoder_ctl(oe, OPUS_SET_COMPLEXITY(10)); | |||
opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); | |||
opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_APPLICATION_RESTRICTED_LOWDELAY)); | |||
opus_custom_encoder_init(oe, opus_mode, 1); | |||
playback_srcs = jack_slist_append(playback_srcs, oe); | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
@@ -269,7 +300,7 @@ process (jack_nframes_t nframes, void *arg) | |||
uint32_t *rx_packet_ptr; | |||
jack_time_t packet_recv_timestamp; | |||
if( bitdepth == 1000 ) | |||
if( bitdepth == 1000 || bitdepth == 999) | |||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ; | |||
else | |||
net_period = (float) nframes / (float) factor; | |||
@@ -519,6 +550,7 @@ printUsage () | |||
" -B <bind port> - reply port, for use in NAT environments\n" | |||
" -b <bitdepth> - Set transport to use 16bit or 8bit\n" | |||
" -c <kbits> - Use CELT encoding with <kbits> kbits per channel\n" | |||
" -P <kbits> - Use Opus encoding with <kbits> kbits per channel\n" | |||
" -m <mtu> - Assume this mtu for the link\n" | |||
" -R <N> - Redundancy: send out packets N times.\n" | |||
" -e - skip host-to-network endianness conversion\n" | |||
@@ -564,7 +596,7 @@ main (int argc, char *argv[]) | |||
sprintf(client_name, "netjack"); | |||
sprintf(peer_ip, "localhost"); | |||
while ((c = getopt (argc, argv, ":h:H:o:i:O:I:n:p:r:B:b:c:m:R:e:N:s:")) != -1) { | |||
while ((c = getopt (argc, argv, ":h:H:o:i:O:I:n:p:r:B:b:c:m:R:e:N:s:P:")) != -1) { | |||
switch (c) { | |||
case 'h': | |||
printUsage(); | |||
@@ -613,6 +645,15 @@ main (int argc, char *argv[]) | |||
#else | |||
printf( "not built with celt support\n" ); | |||
exit(10); | |||
#endif | |||
break; | |||
case 'P': | |||
#if HAVE_OPUS | |||
bitdepth = 999; | |||
factor = atoi (optarg); | |||
#else | |||
printf( "not built with opus support\n" ); | |||
exit(10); | |||
#endif | |||
break; | |||
case 'm': | |||
@@ -689,7 +730,7 @@ main (int argc, char *argv[]) | |||
alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi); | |||
if( bitdepth == 1000 ) | |||
if( bitdepth == 1000 || bitdepth == 999) | |||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ; | |||
else | |||
net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor); | |||
@@ -153,9 +153,10 @@ int main(int argc, char *argv[]) | |||
struct option long_options[] = { | |||
{"driver", 1, 0, 'd'}, | |||
{"client", 1, 0, 'c'}, | |||
{0, 0, 0, 0} | |||
}; | |||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | |||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != -1) { | |||
switch (opt) { | |||
case 'd': | |||
driver_name = optarg; | |||
@@ -191,7 +191,7 @@ main (int argc, char *argv[]) | |||
fprintf (stderr, "cannot connect output ports\n"); | |||
} | |||
free (ports); | |||
jack_free (ports); | |||
/* install a signal handler to properly quits jack client */ | |||
#ifdef WIN32 | |||
@@ -231,7 +231,7 @@ main (int argc, char *argv[]) | |||
fprintf (stderr, "cannot connect input ports\n"); | |||
} | |||
free (ports); | |||
jack_free (ports); | |||
ports = jack_get_ports (client, NULL, NULL, | |||
JackPortIsPhysical|JackPortIsInput); | |||
@@ -244,7 +244,7 @@ main (int argc, char *argv[]) | |||
fprintf (stderr, "cannot connect output ports\n"); | |||
} | |||
free (ports); | |||
jack_free (ports); | |||
/* install a signal handler to properly quits jack client */ | |||
signal(SIGQUIT, signal_handler); | |||
@@ -50,7 +50,7 @@ def configure(conf): | |||
#if conf.is_defined('HAVE_READLINE'): | |||
# conf.env['LIB_READLINE'] = ['readline'] | |||
conf.env['BUILD_EXAMPLE_CLIENT_TRANSPORT'] = bool(conf.env['LIB_READLINE']) and bool(conf.env['LIB_NCURSES']) | |||
conf.env['BUILD_EXAMPLE_CLIENT_TRANSPORT'] = bool(conf.env['LIB_READLINE']) | |||
conf.env['BUILD_EXAMPLE_CLIENT_REC'] = conf.is_defined('HAVE_SNDFILE') | |||
@@ -65,7 +65,7 @@ def build(bld): | |||
os_incdir = ['../solaris', '../posix'] | |||
for example_program, example_program_source in list(example_programs.items()): | |||
if example_program == 'jack_server_control': | |||
use = ['serverlib'] | |||
use = ['serverlib', 'STDC++'] | |||
elif example_program == 'jack_net_slave': | |||
if not bld.env['BUILD_NETLIB']: | |||
continue | |||
@@ -86,10 +86,9 @@ def build(bld): | |||
#prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
prog.env.append_value("LINKFLAGS", "") | |||
if bld.env['IS_LINUX']: | |||
prog.use += ['RT'] | |||
prog.env.append_value("LINKFLAGS", "-lm") | |||
prog.use += ['RT', 'M'] | |||
if bld.env['IS_SUN']: | |||
prog.env.append_value("LINKFLAGS", "-lm") | |||
prog.use += ['M'] | |||
prog.target = example_program | |||
@@ -103,9 +102,9 @@ def build(bld): | |||
#prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
prog.env.append_value("LINKFLAGS", "") | |||
if bld.env['IS_LINUX']: | |||
prog.use += ['RT', 'READLINE', 'NCURSES'] | |||
prog.use += ['RT', 'READLINE'] | |||
if bld.env['IS_MACOSX']: | |||
prog.use += ['READLINE', 'NCURSES'] | |||
prog.use += ['READLINE'] | |||
prog.target = 'jack_transport' | |||
if bld.env['BUILD_EXAMPLE_CLIENT_REC']: | |||
@@ -126,26 +125,26 @@ def build(bld): | |||
if bld.env['IS_LINUX'] or bld.env['IS_MACOSX']: | |||
prog = bld(features = 'c cprogram') | |||
prog.includes = os_incdir + ['../common/jack', '../common'] | |||
prog.includes = os_incdir + ['.', '..', '../common/jack', '../common'] | |||
prog.source = ['netsource.c', '../common/netjack_packet.c'] | |||
prog.env.append_value("CFLAGS", "-DNO_JACK_ERROR") | |||
prog.use = ['CELT', 'SAMPLERATE'] | |||
prog.use = ['clientlib'] | |||
prog.use = ['CELT', 'SAMPLERATE', 'OPUS', 'M', 'clientlib'] | |||
prog.target = 'jack_netsource' | |||
prog.defines = ['HAVE_CONFIG_H'] | |||
if bld.env['IS_LINUX'] and bld.env['BUILD_EXAMPLE_ALSA_IO']: | |||
prog = bld(features = 'c cprogram') | |||
prog.includes = os_incdir + ['../common/jack', '../common'] | |||
prog.source = ['alsa_in.c', '../common/memops.c'] | |||
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR") | |||
prog.use = ['clientlib', 'ALSA', 'SAMPLERATE'] | |||
prog.env.append_value("CFLAGS", "-DNO_JACK_ERROR") | |||
prog.use = ['clientlib', 'ALSA', 'SAMPLERATE', 'M'] | |||
prog.target = 'alsa_in' | |||
prog = bld(features = 'c cprogram') | |||
prog.includes = os_incdir + ['../common/jack', '../common'] | |||
prog.source = ['alsa_out.c', '../common/memops.c'] | |||
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR") | |||
prog.use = ['clientlib', 'ALSA', 'SAMPLERATE'] | |||
prog.env.append_value("CFLAGS", "-DNO_JACK_ERROR") | |||
prog.use = ['clientlib', 'ALSA', 'SAMPLERATE', 'M'] | |||
prog.target = 'alsa_out' | |||
for example_lib, example_lib_source in list(example_libs.items()): | |||
@@ -54,8 +54,14 @@ namespace Jack | |||
fPlaybackChannels = param->value.ui; | |||
break; | |||
case 'C': | |||
if (strncmp(param->value.str,"none",4) != 0) { | |||
fAudioInterface.fCaptureName = strdup ( param->value.str ); | |||
} | |||
break; | |||
case 'P': | |||
if (strncmp(param->value.str,"none",4) != 0) { | |||
fAudioInterface.fPlaybackName = strdup ( param->value.str ); | |||
} | |||
break; | |||
case 'D': | |||
break; | |||
@@ -130,6 +130,8 @@ namespace Jack | |||
snd_pcm_access_t fSampleAccess; | |||
//channels | |||
const char* fCaptureName; | |||
const char* fPlaybackName; | |||
unsigned int fCardInputs; | |||
unsigned int fCardOutputs; | |||
@@ -182,6 +184,8 @@ namespace Jack | |||
fInputParams = 0; | |||
fOutputParams = 0; | |||
fPeriod = 2; | |||
fCaptureName = NULL; | |||
fPlaybackName = NULL; | |||
fInputCardBuffer = 0; | |||
fOutputCardBuffer = 0; | |||
@@ -200,6 +204,8 @@ namespace Jack | |||
{ | |||
fInputCardBuffer = 0; | |||
fOutputCardBuffer = 0; | |||
fCaptureName = NULL; | |||
fPlaybackName = NULL; | |||
for ( int i = 0; i < 256; i++ ) | |||
{ | |||
@@ -216,8 +222,8 @@ namespace Jack | |||
int open() | |||
{ | |||
//open input/output streams | |||
check_error ( snd_pcm_open ( &fInputDevice, fCardName, SND_PCM_STREAM_CAPTURE, 0 ) ); | |||
check_error ( snd_pcm_open ( &fOutputDevice, fCardName, SND_PCM_STREAM_PLAYBACK, 0 ) ); | |||
check_error ( snd_pcm_open ( &fInputDevice, (fCaptureName == NULL) ? fCardName : fCaptureName, SND_PCM_STREAM_CAPTURE, 0 ) ); | |||
check_error ( snd_pcm_open ( &fOutputDevice, (fPlaybackName == NULL) ? fCardName : fPlaybackName, SND_PCM_STREAM_PLAYBACK, 0 ) ); | |||
//get hardware input parameters | |||
check_error ( snd_pcm_hw_params_malloc ( &fInputParams ) ); | |||
@@ -523,6 +529,7 @@ namespace Jack | |||
fCardInputs, fCardOutputs, | |||
fFrequency, fBuffering, | |||
snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ) ); | |||
snd_ctl_close(ctl_handle); | |||
} | |||
/** | |||
@@ -551,7 +558,7 @@ namespace Jack | |||
printHWParams ( fInputParams ); | |||
if ( fSoftOutputs > 0 ) | |||
printHWParams ( fOutputParams ); | |||
snd_ctl_close(ctl_handle); | |||
return 0; | |||
} | |||
@@ -31,7 +31,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include <signal.h> | |||
#include <sys/types.h> | |||
#include <sys/time.h> | |||
#include <regex.h> | |||
#include <string.h> | |||
#include "JackAlsaDriver.h" | |||
@@ -172,30 +171,31 @@ int JackAlsaDriver::Detach() | |||
return JackAudioDriver::Detach(); | |||
} | |||
static char* get_control_device_name(const char * device_name) | |||
extern "C" char* get_control_device_name(const char * device_name) | |||
{ | |||
char * ctl_name; | |||
regex_t expression; | |||
const char * comma; | |||
regcomp(&expression, "(plug)?hw:[0-9](,[0-9])?", REG_ICASE | REG_EXTENDED); | |||
/* the user wants a hw or plughw device, the ctl name | |||
* should be hw:x where x is the card identification. | |||
* We skip the subdevice suffix that starts with comma */ | |||
if (!regexec(&expression, device_name, 0, NULL, 0)) { | |||
/* the user wants a hw or plughw device, the ctl name | |||
* should be hw:x where x is the card number */ | |||
char tmp[5]; | |||
strncpy(tmp, strstr(device_name, "hw"), 4); | |||
tmp[4] = '\0'; | |||
jack_info("control device %s",tmp); | |||
ctl_name = strdup(tmp); | |||
} else { | |||
ctl_name = strdup(device_name); | |||
if (strncasecmp(device_name, "plughw:", 7) == 0) { | |||
/* skip the "plug" prefix" */ | |||
device_name += 4; | |||
} | |||
regfree(&expression); | |||
if (ctl_name == NULL) { | |||
jack_error("strdup(\"%s\") failed.", ctl_name); | |||
comma = strchr(device_name, ','); | |||
if (comma == NULL) { | |||
ctl_name = strdup(device_name); | |||
if (ctl_name == NULL) { | |||
jack_error("strdup(\"%s\") failed.", device_name); | |||
} | |||
} else { | |||
ctl_name = strndup(device_name, comma - device_name); | |||
if (ctl_name == NULL) { | |||
jack_error("strndup(\"%s\", %u) failed.", device_name, (unsigned int)(comma - device_name)); | |||
} | |||
} | |||
return ctl_name; | |||
@@ -278,16 +278,22 @@ int JackAlsaDriver::Open(jack_nframes_t nframes, | |||
int playback_card = card_to_num(playback_driver_name); | |||
char audio_name[32]; | |||
snprintf(audio_name, sizeof(audio_name), "Audio%d", capture_card); | |||
if (!JackServerGlobals::on_device_acquire(audio_name)) { | |||
jack_error("Audio device %s cannot be acquired...", capture_driver_name); | |||
return -1; | |||
if (capture_card >= 0) { | |||
snprintf(audio_name, sizeof(audio_name), "Audio%d", capture_card); | |||
if (!JackServerGlobals::on_device_acquire(audio_name)) { | |||
jack_error("Audio device %s cannot be acquired...", capture_driver_name); | |||
return -1; | |||
} | |||
} | |||
if (playback_card != capture_card) { | |||
if (playback_card >= 0 && playback_card != capture_card) { | |||
snprintf(audio_name, sizeof(audio_name), "Audio%d", playback_card); | |||
if (!JackServerGlobals::on_device_acquire(audio_name)) { | |||
jack_error("Audio device %s cannot be acquired...", playback_driver_name); | |||
if (capture_card >= 0) { | |||
snprintf(audio_name, sizeof(audio_name), "Audio%d", capture_card); | |||
JackServerGlobals::on_device_release(audio_name); | |||
} | |||
return -1; | |||
} | |||
} | |||
@@ -579,6 +585,7 @@ enum_alsa_devices() | |||
if (snd_ctl_open(&handle, card_id, 0) >= 0 && | |||
snd_ctl_card_info(handle, info) >= 0) | |||
{ | |||
snprintf(card_id, sizeof(card_id), "hw:%s", snd_ctl_card_info_get_id(info)); | |||
fill_device(&constraint_ptr, &array_size, card_id, snd_ctl_card_info_get_name(info)); | |||
device_no = -1; | |||
@@ -731,13 +738,13 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () | |||
desc = jack_driver_descriptor_construct("alsa", JackDriverMaster, "Linux ALSA API based audio backend", &filler); | |||
strcpy(value.str, "hw:0"); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, enum_alsa_devices(), "ALSA device name", NULL); | |||
strcpy(value.str, "none"); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set device", NULL); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set device", NULL); | |||
strcpy(value.str, "hw:0"); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, enum_alsa_devices(), "ALSA device name", NULL); | |||
value.ui = 48000U; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); | |||
@@ -778,9 +785,9 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () | |||
" s - shaped\n" | |||
" t - triangular"); | |||
value.i = 0; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamInt, &value, NULL, "Number of capture channels (defaults to hardware max)", NULL); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamInt, &value, NULL, "Number of playback channels (defaults to hardware max)", NULL); | |||
value.ui = 0; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to hardware max)", NULL); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Number of playback channels (defaults to hardware max)", NULL); | |||
value.i = FALSE; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "shorts", 'S', JackDriverParamBool, &value, NULL, "Try 16-bit samples before 32-bit", NULL); | |||
@@ -859,10 +866,12 @@ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLocke | |||
break; | |||
case 'd': | |||
playback_pcm_name = strdup (param->value.str); | |||
capture_pcm_name = strdup (param->value.str); | |||
jack_log("playback device %s", playback_pcm_name); | |||
jack_log("capture device %s", capture_pcm_name); | |||
if (strcmp (param->value.str, "none") != 0) { | |||
playback_pcm_name = strdup (param->value.str); | |||
capture_pcm_name = strdup (param->value.str); | |||
jack_log("playback device %s", playback_pcm_name); | |||
jack_log("capture device %s", capture_pcm_name); | |||
} | |||
break; | |||
case 'H': | |||
@@ -889,8 +898,9 @@ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLocke | |||
case 'n': | |||
user_nperiods = param->value.ui; | |||
if (user_nperiods < 2) /* enforce minimum value */ | |||
if (user_nperiods < 2) { /* enforce minimum value */ | |||
user_nperiods = 2; | |||
} | |||
break; | |||
case 's': | |||
@@ -974,8 +984,9 @@ void SetTime(jack_time_t time) | |||
int Restart() | |||
{ | |||
int res; | |||
if ((res = g_alsa_driver->Stop()) == 0) | |||
if ((res = g_alsa_driver->Stop()) == 0) { | |||
res = g_alsa_driver->Start(); | |||
} | |||
return res; | |||
} | |||
@@ -39,15 +39,13 @@ class JackAlsaDriver : public JackAudioDriver | |||
private: | |||
jack_driver_t* fDriver; | |||
int fReservedCaptureDevice; | |||
int fReservedPlaybackDevice; | |||
void UpdateLatencies(); | |||
public: | |||
JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | |||
: JackAudioDriver(name, alias, engine, table),fDriver(NULL),fReservedCaptureDevice(-1),fReservedPlaybackDevice(-1) | |||
: JackAudioDriver(name, alias, engine, table),fDriver(NULL) | |||
{} | |||
virtual ~JackAlsaDriver() | |||
{} | |||
@@ -32,7 +32,6 @@ | |||
#include <signal.h> | |||
#include <sys/types.h> | |||
#include <sys/time.h> | |||
#include <regex.h> | |||
#include <string.h> | |||
#include "alsa_driver.h" | |||
@@ -137,30 +136,18 @@ alsa_driver_check_capabilities (alsa_driver_t *driver) | |||
return 0; | |||
} | |||
char* get_control_device_name(const char * device_name); | |||
static int | |||
alsa_driver_check_card_type (alsa_driver_t *driver) | |||
{ | |||
int err; | |||
snd_ctl_card_info_t *card_info; | |||
char * ctl_name; | |||
regex_t expression; | |||
snd_ctl_card_info_alloca (&card_info); | |||
regcomp(&expression,"(plug)?hw:[0-9](,[0-9])?",REG_ICASE|REG_EXTENDED); | |||
if (!regexec(&expression,driver->alsa_name_playback,0,NULL,0)) { | |||
/* the user wants a hw or plughw device, the ctl name | |||
* should be hw:x where x is the card number */ | |||
char tmp[5]; | |||
strncpy(tmp,strcasestr(driver->alsa_name_playback,"hw"),4); | |||
tmp[4]='\0'; | |||
jack_info("control device %s",tmp); | |||
ctl_name = strdup(tmp); | |||
} else { | |||
ctl_name = strdup(driver->alsa_name_playback); | |||
} | |||
ctl_name = get_control_device_name(driver->alsa_name_playback); | |||
// XXX: I don't know the "right" way to do this. Which to use | |||
// driver->alsa_name_playback or driver->alsa_name_capture. | |||
@@ -175,7 +162,6 @@ alsa_driver_check_card_type (alsa_driver_t *driver) | |||
driver->alsa_driver = strdup(snd_ctl_card_info_get_driver (card_info)); | |||
regfree(&expression); | |||
free(ctl_name); | |||
return alsa_driver_check_capabilities (driver); | |||
@@ -38,9 +38,9 @@ def build(bld): | |||
jackd.use = ['serverlib'] | |||
if bld.env['IS_LINUX'] and bld.env['BUILD_JACKDBUS']: | |||
jackd.source += ['../dbus/reserve.c', '../dbus/audio_reserve.c'] | |||
jackd.use += ['PTHREAD', 'DL', 'RT', 'DBUS-1'] | |||
jackd.use += ['PTHREAD', 'DL', 'RT', 'M', 'STDC++', 'DBUS-1'] | |||
else: | |||
jackd.use += ['PTHREAD', 'DL', 'RT'] | |||
jackd.use += ['PTHREAD', 'DL', 'RT', 'M', 'STDC++'] | |||
jackd.target = 'jackd' | |||
create_jack_driver_obj(bld, 'dummy', '../common/JackDummyDriver.cpp') | |||
@@ -7,7 +7,7 @@ | |||
<key>CFBundleExecutable</key> | |||
<string>Jackservermp</string> | |||
<key>CFBundleGetInfoString</key> | |||
<string>Jackdmp 1.9.9, @03-11 Paul Davis, Grame</string> | |||
<string>Jackdmp 1.9.9.5, @03-12 Paul Davis, Grame</string> | |||
<key>CFBundleIdentifier</key> | |||
<string>com.grame.Jackmp</string> | |||
<key>CFBundleInfoDictionaryVersion</key> | |||
@@ -19,6 +19,6 @@ | |||
<key>CFBundleSignature</key> | |||
<string>????</string> | |||
<key>CFBundleVersion</key> | |||
<string>1.9.9</string> | |||
<string>1.9.9.5</string> | |||
</dict> | |||
</plist> |
@@ -8737,6 +8737,7 @@ | |||
GCC_OPTIMIZATION_LEVEL = 0; | |||
GCC_PREPROCESSOR_DEFINITIONS = ""; | |||
HEADER_SEARCH_PATHS = ( | |||
../macosx, | |||
/opt/local/include, | |||
., | |||
../posix, | |||
@@ -8787,6 +8788,7 @@ | |||
GCC_MODEL_TUNING = G4; | |||
GCC_PREPROCESSOR_DEFINITIONS = ""; | |||
HEADER_SEARCH_PATHS = ( | |||
../macosx, | |||
/opt/local/include, | |||
., | |||
../posix, | |||
@@ -9750,7 +9752,7 @@ | |||
../common/jack, | |||
); | |||
INFOPLIST_FILE = "Jack-Info.plist"; | |||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | |||
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3; | |||
MACOSX_DEPLOYMENT_TARGET = 10.4; | |||
OTHER_CFLAGS = ( | |||
@@ -9935,7 +9937,7 @@ | |||
../common/jack, | |||
); | |||
INFOPLIST_FILE = "Jack-Info.plist"; | |||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | |||
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3; | |||
MACOSX_DEPLOYMENT_TARGET = 10.4; | |||
OTHER_CFLAGS = ( | |||
@@ -13629,7 +13631,7 @@ | |||
../common/jack, | |||
); | |||
INFOPLIST_FILE = "Jack-Info.plist"; | |||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | |||
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3; | |||
MACOSX_DEPLOYMENT_TARGET = 10.4; | |||
OTHER_CFLAGS = ( | |||
@@ -14461,7 +14463,7 @@ | |||
../common/jack, | |||
); | |||
INFOPLIST_FILE = "Jack-Info.plist"; | |||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | |||
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3; | |||
MACOSX_DEPLOYMENT_TARGET = 10.4; | |||
OTHER_CFLAGS = ( | |||
@@ -14640,7 +14642,7 @@ | |||
../common/jack, | |||
); | |||
INFOPLIST_FILE = "Jack-Info.plist"; | |||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | |||
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3; | |||
MACOSX_DEPLOYMENT_TARGET = 10.4; | |||
OTHER_CFLAGS = ( | |||
@@ -16431,7 +16433,7 @@ | |||
../common/jack, | |||
); | |||
INFOPLIST_FILE = "Jack-Info.plist"; | |||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | |||
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = ( | |||
/opt/local/lib, | |||
/usr/lib/gcc/darwin/3.3, | |||
@@ -16954,7 +16956,7 @@ | |||
../common/jack, | |||
); | |||
INFOPLIST_FILE = "Jack-Info.plist"; | |||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | |||
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3; | |||
MACOSX_DEPLOYMENT_TARGET = 10.4; | |||
OTHER_CFLAGS = ( | |||
@@ -17908,6 +17910,7 @@ | |||
GCC_OPTIMIZATION_LEVEL = 0; | |||
GCC_PREPROCESSOR_DEFINITIONS = ""; | |||
HEADER_SEARCH_PATHS = ( | |||
../macosx, | |||
/opt/local/include, | |||
., | |||
../posix, | |||
@@ -17960,6 +17963,7 @@ | |||
GCC_MODEL_TUNING = G4; | |||
GCC_PREPROCESSOR_DEFINITIONS = ""; | |||
HEADER_SEARCH_PATHS = ( | |||
../macosx, | |||
/opt/local/include, | |||
., | |||
../posix, | |||
@@ -908,16 +908,26 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
} | |||
// AUHAL | |||
#ifdef MAC_OS_X_VERSION_10_5 | |||
ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; | |||
Component HALOutput = FindNextComponent(NULL, &cd); | |||
err1 = OpenAComponent(HALOutput, &fAUHAL); | |||
if (err1 != noErr) { | |||
jack_error("Error calling OpenAComponent"); | |||
printError(err1); | |||
goto error; | |||
} | |||
#else | |||
AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; | |||
AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd); | |||
err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL); | |||
if (err1 != noErr) { | |||
jack_error("Error calling AudioComponentInstanceNew"); | |||
printError(err1); | |||
goto error; | |||
} | |||
#endif | |||
err1 = AudioUnitInitialize(fAUHAL); | |||
if (err1 != noErr) { | |||
jack_error("Cannot initialize AUHAL unit"); | |||
@@ -258,17 +258,21 @@ static CFStringRef GetDeviceName(AudioDeviceID id) | |||
return (err == noErr) ? UIname : NULL; | |||
} | |||
static void ParseChannelList(const string& list, vector<int>& result) | |||
static void ParseChannelList(const string& list, vector<int>& result, int max_chan) | |||
{ | |||
stringstream ss(list); | |||
string token; | |||
int chan; | |||
int chan; | |||
while (ss >> token) { | |||
istringstream ins; | |||
ins.str(token); | |||
ins >> chan; | |||
result.push_back(chan); | |||
if (chan < 0 || chan >= max_chan) { | |||
jack_error("Ignore incorrect channel mapping value = %d", chan); | |||
} else { | |||
result.push_back(chan); | |||
} | |||
} | |||
} | |||
@@ -1384,56 +1388,56 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, | |||
} | |||
/* | |||
Return the max possible input channels in in_nChannels and output channels in out_nChannels. | |||
Return the max possible input channels in in_maxChannels and output channels in out_maxChannels. | |||
*/ | |||
int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchannels, int& outchannels, int& in_nChannels, int& out_nChannels, bool strict) | |||
int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchannels, int& outchannels, int& in_maxChannels, int& out_maxChannels, bool strict) | |||
{ | |||
OSStatus err = noErr; | |||
if (capturing) { | |||
err = GetTotalChannels(fDeviceID, in_nChannels, true); | |||
err = GetTotalChannels(fDeviceID, in_maxChannels, true); | |||
if (err != noErr) { | |||
jack_error("SetupChannels : cannot get input channel number"); | |||
printError(err); | |||
return -1; | |||
} else { | |||
jack_log("JackCoreAudioDriver::SetupChannels : max input channels : %d", in_nChannels); | |||
jack_log("JackCoreAudioDriver::SetupChannels : max input channels : %d", in_maxChannels); | |||
} | |||
} | |||
if (playing) { | |||
err = GetTotalChannels(fDeviceID, out_nChannels, false); | |||
err = GetTotalChannels(fDeviceID, out_maxChannels, false); | |||
if (err != noErr) { | |||
jack_error("Cannot get output channel number"); | |||
printError(err); | |||
return -1; | |||
} else { | |||
jack_log("JackCoreAudioDriver::SetupChannels : max output channels : %d", out_nChannels); | |||
jack_log("JackCoreAudioDriver::SetupChannels : max output channels : %d", out_maxChannels); | |||
} | |||
} | |||
if (inchannels > in_nChannels) { | |||
jack_error("This device hasn't required input channels inchannels = %d in_nChannels = %d", inchannels, in_nChannels); | |||
if (inchannels > in_maxChannels) { | |||
jack_error("This device hasn't required input channels inchannels = %d in_maxChannels = %d", inchannels, in_maxChannels); | |||
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 (outchannels > out_maxChannels) { | |||
jack_error("This device hasn't required output channels outchannels = %d out_maxChannels = %d", outchannels, out_maxChannels); | |||
if (strict) { | |||
return -1; | |||
} | |||
} | |||
if (inchannels == -1) { | |||
jack_log("JackCoreAudioDriver::SetupChannels : setup max in channels = %d", in_nChannels); | |||
inchannels = in_nChannels; | |||
jack_log("JackCoreAudioDriver::SetupChannels : setup max in channels = %d", in_maxChannels); | |||
inchannels = in_maxChannels; | |||
} | |||
if (outchannels == -1) { | |||
jack_log("JackCoreAudioDriver::SetupChannels : setup max out channels = %d", out_nChannels); | |||
outchannels = out_nChannels; | |||
jack_log("JackCoreAudioDriver::SetupChannels : setup max out channels = %d", out_maxChannels); | |||
outchannels = out_maxChannels; | |||
} | |||
return 0; | |||
@@ -1509,7 +1513,6 @@ error: | |||
// Remove BS change notification | |||
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback); | |||
return -1; | |||
} | |||
int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t sample_rate) | |||
@@ -1594,8 +1597,8 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
bool playing, | |||
int inchannels, | |||
int outchannels, | |||
int in_nChannels, | |||
int out_nChannels, | |||
int in_maxChannels, | |||
int out_maxChannels, | |||
const vector<int>& chan_in_list, | |||
const vector<int>& chan_out_list, | |||
jack_nframes_t buffer_size, | |||
@@ -1607,24 +1610,34 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
AudioDeviceID currAudioDeviceID; | |||
UInt32 size; | |||
jack_log("JackCoreAudioDriver::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()); | |||
jack_log("JackCoreAudioDriver::OpenAUHAL : capturing = %d playing = %d inchannels = %d outchannels = %d in_maxChannels = %d out_maxChannels = %d chan_in_list = %d chan_out_list = %d", | |||
capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, chan_in_list.size(), chan_out_list.size()); | |||
if (inchannels == 0 && outchannels == 0) { | |||
jack_error("No input and output channels..."); | |||
return -1; | |||
} | |||
// AUHAL | |||
#ifdef MAC_OS_X_VERSION_10_5 | |||
ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; | |||
Component HALOutput = FindNextComponent(NULL, &cd); | |||
err1 = OpenAComponent(HALOutput, &fAUHAL); | |||
if (err1 != noErr) { | |||
jack_error("Error calling OpenAComponent"); | |||
printError(err1); | |||
goto error; | |||
} | |||
#else | |||
AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; | |||
AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd); | |||
err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL); | |||
if (err1 != noErr) { | |||
jack_error("Error calling AudioComponentInstanceNew"); | |||
printError(err1); | |||
goto error; | |||
} | |||
#endif | |||
err1 = AudioUnitInitialize(fAUHAL); | |||
if (err1 != noErr) { | |||
@@ -1702,16 +1715,16 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
} | |||
// Setup input channel map | |||
if (capturing && inchannels > 0 && inchannels <= in_nChannels) { | |||
SInt32 chanArr[in_nChannels]; | |||
for (int i = 0; i < in_nChannels; i++) { | |||
if (capturing && inchannels > 0 && inchannels <= in_maxChannels) { | |||
SInt32 chanArr[in_maxChannels]; | |||
for (int i = 0; i < in_maxChannels; i++) { | |||
chanArr[i] = -1; | |||
} | |||
// 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) { | |||
if (chan < out_maxChannels) { | |||
// The wanted JACK input index for the 'chan' channel value | |||
chanArr[chan] = i; | |||
jack_info("Input channel = %d ==> JACK input port = %d", chan, i); | |||
@@ -1727,7 +1740,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
} | |||
} | |||
AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels); | |||
AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_maxChannels); | |||
if (err1 != noErr) { | |||
jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input"); | |||
printError(err1); | |||
@@ -1736,16 +1749,16 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
} | |||
// Setup output channel map | |||
if (playing && outchannels > 0 && outchannels <= out_nChannels) { | |||
SInt32 chanArr[out_nChannels]; | |||
for (int i = 0; i < out_nChannels; i++) { | |||
if (playing && outchannels > 0 && outchannels <= out_maxChannels) { | |||
SInt32 chanArr[out_maxChannels]; | |||
for (int i = 0; i < out_maxChannels; i++) { | |||
chanArr[i] = -1; | |||
} | |||
// 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) { | |||
if (chan < out_maxChannels) { | |||
// The wanted JACK output index for the 'chan' channel value | |||
chanArr[chan] = i; | |||
jack_info("JACK output port = %d ==> output channel = %d", i, chan); | |||
@@ -1761,7 +1774,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
} | |||
} | |||
err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels); | |||
err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_maxChannels); | |||
if (err1 != noErr) { | |||
jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output"); | |||
printError(err1); | |||
@@ -1993,8 +2006,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, | |||
int ac3_bitrate, | |||
bool ac3_lfe) | |||
{ | |||
int in_nChannels = 0; | |||
int out_nChannels = 0; | |||
int in_maxChannels = 0; | |||
int out_maxChannels = 0; | |||
char capture_driver_name[256]; | |||
char playback_driver_name[256]; | |||
@@ -2012,19 +2025,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, | |||
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; | |||
@@ -2052,9 +2053,21 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, | |||
goto error; | |||
} | |||
if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, !ac3_encoding) < 0) { | |||
if (SetupChannels(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, !ac3_encoding) < 0) { | |||
goto error; | |||
} | |||
ParseChannelList(chan_in_list, parsed_chan_in_list, in_maxChannels); | |||
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, out_maxChannels); | |||
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(); | |||
} | |||
if (SetupBufferSize(buffer_size) < 0) { | |||
goto error; | |||
@@ -2096,7 +2109,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, | |||
} | |||
// Force real output channel number to 2 | |||
outchannels = out_nChannels = 2; | |||
outchannels = out_maxChannels = 2; | |||
} else { | |||
fPlaybackChannels = outchannels; | |||
@@ -2105,7 +2118,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, | |||
// Core driver may have changed the in/out values | |||
fCaptureChannels = inchannels; | |||
if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) { | |||
if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) { | |||
goto error; | |||
} | |||
@@ -2455,8 +2468,8 @@ extern "C" | |||
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"); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "input-list", 'n', JackDriverParamString, &value, NULL, "Input channel list for channel mapping", "List of input channel number to be opened (syntax like : \"0 3 2\")"); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "output-list", 'N', JackDriverParamString, &value, NULL, "Output channel list for channel mapping", "List of output channel number to be opened (syntax like : \"0 3 2\")"); | |||
value.str[0] = 0; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL); | |||
@@ -2650,7 +2663,7 @@ extern "C" | |||
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) { | |||
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"); | |||
} | |||
@@ -105,8 +105,9 @@ class TiPhoneCoreAudioRenderer | |||
void PerformAudioCallback(int frames) | |||
{ | |||
if (fAudioCallback) | |||
if (fAudioCallback) { | |||
fAudioCallback(frames, fInChannel, fOutChannel, fCallbackArg); | |||
} | |||
} | |||
}; | |||
@@ -81,7 +81,11 @@ JackCoreMidiOutputPort::Execute() | |||
packet = MIDIPacketListAdd(packet_list, PACKET_BUFFER_SIZE, packet, | |||
timestamp, size, data); | |||
if (packet) { | |||
while (GetMicroSeconds() < send_time) { | |||
do { | |||
if (GetMicroSeconds() >= send_time) { | |||
event = 0; | |||
break; | |||
} | |||
event = GetCoreMidiEvent(false); | |||
if (! event) { | |||
break; | |||
@@ -90,10 +94,7 @@ JackCoreMidiOutputPort::Execute() | |||
packet, | |||
GetTimeStampFromFrames(event->time), | |||
event->size, event->buffer); | |||
if (! packet) { | |||
break; | |||
} | |||
} | |||
} while (packet); | |||
SendPacketList(packet_list); | |||
} else { | |||
@@ -5,9 +5,9 @@ | |||
[ -d JackRouter.plugin ] && sudo cp -r JackRouter.plugin /Library/Audio/Plug-Ins/HAL/ | |||
# Copy libraries and exe | |||
sudo cp -r Jackmp.framework /Library/Frameworks/ | |||
sudo cp -r Jackservermp.framework /Library/Frameworks/ | |||
sudo cp -r Jacknet.framework /Library/Frameworks/ | |||
sudo cp -r Jackmp.framework /System/Library/Frameworks/ | |||
sudo cp -r Jackservermp.framework /System/Library/Frameworks/ | |||
sudo cp -r Jacknet.framework /System/Library/Frameworks/ | |||
sudo install -d /usr/local/bin | |||
sudo cp jackdmp /usr/local/bin | |||
[ -f jack_load ] && sudo cp jack_load /usr/local/bin | |||
@@ -29,16 +29,26 @@ sudo cp jack_loopback.so /usr/local/lib/jackmp | |||
[ -f audioadapter.so ] && sudo cp audioadapter.so /usr/local/lib/jackmp | |||
# Create links to jackmp ressources | |||
cd /usr/local/lib && [ -f libjack.0.dylib ] && sudo mv -f libjack.0.dylib tmp_libjack.0.dylib | |||
cd /usr/local/lib && [ -f jackd ] && sudo mv -f jackd tmp_jackd | |||
cd /usr/local/bin && [ -f jackd ] && sudo rm jackd | |||
cd /usr/local/lib && [ -f libjack.0.dylib ] && sudo rm libjack.0.dylib | |||
cd /usr/local/lib && [ -f libjack.dylib ] && sudo rm libjack.dylib | |||
cd /usr/local/lib && [ -f libjackserver.0.dylib ] && sudo rm libjackserver.0.dylib | |||
cd /usr/local/lib && [ -f libjackserver.dylib ] && sudo rm libjackserver.dylib | |||
cd /usr/local/lib && [ -f libjacknet.dylib ] && sudo rm libjacknet.dylib | |||
cd /usr/local/lib && [ -f libjacknet.0.dylib ] && sudo rm libjacknet.0.dylib | |||
cd /usr/local/bin && [ -f jackd ] && sudo rm jackd | |||
cd /usr/local/lib && sudo ln -s /Library/Frameworks/Jackmp.framework/Jackmp libjack.dylib | |||
cd /usr/local/lib && sudo ln -s /Library/Frameworks/Jackmp.framework/Jackmp libjack.0.dylib | |||
cd /usr/local/lib && sudo ln -s /Library/Frameworks/Jacknet.framework/Jacknet libjacknet.dylib | |||
cd /usr/local/lib && sudo ln -s /Library/Frameworks/Jacknet.framework/Jacknet libjacknet.0.dylib | |||
cd /usr/local/lib && sudo ln -s /System/Library/Frameworks/Jackmp.framework/Jackmp libjack.dylib | |||
cd /usr/local/lib && sudo ln -s /System/Library/Frameworks/Jackmp.framework/Jackmp libjack.0.dylib | |||
cd /usr/local/lib && sudo ln -s /System/Library/Frameworks/Jackservermp.framework/Jackservermp libjackserver.dylib | |||
cd /usr/local/lib && sudo ln -s /System/Library/Frameworks/Jackservermp.framework/Jackservermp libjackserver.0.dylib | |||
cd /usr/local/lib && sudo ln -s /System/Library/Frameworks/Jacknet.framework/Jacknet libjacknet.dylib | |||
cd /usr/local/lib && sudo ln -s /System/Library/Frameworks/Jacknet.framework/Jacknet libjacknet.0.dylib | |||
cd /usr/local/bin && sudo ln -s jackdmp jackd | |||
@@ -3,14 +3,10 @@ sudo rm -r "/usr/local/lib/jackmp" | |||
sudo rm "/usr/local/bin/jackdmp" | |||
sudo rm -r "/usr/local/lib/jackd" | |||
sudo rm "/usr/local/lib/libjackmp.dylib" | |||
sudo rm -r "/Library/Frameworks/Jackmp.framework" | |||
sudo rm -r "/Library/Frameworks/Jackservermp.framework" | |||
sudo rm -r "/Library/Frameworks/Jacknet.framework" | |||
sudo rm -r "/System/Library/Frameworks/Jackmp.framework" | |||
sudo rm -r "/System/Library/Frameworks/Jackservermp.framework" | |||
sudo rm -r "/System/Library/Frameworks/Jacknet.framework" | |||
sudo rm -r "/Library/Audio/Plug-Ins/HAL/JackRouter.plugin" | |||
# Tries to restore jack | |||
cd /usr/local/lib && sudo rm -r libjack.0.dylib | |||
cd /usr/local/lib && [ -f tmp_libjack.0.dylib ] && sudo mv -f tmp_libjack.0.dylib libjack.0.dylib | |||
cd /usr/local/lib && ln -s libjack.0.dylib libjack.dylib | |||
cd /usr/local/bin && [ -f tmp_jackd ] && sudo mv -f tmp_jackd jackd | |||
@@ -73,7 +73,7 @@ static int start_server_dbus(const char* server_name) | |||
return 0; | |||
} | |||
#else | |||
#elif defined(USE_CLASSIC_AUTOLAUNCH) | |||
/* Exec the JACK server in this process. Does not return. */ | |||
static void start_server_classic_aux(const char* server_name) | |||
@@ -199,8 +199,11 @@ static int start_server(const char* server_name, jack_options_t options) | |||
#if defined(USE_LIBDBUS_AUTOLAUNCH) | |||
return start_server_dbus(server_name); | |||
#else | |||
#elif defined(USE_CLASSIC_AUTOLAUNCH) | |||
return start_server_classic(server_name); | |||
#else | |||
fprintf(stderr, "Automatic start of JACK server is disabled at configure time\n"); | |||
return 1; | |||
#endif | |||
} | |||
@@ -97,7 +97,7 @@ int JackSocketServerChannel::Start() | |||
void JackSocketServerChannel::Stop() | |||
{ | |||
fThread.Kill(); | |||
fThread.Stop(); | |||
} | |||
void JackSocketServerChannel::ClientCreate() | |||
@@ -6,7 +6,7 @@ def create_jack_driver_obj(bld, target, sources, uselib = None): | |||
driver.features.append('cc') | |||
driver.env['shlib_PATTERN'] = 'jack_%s.so' | |||
#driver.env.append_unique('CXXFLAGS', '-march=i686 -msse3 -ffast-math') | |||
#driver.env.append_unique('CCFLAGS', '-march=i686 -msse3 -ffast-math') | |||
#driver.env.append_unique('CFLAGS', '-march=i686 -msse3 -ffast-math') | |||
driver.defines = 'HAVE_CONFIG_H' | |||
driver.includes = ['.', '..','../posix', '../common', '../common/jack'] | |||
driver.target = target | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> | |||
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 | |||
@@ -24,135 +24,145 @@ | |||
#include <unistd.h> | |||
#include <jack/jack.h> | |||
class Freq | |||
struct Freq | |||
{ | |||
public: | |||
int p; | |||
int f; | |||
float a; | |||
float xa; | |||
float ya; | |||
float xf; | |||
float yf; | |||
float x1; | |||
float y1; | |||
float x2; | |||
float y2; | |||
}; | |||
class MTDM | |||
{ | |||
public: | |||
MTDM (void); | |||
int process (size_t len, float *inp, float *out); | |||
int resolve (void); | |||
void invert (void) { _inv ^= 1; } | |||
int inv (void) { return _inv; } | |||
double del (void) { return _del; } | |||
double err (void) { return _err; } | |||
struct MTDM | |||
{ | |||
double _del; | |||
double _err; | |||
float _wlp; | |||
int _cnt; | |||
int _inv; | |||
Freq _freq [5]; | |||
struct Freq _freq [13]; | |||
}; | |||
MTDM::MTDM (void) : _cnt (0), _inv (0) | |||
struct MTDM * mtdm_new (double fsamp) | |||
{ | |||
int i; | |||
Freq *F; | |||
_freq [0].f = 4096; | |||
_freq [1].f = 512; | |||
_freq [2].f = 1088; | |||
_freq [3].f = 1544; | |||
_freq [4].f = 2049; | |||
_freq [0].a = 0.2f; | |||
_freq [1].a = 0.1f; | |||
_freq [2].a = 0.1f; | |||
_freq [3].a = 0.1f; | |||
_freq [4].a = 0.1f; | |||
for (i = 0, F = _freq; i < 5; i++, F++) | |||
{ | |||
struct Freq *F; | |||
struct MTDM *retval = (MTDM *)malloc( sizeof(struct MTDM) ); | |||
if (retval==NULL) | |||
return NULL; | |||
retval->_cnt = 0; | |||
retval->_inv = 0; | |||
retval->_freq [0].f = 4096; | |||
retval->_freq [1].f = 2048; | |||
retval->_freq [2].f = 3072; | |||
retval->_freq [3].f = 2560; | |||
retval->_freq [4].f = 2304; | |||
retval->_freq [5].f = 2176; | |||
retval->_freq [6].f = 1088; | |||
retval->_freq [7].f = 1312; | |||
retval->_freq [8].f = 1552; | |||
retval->_freq [9].f = 1800; | |||
retval->_freq [10].f = 3332; | |||
retval->_freq [11].f = 3586; | |||
retval->_freq [12].f = 3841; | |||
retval->_wlp = 200.0f / fsamp; | |||
for (i = 0, F = retval->_freq; i < 13; i++, F++) { | |||
F->p = 128; | |||
F->xa = F->ya = 0.0f; | |||
F->xf = F->yf = 0.0f; | |||
F->x1 = F->y1 = 0.0f; | |||
F->x2 = F->y2 = 0.0f; | |||
} | |||
return retval; | |||
} | |||
int MTDM::process (size_t len, float *ip, float *op) | |||
int mtdm_process (struct MTDM *self, size_t len, float *ip, float *op) | |||
{ | |||
int i; | |||
float vip, vop, a, c, s; | |||
Freq *F; | |||
struct Freq *F; | |||
while (len--) | |||
{ | |||
vop = 0.0f; | |||
vip = *ip++; | |||
for (i = 0, F = _freq; i < 5; i++, F++) | |||
for (i = 0, F = self->_freq; i < 13; i++, F++) | |||
{ | |||
a = 2 * (float) M_PI * (F->p & 65535) / 65536.0; | |||
a = 2 * (float) M_PI * (F->p & 65535) / 65536.0; | |||
F->p += F->f; | |||
c = cosf (a); | |||
s = -sinf (a); | |||
vop += F->a * s; | |||
c = cosf (a); | |||
s = -sinf (a); | |||
vop += (i ? 0.01f : 0.20f) * s; | |||
F->xa += s * vip; | |||
F->ya += c * vip; | |||
} | |||
} | |||
*op++ = vop; | |||
if (++_cnt == 16) | |||
if (++self->_cnt == 16) | |||
{ | |||
for (i = 0, F = _freq; i < 5; i++, F++) | |||
for (i = 0, F = self->_freq; i < 13; i++, F++) | |||
{ | |||
F->xf += 1e-3f * (F->xa - F->xf + 1e-20); | |||
F->yf += 1e-3f * (F->ya - F->yf + 1e-20); | |||
F->x1 += self->_wlp * (F->xa - F->x1 + 1e-20); | |||
F->y1 += self->_wlp * (F->ya - F->y1 + 1e-20); | |||
F->x2 += self->_wlp * (F->x1 - F->x2 + 1e-20); | |||
F->y2 += self->_wlp * (F->y1 - F->y2 + 1e-20); | |||
F->xa = F->ya = 0.0f; | |||
} | |||
_cnt = 0; | |||
self->_cnt = 0; | |||
} | |||
} | |||
return 0; | |||
} | |||
int MTDM::resolve (void) | |||
int mtdm_resolve (struct MTDM *self) | |||
{ | |||
int i, k, m; | |||
double d, e, f0, p; | |||
Freq *F = _freq; | |||
struct Freq *F = self->_freq; | |||
if (hypot (F->xf, F->yf) < 0.01) return -1; | |||
d = atan2 (F->yf, F->xf) / (2 * M_PI); | |||
if (_inv) d += 0.5f; | |||
if (d > 0.5f) d -= 1.0f; | |||
f0 = _freq [0].f; | |||
if (hypot (F->x2, F->y2) < 0.001) return -1; | |||
d = atan2 (F->y2, F->x2) / (2 * M_PI); | |||
if (self->_inv) d += 0.5; | |||
if (d > 0.5) d -= 1.0; | |||
f0 = self->_freq [0].f; | |||
m = 1; | |||
_err = 0.0; | |||
for (i = 0; i < 4; i++) | |||
self->_err = 0.0; | |||
for (i = 0; i < 12; i++) | |||
{ | |||
F++; | |||
p = atan2 (F->yf, F->xf) / (2 * M_PI) - d * F->f / f0; | |||
if (_inv) p += 0.5f; | |||
p = atan2 (F->y2, F->x2) / (2 * M_PI) - d * F->f / f0; | |||
if (self->_inv) p += 0.5; | |||
p -= floor (p); | |||
p *= 8; | |||
p *= 2; | |||
k = (int)(floor (p + 0.5)); | |||
e = fabs (p - k); | |||
if (e > _err) _err = e; | |||
if (e > 0.4) return 1; | |||
d += m * (k & 7); | |||
m *= 8; | |||
} | |||
_del = 16 * d; | |||
if (e > self->_err) self->_err = e; | |||
if (e > 0.4) return 1; | |||
d += m * (k & 1); | |||
m *= 2; | |||
} | |||
self->_del = 16 * d; | |||
return 0; | |||
} | |||
void mtdm_invert (struct MTDM *self) | |||
{ | |||
self->_inv ^= 1; | |||
} | |||
// -------------------------------------------------------------------------------- | |||
static MTDM mtdm; | |||
static struct MTDM *mtdm; | |||
static jack_client_t *jack_handle; | |||
static jack_port_t *jack_capt; | |||
static jack_port_t *jack_play; | |||
@@ -191,7 +201,7 @@ int jack_callback (jack_nframes_t nframes, void *arg) | |||
ip = (float *)(jack_port_get_buffer (jack_capt, nframes)); | |||
op = (float *)(jack_port_get_buffer (jack_play, nframes)); | |||
mtdm.process (nframes, ip, op); | |||
mtdm_process (mtdm, nframes, ip, op); | |||
return 0; | |||
} | |||
@@ -207,6 +217,8 @@ int main (int ac, char *av []) | |||
exit (1); | |||
} | |||
mtdm = mtdm_new(jack_get_sample_rate(jack_handle)); | |||
jack_set_process_callback (jack_handle, jack_callback, 0); | |||
if (jack_set_latency_callback) | |||
@@ -225,28 +237,28 @@ int main (int ac, char *av []) | |||
while (1) | |||
{ | |||
#ifdef WIN32 | |||
Sleep (250); | |||
#else | |||
usleep (250000); | |||
#endif | |||
if (mtdm.resolve() < 0) printf ("Signal below threshold...\n"); | |||
else | |||
#ifdef WIN32 | |||
Sleep (250); | |||
#else | |||
usleep (250000); | |||
#endif | |||
if (mtdm_resolve (mtdm) < 0) printf ("Signal below threshold...\n"); | |||
else | |||
{ | |||
jack_nframes_t systemic_latency; | |||
if (mtdm.err () > 0.3) | |||
if (mtdm->_err > 0.3) | |||
{ | |||
mtdm.invert (); | |||
mtdm.resolve (); | |||
mtdm_invert ( mtdm ); | |||
mtdm_resolve ( mtdm ); | |||
} | |||
systemic_latency = (jack_nframes_t) floor (mtdm._del - (capture_latency.max + playback_latency.max)); | |||
systemic_latency = (jack_nframes_t) floor (mtdm->_del - (capture_latency.max + playback_latency.max)); | |||
printf("%10.3lf frames %10.3lf ms total roundtrip latency\n\textra loopback latency: %u frames\n\tuse %u for the backend arguments -I and -O" | |||
, mtdm._del, mtdm._del * t, | |||
printf ("%10.3lf frames %10.3lf ms total roundtrip latency\n\textra loopback latency: %u frames\n\tuse %u for the backend arguments -I and -O", mtdm->_del, mtdm->_del * t, | |||
systemic_latency, systemic_latency/2); | |||
if (mtdm._err > 0.2) printf (" ??"); | |||
if (mtdm._inv) printf (" Inv"); | |||
if (mtdm->_err > 0.2) printf (" ??"); | |||
if (mtdm->_inv) printf (" Inv"); | |||
printf ("\n"); | |||
} | |||
} | |||
@@ -254,4 +266,4 @@ int main (int ac, char *av []) | |||
return 0; | |||
} | |||
// -------------------------------------------------------------------------------- | |||
// -------------------------------------------------------------------------------- |
@@ -208,7 +208,7 @@ bool JackWinNamedPipeServerChannel::Init() | |||
bool JackWinNamedPipeServerChannel::ClientListen() | |||
{ | |||
if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) { | |||
if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) { | |||
jack_error("JackWinNamedPipeServerChannel::ClientListen : cannot create result listen pipe"); | |||
return false; | |||
} else { | |||
@@ -17,16 +17,13 @@ | |||
*/ | |||
#ifndef __JackWinNamedPipeServerChannel__ | |||
#define __JackWinNamedPipeServerChannel__ | |||
#include "JackWinNamedPipe.h" | |||
#include "JackPlatformPlug.h" | |||
#include "JackConstants.h" | |||
#include "JackRequestDecoder.h" | |||
#include <list> | |||
namespace Jack | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp Audio Adapter for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "audioadapter\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "audioadapter.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "audioadapter\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_APP | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jack server for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "jackd\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "jackd.exe\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "jackd\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp Dummy Driver for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "jack_dummy\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "jack_dummy.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "jack_dummy\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp Loopback Driver for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "jack_loopback\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "jack_loopback.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "jack_loopback\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp Net Adapter for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "netadapter\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "netadapter.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "netadapter\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp Net Driver for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "jack_netdriver\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "jack_netdriver.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "jack_netdriver\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp Net Manager for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "netmanager\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "netmanager.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "netmanager\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp NetOne Driver for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "jack_netonedriver\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "jack_netonedriver.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "jack_netonedriver\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp PortAudio Driver for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "jack_portaudio\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "jack_portaudio.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "jack_portaudio\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jackmp WinMME Driver for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "jack_portaudio\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "jack_winmme.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "jack_winmme\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jack client library for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "libjack\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "libjack.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "libjack\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jack Net library for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "libjacknet\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "libjacknet.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "libjacknet\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -11,8 +11,8 @@ | |||
// | |||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||
1 VERSIONINFO | |||
FILEVERSION 1,9,9,3 | |||
PRODUCTVERSION 1,9,9,3 | |||
FILEVERSION 1,9,9,5 | |||
PRODUCTVERSION 1,9,9,5 | |||
FILEOS VOS_UNKNOWN | |||
FILETYPE VFT_DLL | |||
BEGIN | |||
@@ -23,14 +23,14 @@ BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "Grame\0" | |||
VALUE "FileDescription", "Jack server library for Windows\0" | |||
VALUE "FileVersion", "1, 9, 9, 3\0" | |||
VALUE "FileVersion", "1, 9, 9, 5\0" | |||
VALUE "InternalName", "libjackserver\0" | |||
VALUE "LegalCopyright", "Copyright Grame © 2006-2012\0" | |||
VALUE "LegalTrademarks", "\0" | |||
VALUE "OriginalFilename", "libjackserver.dll\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductName", "libjackserver\0" | |||
VALUE "ProductVersion", "1, 9, 9, 3\0" | |||
VALUE "ProductVersion", "1, 9, 9, 5\0" | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
@@ -37,7 +37,7 @@ PortAudioDevices::PortAudioDevices() | |||
} | |||
fHostName = new string[fNumHostApi]; | |||
for (id = 0; id < fNumHostApi; id++) { | |||
fHostName[id] = string (Pa_GetHostApiInfo(id)->name); | |||
fHostName[id] = string(Pa_GetHostApiInfo(id)->name); | |||
} | |||
} else { | |||
jack_error("JackPortAudioDriver::Pa_Initialize error = %s", Pa_GetErrorText(err)); | |||
@@ -97,7 +97,7 @@ string PortAudioDevices::GetFullName(std::string hostname, std::string devicenam | |||
return (hostname + "::" + devicename); | |||
} | |||
PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName (string fullname, PaDeviceIndex& id, bool isInput) | |||
PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName(string fullname, PaDeviceIndex& id, bool isInput) | |||
{ | |||
PaDeviceInfo* ret = NULL; | |||
//no driver to find | |||
@@ -112,14 +112,14 @@ PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName (string fullname, PaDevice | |||
} | |||
char* hostname = (char*)malloc(separator + 9); | |||
fill_n (hostname, separator + 9, 0); | |||
fullname.copy (hostname, separator); | |||
fill_n(hostname, separator + 9, 0); | |||
fullname.copy(hostname, separator); | |||
//we need the entire hostname, replace shortcuts | |||
if (strcmp (hostname, "DirectSound") == 0) { | |||
strcpy (hostname, "Windows DirectSound"); | |||
if (strcmp(hostname, "DirectSound") == 0) { | |||
strcpy(hostname, "Windows DirectSound"); | |||
} | |||
string devicename = fullname.substr (separator + 2); | |||
string devicename = fullname.substr(separator + 2); | |||
//then find the corresponding device | |||
for (PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++) { | |||
bool flag = (isInput) ? (fDeviceInfo[dev_id]->maxInputChannels > 0) : (fDeviceInfo[dev_id]->maxOutputChannels > 0); | |||
@@ -170,7 +170,7 @@ void PortAudioDevices::PrintSupportedStandardSampleRates(const PaStreamParameter | |||
int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_input) | |||
{ | |||
string fullname = string(devicename); | |||
PaDeviceInfo* device = GetDeviceFromFullName (fullname, id, true); | |||
PaDeviceInfo* device = GetDeviceFromFullName(fullname, id, true); | |||
if (device) { | |||
max_input = device->maxInputChannels; | |||
} else { | |||
@@ -189,7 +189,7 @@ int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceInd | |||
int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output) | |||
{ | |||
string fullname = string(devicename); | |||
PaDeviceInfo* device = GetDeviceFromFullName (fullname, id, false); | |||
PaDeviceInfo* device = GetDeviceFromFullName(fullname, id, false); | |||
if (device) { | |||
max_output = device->maxOutputChannels; | |||
} else { | |||
@@ -205,54 +205,80 @@ int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIn | |||
return id; | |||
} | |||
int PortAudioDevices::GetPreferredBufferSize(PaDeviceIndex id) | |||
{ | |||
#ifdef WIN32 | |||
/* ASIO specific latency information */ | |||
if (Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO) { | |||
long minLatency, maxLatency, preferredLatency, granularity; | |||
PaAsio_GetAvailableBufferSizes(id, &minLatency, &maxLatency, &preferredLatency, &granularity); | |||
jack_info("ASIO minimum buffer size = %ld", minLatency); | |||
jack_info("ASIO maximum buffer size = %ld", maxLatency); | |||
jack_info("ASIO preferred buffer size = %ld", preferredLatency); | |||
if (granularity == -1) { | |||
jack_info("ASIO buffer granularity = power of 2"); | |||
} else { | |||
jack_info("ASIO buffer granularity = %ld", granularity); | |||
} | |||
return preferredLatency; | |||
} else | |||
#endif | |||
{ | |||
return 512; // Non ASIO driver, returns generic value | |||
} | |||
} | |||
void PortAudioDevices::DisplayDevicesNames() | |||
{ | |||
PaDeviceIndex id; | |||
PaStreamParameters inputParameters, outputParameters; | |||
jack_info ("********************** Devices list, %d detected **********************", fNumDevice); | |||
jack_info("********************** Devices list, %d detected **********************", fNumDevice); | |||
for (id = 0; id < fNumDevice; id++) { | |||
jack_info ("-------- device #%d ------------------------------------------------", id); | |||
jack_info("-------- device #%d ------------------------------------------------", id); | |||
if (id == Pa_GetDefaultInputDevice()) { | |||
jack_info("[ Default Input ]"); | |||
} else if (id == Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi)->defaultInputDevice) { | |||
const PaHostApiInfo *host_info = Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi); | |||
} else if (id == Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->defaultInputDevice) { | |||
const PaHostApiInfo *host_info = Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi); | |||
jack_info("[ Default %s Input ]", host_info->name); | |||
} | |||
if (id == Pa_GetDefaultOutputDevice()) { | |||
jack_info ("[ Default Output ]"); | |||
} else if (id == Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi)->defaultOutputDevice) { | |||
const PaHostApiInfo *host_info = Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi); | |||
jack_info("[ Default Output ]"); | |||
} else if (id == Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->defaultOutputDevice) { | |||
const PaHostApiInfo *host_info = Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi); | |||
jack_info("[ Default %s Output ]", host_info->name); | |||
} | |||
/* print device info fields */ | |||
jack_info ("Name = %s", GetFullName(id).c_str()); | |||
jack_info ("Max inputs = %d", fDeviceInfo[id]->maxInputChannels); | |||
jack_info ("Max outputs = %d", fDeviceInfo[id]->maxOutputChannels); | |||
#ifdef WIN32 | |||
jack_info("Name = %s", GetFullName(id).c_str()); | |||
jack_info("Max inputs = %d", fDeviceInfo[id]->maxInputChannels); | |||
jack_info("Max outputs = %d", fDeviceInfo[id]->maxOutputChannels); | |||
#ifdef WIN32 | |||
/* ASIO specific latency information */ | |||
if (Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO) { | |||
long minLatency, maxLatency, preferredLatency, granularity; | |||
PaAsio_GetAvailableBufferSizes (id, &minLatency, &maxLatency, &preferredLatency, &granularity); | |||
PaAsio_GetAvailableBufferSizes(id, &minLatency, &maxLatency, &preferredLatency, &granularity); | |||
jack_info ("ASIO minimum buffer size = %ld", minLatency); | |||
jack_info ("ASIO maximum buffer size = %ld", maxLatency); | |||
jack_info ("ASIO preferred buffer size = %ld", preferredLatency); | |||
jack_info("ASIO minimum buffer size = %ld", minLatency); | |||
jack_info("ASIO maximum buffer size = %ld", maxLatency); | |||
jack_info("ASIO preferred buffer size = %ld", preferredLatency); | |||
if (granularity == -1) { | |||
jack_info ("ASIO buffer granularity = power of 2"); | |||
jack_info("ASIO buffer granularity = power of 2"); | |||
} else { | |||
jack_info ("ASIO buffer granularity = %ld", granularity); | |||
jack_info("ASIO buffer granularity = %ld", granularity); | |||
} | |||
} | |||
#endif | |||
jack_info ("Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate); | |||
#endif | |||
jack_info("Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate); | |||
/* poll for standard sample rates */ | |||
inputParameters.device = id; | |||
@@ -288,4 +314,3 @@ bool PortAudioDevices::IsDuplex(PaDeviceIndex id) | |||
//then the device isn't full duplex | |||
return false; | |||
} | |||
@@ -55,6 +55,7 @@ class PortAudioDevices | |||
void PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters); | |||
int GetInputDeviceFromName(const char* name, PaDeviceIndex& device, int& in_max); | |||
int GetOutputDeviceFromName(const char* name, PaDeviceIndex& device, int& out_max); | |||
int GetPreferredBufferSize(PaDeviceIndex id); | |||
void DisplayDevicesNames(); | |||
bool IsDuplex(PaDeviceIndex id); | |||
@@ -98,15 +98,15 @@ PaError JackPortAudioDriver::OpenStream(jack_nframes_t buffer_size) | |||
inputParameters.channelCount = fCaptureChannels; | |||
inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | |||
inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO | |||
? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency | |||
? ((fPaDevices->GetHostFromDevice(fInputDevice) == "ASIO") ? 0 : Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency) | |||
: 0; | |||
inputParameters.hostApiSpecificStreamInfo = NULL; | |||
outputParameters.device = fOutputDevice; | |||
outputParameters.channelCount = fPlaybackChannels; | |||
outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | |||
outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO | |||
? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency | |||
outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | |||
outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO | |||
? ((fPaDevices->GetHostFromDevice(fOutputDevice) == "ASIO") ? 0 : Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency) | |||
: 0; | |||
outputParameters.hostApiSpecificStreamInfo = NULL; | |||
@@ -167,17 +167,11 @@ int JackPortAudioDriver::Open(jack_nframes_t buffer_size, | |||
fCaptureLatency = capture_latency; | |||
fPlaybackLatency = playback_latency; | |||
jack_log("JackPortAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s samplerate = %ld", | |||
buffer_size, inchannels, outchannels, capture_driver_uid, playback_driver_uid, samplerate); | |||
// Generic JackAudioDriver Open | |||
if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, | |||
capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) { | |||
return -1; | |||
} | |||
//get devices | |||
// Get devices | |||
if (capturing) { | |||
if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0) { | |||
goto error; | |||
@@ -188,10 +182,22 @@ int JackPortAudioDriver::Open(jack_nframes_t buffer_size, | |||
goto error; | |||
} | |||
} | |||
// If ASIO, request for preferred size (assuming fInputDevice and fOutputDevice are the same) | |||
if (buffer_size == 0) { | |||
buffer_size = fPaDevices->GetPreferredBufferSize(fInputDevice); | |||
jack_log("JackPortAudioDriver::Open preferred buffer_size = %d", buffer_size); | |||
} | |||
// Generic JackAudioDriver Open | |||
if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, | |||
capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) { | |||
return -1; | |||
} | |||
jack_log("JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice); | |||
//default channels number required | |||
// Default channels number required | |||
if (inchannels == 0) { | |||
jack_log("JackPortAudioDriver::Open setup max in channels = %ld", in_max); | |||
inchannels = in_max; | |||
@@ -201,7 +207,7 @@ int JackPortAudioDriver::Open(jack_nframes_t buffer_size, | |||
outchannels = out_max; | |||
} | |||
//too many channels required, take max available | |||
// Too many channels required, take max available | |||
if (inchannels > in_max) { | |||
jack_error("This device has only %d available input channels.", in_max); | |||
inchannels = in_max; | |||
@@ -244,10 +250,9 @@ error: | |||
int JackPortAudioDriver::Close() | |||
{ | |||
// Generic audio driver close | |||
int res = JackAudioDriver::Close(); | |||
jack_log("JackPortAudioDriver::Close"); | |||
Pa_CloseStream(fStream); | |||
return res; | |||
int res = JackAudioDriver::Close(); | |||
return (Pa_CloseStream(fStream) != paNoError) ? -1 : res; | |||
} | |||
int JackPortAudioDriver::Attach() | |||
@@ -258,8 +263,7 @@ int JackPortAudioDriver::Attach() | |||
if (fInputDevice != paNoDevice && fPaDevices->GetHostFromDevice(fInputDevice) == "ASIO") { | |||
for (int i = 0; i < fCaptureChannels; i++) { | |||
PaError err = PaAsio_GetInputChannelName(fInputDevice, i, &alias); | |||
if (err == paNoError) { | |||
if (PaAsio_GetInputChannelName(fInputDevice, i, &alias) == paNoError) { | |||
JackPort* port = fGraphManager->GetPort(fCapturePortList[i]); | |||
port->SetAlias(alias); | |||
} | |||
@@ -268,8 +272,7 @@ int JackPortAudioDriver::Attach() | |||
if (fOutputDevice != paNoDevice && fPaDevices->GetHostFromDevice(fOutputDevice) == "ASIO") { | |||
for (int i = 0; i < fPlaybackChannels; i++) { | |||
PaError err = PaAsio_GetInputChannelName(fOutputDevice, i, &alias); | |||
if (err == paNoError) { | |||
if (PaAsio_GetOutputChannelName(fOutputDevice, i, &alias) == paNoError) { | |||
JackPort* port = fGraphManager->GetPort(fPlaybackPortList[i]); | |||
port->SetAlias(alias); | |||
} | |||
@@ -287,8 +290,7 @@ int JackPortAudioDriver::Start() | |||
{ | |||
jack_log("JackPortAudioDriver::Start"); | |||
if (JackAudioDriver::Start() >= 0) { | |||
PaError err = Pa_StartStream(fStream); | |||
if (err == paNoError) { | |||
if (Pa_StartStream(fStream) == paNoError) { | |||
return 0; | |||
} | |||
JackAudioDriver::Stop(); | |||
@@ -299,8 +301,7 @@ int JackPortAudioDriver::Start() | |||
int JackPortAudioDriver::Stop() | |||
{ | |||
jack_log("JackPortAudioDriver::Stop"); | |||
PaError err = Pa_StopStream(fStream); | |||
int res = (err == paNoError) ? 0 : -1; | |||
int res = (Pa_StopStream(fStream) == paNoError) ? 0 : -1; | |||
if (JackAudioDriver::Stop() < 0) { | |||
res = -1; | |||
} | |||
@@ -362,7 +363,7 @@ extern "C" | |||
jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); | |||
value.ui = 512U; | |||
jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", "Frames per period. If 0 and ASIO driver, will take preferred value"); | |||
jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "PortAudio device name", NULL); | |||
@@ -13,7 +13,7 @@ import re | |||
import Logs | |||
import sys | |||
VERSION='1.9.9' | |||
VERSION='1.9.9.5' | |||
APPNAME='jack' | |||
JACK_API_VERSION = '0.1.0' | |||
@@ -76,6 +76,7 @@ def options(opt): | |||
opt.add_option('--firewire', action='store_true', default=False, help='Enable FireWire driver (FFADO)') | |||
opt.add_option('--freebob', action='store_true', default=False, help='Enable FreeBob driver') | |||
opt.add_option('--alsa', action='store_true', default=False, help='Enable ALSA driver') | |||
opt.add_option('--autostart', type='string', default="default", help='Autostart method. Possible values: "default", "classic", "dbus", "none"') | |||
opt.sub_options('dbus') | |||
def configure(conf): | |||
@@ -116,7 +117,7 @@ def configure(conf): | |||
# conf.check_tool('compiler_cc') | |||
conf.env.append_unique('CXXFLAGS', '-Wall') | |||
conf.env.append_unique('CCFLAGS', '-Wall') | |||
conf.env.append_unique('CFLAGS', '-Wall') | |||
conf.sub_config('common') | |||
if conf.env['IS_LINUX']: | |||
@@ -173,9 +174,18 @@ def configure(conf): | |||
conf.define('HAVE_CELT_API_0_7', 0) | |||
conf.define('HAVE_CELT_API_0_5', 0) | |||
conf.env['WITH_OPUS'] = False | |||
if conf.check_cfg(package='opus', atleast_version='0.9.0' , args='--cflags --libs', mandatory=False): | |||
if conf.check_cc(header_name='opus/opus_custom.h', mandatory=False): | |||
conf.define('HAVE_OPUS', 1) | |||
conf.env['WITH_OPUS'] = True | |||
conf.env['LIB_PTHREAD'] = ['pthread'] | |||
conf.env['LIB_DL'] = ['dl'] | |||
conf.env['LIB_RT'] = ['rt'] | |||
conf.env['LIB_M'] = ['m'] | |||
conf.env['LIB_STDC++'] = ['stdc++'] | |||
conf.env['JACK_API_VERSION'] = JACK_API_VERSION | |||
conf.env['JACK_VERSION'] = VERSION | |||
@@ -202,9 +212,30 @@ def configure(conf): | |||
if conf.env['BUILD_DEBUG']: | |||
conf.env.append_unique('CXXFLAGS', '-g') | |||
conf.env.append_unique('CCFLAGS', '-g') | |||
conf.env.append_unique('CFLAGS', '-g') | |||
conf.env.append_unique('LINKFLAGS', '-g') | |||
if not Options.options.autostart in ["default", "classic", "dbus", "none"]: | |||
conf.fatal("Invalid autostart value \"" + Options.options.autostart + "\"") | |||
if Options.options.autostart == "default": | |||
if conf.env['BUILD_JACKDBUS'] == True and conf.env['BUILD_JACKD'] == False: | |||
conf.env['AUTOSTART_METHOD'] = "dbus" | |||
else: | |||
conf.env['AUTOSTART_METHOD'] = "classic" | |||
else: | |||
conf.env['AUTOSTART_METHOD'] = Options.options.autostart | |||
if conf.env['AUTOSTART_METHOD'] == "dbus" and not conf.env['BUILD_JACKDBUS']: | |||
conf.fatal("D-Bus autostart mode was specified but jackdbus will not be built") | |||
if conf.env['AUTOSTART_METHOD'] == "classic" and not conf.env['BUILD_JACKD']: | |||
conf.fatal("Classic autostart mode was specified but jackd will not be built") | |||
if conf.env['AUTOSTART_METHOD'] == "dbus": | |||
conf.define('USE_LIBDBUS_AUTOLAUNCH', 1) | |||
elif conf.env['AUTOSTART_METHOD'] == "classic": | |||
conf.define('USE_CLASSIC_AUTOLAUNCH', 1) | |||
conf.define('CLIENT_NUM', Options.options.clients) | |||
conf.define('PORT_NUM_FOR_CLIENT', Options.options.application_ports) | |||
@@ -215,11 +246,9 @@ def configure(conf): | |||
conf.define('JACKMP', 1) | |||
if conf.env['BUILD_JACKDBUS'] == True: | |||
conf.define('JACK_DBUS', 1) | |||
if conf.env['BUILD_JACKD'] == False: | |||
conf.define('USE_LIBDBUS_AUTOLAUNCH', 1) | |||
if conf.env['BUILD_WITH_PROFILE'] == True: | |||
conf.define('JACK_MONITOR', 1) | |||
conf.write_config_header('config.h') | |||
conf.write_config_header('config.h', remove=False) | |||
svnrev = None | |||
if os.access('svnversion.h', os.R_OK): | |||
@@ -228,15 +257,13 @@ def configure(conf): | |||
if m != None: | |||
svnrev = m.group(1) | |||
conf.env.append_unique('LINKFLAGS', ['-lm', '-lstdc++']) | |||
if Options.options.mixed == True: | |||
env_variant2 = conf.env.copy() | |||
conf.set_env_name('lib32', env_variant2) | |||
env_variant2.set_variant('lib32') | |||
conf.setenv('lib32') | |||
conf.env.append_unique('CXXFLAGS', '-m32') | |||
conf.env.append_unique('CCFLAGS', '-m32') | |||
conf.env.append_unique('CFLAGS', '-m32') | |||
conf.env.append_unique('LINKFLAGS', '-m32') | |||
if Options.options.libdir32: | |||
conf.env['LIBDIR'] = Options.options.libdir32 | |||
@@ -260,15 +287,17 @@ def configure(conf): | |||
display_msg("Library directory", conf.env['LIBDIR'], 'CYAN') | |||
display_msg("Drivers directory", conf.env['ADDON_DIR'], 'CYAN') | |||
display_feature('Build debuggable binaries', conf.env['BUILD_DEBUG']) | |||
display_msg('C compiler flags', repr(conf.env['CCFLAGS'])) | |||
display_msg('C compiler flags', repr(conf.env['CFLAGS'])) | |||
display_msg('C++ compiler flags', repr(conf.env['CXXFLAGS'])) | |||
display_msg('Linker flags', repr(conf.env['LINKFLAGS'])) | |||
display_feature('Build doxygen documentation', conf.env['BUILD_DOXYGEN_DOCS']) | |||
display_feature('Build Opus netjack2', conf.env['WITH_OPUS']) | |||
display_feature('Build with engine profiling', conf.env['BUILD_WITH_PROFILE']) | |||
display_feature('Build with 32/64 bits mixed mode', conf.env['BUILD_WITH_32_64']) | |||
display_feature('Build standard JACK (jackd)', conf.env['BUILD_JACKD']) | |||
display_feature('Build D-Bus JACK (jackdbus)', conf.env['BUILD_JACKDBUS']) | |||
display_msg('Autostart method', conf.env['AUTOSTART_METHOD']) | |||
if conf.env['BUILD_JACKDBUS'] and conf.env['BUILD_JACKD']: | |||
print(Logs.colors.RED + 'WARNING !! mixing both jackd and jackdbus may cause issues:' + Logs.colors.NORMAL) | |||