git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1972 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.71
@@ -23,6 +23,7 @@ Nedko Arnaudov | |||
* Add test for jack_cycle_wait, jack_cycle_wait and jack_set_process_thread API. | |||
* Add jack_set_process_thread in wrapper library. | |||
* Correct all backend playback port latency in case of "asynchronous" mode (1 buffer more). | |||
2008-03-12 Stephane Letz <letz@grame.fr> | |||
@@ -48,10 +48,10 @@ extern "C" | |||
{ | |||
#endif | |||
EXPORT jack_client_t * jack_client_open_aux (const char *client_name, | |||
EXPORT jack_client_t * jack_client_open_aux (const char *client_name, | |||
jack_options_t options, | |||
jack_status_t *status, va_list ap); | |||
EXPORT jack_client_t * jack_client_open (const char *client_name, | |||
EXPORT jack_client_t * jack_client_open (const char *client_name, | |||
jack_options_t options, | |||
jack_status_t *status, ...); | |||
EXPORT jack_client_t * jack_client_new (const char *client_name); | |||
@@ -167,7 +167,7 @@ extern "C" | |||
EXPORT float jack_cpu_load (jack_client_t *client); | |||
EXPORT pthread_t jack_client_thread_id (jack_client_t *); | |||
EXPORT void jack_set_error_function (void (*func)(const char *)); | |||
EXPORT void jack_set_info_function (void (*func)(const char *)); | |||
EXPORT void jack_set_info_function (void (*func)(const char *)); | |||
EXPORT float jack_get_max_delayed_usecs (jack_client_t *client); | |||
EXPORT float jack_get_xrun_delayed_usecs (jack_client_t *client); | |||
@@ -215,7 +215,7 @@ extern "C" | |||
const char *client_name, | |||
jack_options_t options, | |||
jack_status_t *status, ...); | |||
EXPORT jack_intclient_t jack_internal_client_load_aux (jack_client_t *client, | |||
EXPORT jack_intclient_t jack_internal_client_load_aux (jack_client_t *client, | |||
const char *client_name, | |||
jack_options_t options, | |||
jack_status_t *status, va_list ap); | |||
@@ -274,7 +274,7 @@ EXPORT jack_client_t* jack_client_new(const char* client_name) | |||
int options = JackUseExactName; | |||
if (getenv("JACK_START_SERVER") == NULL) | |||
options |= JackNoStartServer; | |||
va_list ap; | |||
va_list ap; | |||
return jack_client_open_aux(client_name, (jack_options_t)options, NULL, ap); | |||
} | |||
@@ -1628,9 +1628,9 @@ EXPORT jack_intclient_t jack_internal_client_load_aux(jack_client_t* ext_client, | |||
EXPORT jack_intclient_t jack_internal_client_load(jack_client_t *client, const char *client_name, jack_options_t options, jack_status_t *status, ...) | |||
{ | |||
va_list ap; | |||
va_list ap; | |||
va_start(ap, status); | |||
jack_intclient_t res = jack_internal_client_load_aux(client, client_name, options, status, ap); | |||
jack_intclient_t res = jack_internal_client_load_aux(client, client_name, options, status, ap); | |||
va_end(ap); | |||
return res; | |||
} | |||
@@ -118,7 +118,8 @@ int JackAudioDriver::Attach() | |||
} | |||
port = fGraphManager->GetPort(port_index); | |||
port->SetAlias(alias); | |||
port->SetLatency(fEngineControl->fBufferSize + fPlaybackLatency); | |||
// Add more latency if "async" mode is used... | |||
port->SetLatency(fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + fPlaybackLatency); | |||
fPlaybackPortList[i] = port_index; | |||
jack_log("JackAudioDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); | |||
@@ -250,9 +250,9 @@ int JackClient::Activate() | |||
#endif | |||
*/ | |||
//if (fProcess || fThreadFun) | |||
if (StartThread() < 0) | |||
return -1; | |||
//if (fProcess || fThreadFun) | |||
if (StartThread() < 0) | |||
return -1; | |||
int result = -1; | |||
fChannel->ClientActivate(GetClientControl()->fRefNum, &result); | |||
@@ -293,8 +293,8 @@ int JackClient::Deactivate() | |||
fThread->Kill(); | |||
#endif | |||
*/ | |||
//if (fProcess || fThreadFun) | |||
fThread->Kill(); | |||
//if (fProcess || fThreadFun) | |||
fThread->Kill(); | |||
return result; | |||
} | |||
@@ -317,9 +317,9 @@ bool JackClient::Init() | |||
int JackClient::StartThread() | |||
{ | |||
jack_log("JackClient::StartThread : period = %ld computation = %ld constraint = %ld", | |||
long(int64_t(GetEngineControl()->fPeriod) / 1000.0f), | |||
long(int64_t(GetEngineControl()->fComputation) / 1000.0f), | |||
long(int64_t(GetEngineControl()->fConstraint) / 1000.0f)); | |||
long(int64_t(GetEngineControl()->fPeriod) / 1000.0f), | |||
long(int64_t(GetEngineControl()->fComputation) / 1000.0f), | |||
long(int64_t(GetEngineControl()->fConstraint) / 1000.0f)); | |||
// Will do "something" on OSX only... | |||
fThread->SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); | |||
@@ -344,9 +344,9 @@ int JackClient::StartThread() | |||
bool JackClient::Execute() | |||
{ | |||
if (fThreadFun) { | |||
// Execute a dummy cycle to be sure thread has the correct properties (ensure thread creation is finished) | |||
WaitSync(); | |||
SignalSync(); | |||
// Execute a dummy cycle to be sure thread has the correct properties (ensure thread creation is finished) | |||
WaitSync(); | |||
SignalSync(); | |||
fThreadFun(fThreadFunArg); | |||
} else { | |||
if (WaitFirstSync()) | |||
@@ -797,9 +797,9 @@ int JackClient::SetProcessCallback(JackProcessCallback callback, void *arg) | |||
jack_error("You cannot set callbacks on an active client"); | |||
return -1; | |||
} else if (fThreadFun) { | |||
jack_error ("A thread callback has already been setup, both models cannot be used at the same time!"); | |||
return -1; | |||
} else { | |||
jack_error ("A thread callback has already been setup, both models cannot be used at the same time!"); | |||
return -1; | |||
} else { | |||
fProcessArg = arg; | |||
fProcess = callback; | |||
return 0; | |||
@@ -920,9 +920,9 @@ int JackClient::SetProcessThread(JackThreadCallback fun, void *arg) | |||
jack_error("You cannot set callbacks on an active client"); | |||
return -1; | |||
} else if (fProcess) { | |||
jack_error ("A process callback has already been setup, both models cannot be used at the same time!"); | |||
return -1; | |||
} else { | |||
jack_error ("A process callback has already been setup, both models cannot be used at the same time!"); | |||
return -1; | |||
} else { | |||
fThreadFun = fun; | |||
fThreadFunArg = arg; | |||
return 0; | |||
@@ -91,7 +91,7 @@ class JackDebugClient : public JackClient | |||
int PortConnect(const char* src, const char* dst); | |||
int PortDisconnect(const char* src, const char* dst); | |||
int PortDisconnect(jack_port_id_t src); | |||
int PortDisconnect(jack_port_id_t src); | |||
int PortIsMine(jack_port_id_t port_index); | |||
@@ -555,8 +555,8 @@ int JackEngine::ClientInternalClose(int refnum, bool wait) | |||
int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wait) | |||
{ | |||
jack_log("JackEngine::ClientCloseAux ref = %ld name = %s", | |||
refnum, | |||
(client->GetClientControl()) ? client->GetClientControl()->fName : "No name"); | |||
refnum, | |||
(client->GetClientControl()) ? client->GetClientControl()->fName : "No name"); | |||
// Remove the client from the table | |||
ReleaseRefnum(refnum); | |||
@@ -275,7 +275,7 @@ int JackGraphManager::ComputeTotalLatencies() | |||
void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size) | |||
{ | |||
JackLock lock (this); | |||
jack_log("JackGraphManager::SetBufferSize size = %ld", (long int)buffer_size); | |||
jack_log("JackGraphManager::SetBufferSize size = %ld", buffer_size); | |||
jack_port_id_t port_index; | |||
for (port_index = FIRST_AVAILABLE_PORT; port_index < PORT_NUM; port_index++) { | |||
@@ -704,12 +704,12 @@ const char** JackGraphManager::GetConnections(jack_port_id_t port_index) | |||
next_index = GetCurrentIndex(); | |||
} while (cur_index != next_index); // Until a coherent state has been read | |||
if (res[0]) { // at least one connection | |||
return res; | |||
} else { // empty array, should return NULL | |||
free(res); | |||
return NULL; | |||
} | |||
if (res[0]) { // at least one connection | |||
return res; | |||
} else { // empty array, should return NULL | |||
free(res); | |||
return NULL; | |||
} | |||
} | |||
// Client | |||
@@ -56,11 +56,11 @@ JackSynchro** GetSynchroTable() | |||
JackInternalClient::JackInternalClient(JackServer* server, JackSynchro** table): JackClient(table) | |||
{ | |||
fClientControl = new JackClientControl(); | |||
/* | |||
TODO: here we use a "direct access" to server internal, which is not safe if library clients access the server using | |||
the "command thread" at the same time. So using the "command thread" also for internal clients would be safer. | |||
We may want to keep the "direct access" to server internal mode for "server embeded in client process" kind of use. | |||
*/ | |||
/* | |||
TODO: here we use a "direct access" to server internal, which is not safe if library clients access the server using | |||
the "command thread" at the same time. So using the "command thread" also for internal clients would be safer. | |||
We may want to keep the "direct access" to server internal mode for "server embeded in client process" kind of use. | |||
*/ | |||
fChannel = new JackInternalClientChannel(server); | |||
} | |||
@@ -39,10 +39,10 @@ extern "C" | |||
{ | |||
#endif | |||
EXPORT jack_client_t * jack_client_open_aux (const char *client_name, | |||
EXPORT jack_client_t * jack_client_open_aux (const char *client_name, | |||
jack_options_t options, | |||
jack_status_t *status, va_list ap); | |||
EXPORT jack_client_t * jack_client_open (const char *client_name, | |||
EXPORT jack_client_t * jack_client_open (const char *client_name, | |||
jack_options_t options, | |||
jack_status_t *status, ...); | |||
EXPORT int jack_client_close (jack_client_t *client); | |||
@@ -65,8 +65,8 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||
jack_error("jack_client_open called with a NULL client_name"); | |||
return NULL; | |||
} | |||
jack_log("jack_client_open %s", ext_client_name); | |||
jack_log("jack_client_open %s", ext_client_name); | |||
JackTools::RewriteName(ext_client_name, client_name); | |||
if (status == NULL) /* no status from caller? */ | |||
@@ -82,9 +82,9 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||
/* parse variable arguments */ | |||
if (ap) | |||
jack_varargs_parse(options, ap, &va); | |||
jack_varargs_parse(options, ap, &va); | |||
JackLibGlobals::Init(); // jack library initialisation | |||
JackLibGlobals::Init(); // jack library initialisation | |||
#ifndef WIN32 | |||
if (try_start_server(&va, options, status)) { | |||
@@ -118,7 +118,7 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||
EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | |||
{ | |||
va_list ap; | |||
va_list ap; | |||
va_start(ap, status); | |||
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap); | |||
va_end(ap); | |||
@@ -91,7 +91,7 @@ class JackProcessSync : public JackSyncInterface | |||
gettimeofday(&T1, 0); | |||
pthread_mutex_unlock(&fLock); | |||
jack_log("JackProcessSync::Wait finished delta = %5.1lf", | |||
(1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); | |||
(1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); | |||
return (res == 0); | |||
} | |||
@@ -158,7 +158,7 @@ class JackInterProcessSync : public JackSyncInterface | |||
bool res = fSynchro->TimedWait(usec); | |||
gettimeofday(&T1, 0); | |||
jack_log("JackInterProcessSync::Wait finished delta = %5.1lf", | |||
(1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); | |||
(1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); | |||
return res; | |||
} | |||
@@ -54,7 +54,7 @@ class EXPORT JackServer | |||
JackEngineControl* fEngineControl; | |||
JackGraphManager* fGraphManager; | |||
JackServerChannelInterface* fChannel; | |||
JackConnectionManager fConnectionState; | |||
JackConnectionManager fConnectionState; | |||
JackSynchro* fSynchroTable[CLIENT_NUM]; | |||
bool fFreewheel; | |||
long fLoopback; | |||
@@ -42,7 +42,7 @@ extern "C" | |||
{ | |||
#endif | |||
EXPORT jack_client_t * jack_client_open_aux (const char *client_name, | |||
EXPORT jack_client_t * jack_client_open_aux (const char *client_name, | |||
jack_options_t options, | |||
jack_status_t *status, va_list ap); | |||
EXPORT jack_client_t * jack_client_open (const char *client_name, | |||
@@ -62,14 +62,14 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||
jack_status_t my_status; | |||
JackClient* client; | |||
char client_name[JACK_CLIENT_NAME_SIZE]; | |||
if (ext_client_name == NULL) { | |||
if (ext_client_name == NULL) { | |||
jack_error("jack_client_open called with a NULL client_name"); | |||
return NULL; | |||
} | |||
jack_log("jack_client_open %s", ext_client_name); | |||
JackTools::RewriteName(ext_client_name, client_name); | |||
jack_log("jack_client_open %s", ext_client_name); | |||
JackTools::RewriteName(ext_client_name, client_name); | |||
if (status == NULL) /* no status from caller? */ | |||
status = &my_status; /* use local status word */ | |||
@@ -83,9 +83,9 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||
} | |||
/* parse variable arguments */ | |||
if (ap) | |||
jack_varargs_parse(options, ap, &va); | |||
if (ap) | |||
jack_varargs_parse(options, ap, &va); | |||
if (!JackServerGlobals::Init()) { // jack server initialisation | |||
int my_status1 = (JackFailure | JackServerError); | |||
*status = (jack_status_t)my_status1; | |||
@@ -116,7 +116,7 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||
EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | |||
{ | |||
va_list ap; | |||
va_list ap; | |||
va_start(ap, status); | |||
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap); | |||
va_end(ap); | |||
@@ -244,7 +244,7 @@ bool JackServerGlobals::Init() | |||
if (driver_nargs == 0) { | |||
jack_error("No driver specified ... hmm. JACK won't do" | |||
" anything when run like this."); | |||
" anything when run like this."); | |||
goto error; | |||
} | |||
@@ -72,8 +72,7 @@ char* JackTools::ServerDir(const char* server_name, char* server_dir) | |||
} | |||
void JackTools::CleanupFiles(const char* server_name) | |||
{ | |||
} | |||
{} | |||
int JackTools::GetTmpdir() | |||
{ | |||
@@ -86,7 +86,7 @@ extern "C" | |||
/* JackPositionTimecode fields: (EXPERIMENTAL: could change) */ | |||
double frame_time; /**< current time in seconds */ | |||
double next_time; /**< next sequential frame_time | |||
(unless repositioned) */ | |||
(unless repositioned) */ | |||
/* For binary compatibility, new fields should be allocated from | |||
* this padding area with new valid bits controlling access, so | |||
@@ -2145,7 +2145,9 @@ int JackAlsaDriver::Attach() | |||
} | |||
port = fGraphManager->GetPort(port_index); | |||
port->SetAlias(alias); | |||
port->SetLatency((alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) + alsa_driver->playback_frame_latency); | |||
// Add one buffer more latency if "async" mode is used... | |||
port->SetLatency((alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) + | |||
((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + alsa_driver->playback_frame_latency); | |||
fPlaybackPortList[i] = port_index; | |||
jack_log("JackAudioDriver::Attach fPlaybackPortList[i] %ld ", port_index); | |||
@@ -84,8 +84,7 @@ extern "C" | |||
void sample_merge_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
static __inline__ void | |||
sample_merge (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) | |||
{ | |||
sample_merge (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) { | |||
while (cnt--) { | |||
*dst += *src; | |||
dst++; | |||
@@ -94,8 +93,7 @@ extern "C" | |||
} | |||
static __inline__ void | |||
sample_memcpy (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) | |||
{ | |||
sample_memcpy (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) { | |||
memcpy (dst, src, cnt * sizeof (jack_default_audio_sample_t)); | |||
} | |||
@@ -585,7 +585,8 @@ int JackFFADODriver::Attach() | |||
} | |||
port = fGraphManager->GetPort(port_index); | |||
port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + driver->playback_frame_latency); | |||
// Add one buffer more latency if "async" mode is used... | |||
port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency); | |||
fPlaybackPortList[chn] = port_index; | |||
jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index); | |||
fPlaybackChannels++; | |||
@@ -771,7 +771,8 @@ int JackFreebobDriver::Attach() | |||
return -1; | |||
} | |||
port = fGraphManager->GetPort(port_index); | |||
port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + driver->playback_frame_latency); | |||
// Add one buffer more latency if "async" mode is used... | |||
port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency); | |||
fPlaybackPortList[i] = port_index; | |||
jack_log("JackFreebobDriver::Attach fPlaybackPortList[i] %ld ", port_index); | |||
driver->playback_nchannels_audio++; | |||
@@ -28,8 +28,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "driver_interface.h" | |||
#include <iostream> | |||
#define IO_CPU 0 | |||
namespace Jack | |||
{ | |||
@@ -421,7 +419,7 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int* channe | |||
} | |||
JackCoreAudioDriver::JackCoreAudioDriver(const char* name, JackEngine* engine, JackSynchro** table) | |||
: JackAudioDriver(name, engine, table), fJackInputData(NULL), fDriverOutputData(NULL), fState(false) | |||
: JackAudioDriver(name, engine, table), fJackInputData(NULL), fDriverOutputData(NULL), fState(false), fIOUsage(1.f) | |||
{} | |||
JackCoreAudioDriver::~JackCoreAudioDriver() | |||
@@ -848,17 +846,14 @@ int JackCoreAudioDriver::AddListeners() | |||
return -1; | |||
} | |||
#if IO_CPU | |||
if (!fEngineControl->fSyncMode) { | |||
UInt32 outSize = sizeof(float); | |||
float iousage = 0.5f; | |||
err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyIOCycleUsage, outSize, &iousage); | |||
err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyIOCycleUsage, outSize, &fIOUsage); | |||
if (err != noErr) { | |||
jack_error("Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage"); | |||
printError(err); | |||
} | |||
} | |||
#endif | |||
return 0; | |||
} | |||
@@ -1032,7 +1027,8 @@ int JackCoreAudioDriver::Attach() | |||
port = fGraphManager->GetPort(port_index); | |||
port->SetAlias(alias); | |||
port->SetLatency(fEngineControl->fBufferSize + value1 + value2 + fPlaybackLatency); | |||
// Add more latency if "async" mode is used... | |||
port->SetLatency(fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency); | |||
fPlaybackPortList[i] = port_index; | |||
// Monitor ports | |||
@@ -71,6 +71,7 @@ class JackCoreAudioDriver : public JackAudioDriver | |||
char fPlaybackUID[256]; | |||
bool fMonitor; | |||
float fIOUsage; | |||
static OSStatus Render(void *inRefCon, | |||
AudioUnitRenderActionFlags *ioActionFlags, | |||
@@ -155,7 +155,7 @@ int JackMachThread::Kill() | |||
int JackMachThread::AcquireRealTime() | |||
{ | |||
jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld", | |||
long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); | |||
long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); | |||
return (fThread) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1; | |||
} | |||