git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3448 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
@@ -17,38 +17,55 @@ Nedko Arnaudov | |||
Fernando Lopez-Lezcano | |||
Romain Moret | |||
Florian Faber | |||
Michael Voigt | |||
Michael Voigt | |||
Torben Hohn | |||
--------------------------- | |||
Jackdmp changes log | |||
--------------------------- | |||
--------------------------- | |||
2009-03-10 Stephane Letz <letz@grame.fr> | |||
2009-03-19 Stephane Letz <letz@grame.fr> | |||
* Tim Blechmann optimization patch (inlining some heavy used methods). | |||
2009-03-12 Stephane Letz <letz@grame.fr> | |||
* Add -g (ring-buffer) parameter to netadapter. | |||
* Virtualize and allow overriding of thread creation function, to allow Wine support (from JACK1). | |||
2009-03-12 Stephane Letz <letz@grame.fr> | |||
* Try automatic adaptative mode in adapters. | |||
2009-03-11 Stephane Letz <letz@grame.fr> | |||
* Client incorrect re-naming fixed : now done at socket level also. | |||
2009-03-10 Stephane Letz <letz@grame.fr> | |||
* Add -g (ring-buffer) parameter to netadapter. | |||
* Automatic adaptative ringbuffer size mode when -g = 0. | |||
2009-03-09 Stephane Letz <letz@grame.fr> | |||
* Use Torben Hohn PI controler code for adapters (in progress). | |||
* Use Torben Hohn PI controler code for adapters (in progress). | |||
2009-03-05 Stephane Letz <letz@grame.fr> | |||
* Support for BIG_ENDIAN machines in NetJack2 for transport data. | |||
* Support for BIG_ENDIAN machines in NetJack2 for transport data. | |||
* Add auto_connect parameter in netmanager and netadapter. | |||
2009-03-03 Stephane Letz <letz@grame.fr> | |||
* More robust profiling tools when clients come and go. | |||
2009-03-01 Stephane Letz <letz@grame.fr> | |||
* Raise default port number to 1024. | |||
2009-02-27 Stephane Letz <letz@grame.fr> | |||
* Improve generated gnuplot files for adapting code. | |||
2009-02-25 Stephane Letz <letz@grame.fr> | |||
* Major cleanup in adapter code. | |||
@@ -57,8 +74,8 @@ Torben Hohn | |||
* Fix JackNetDriver::Close method. | |||
* For audio device reservation, add card_to_num function. | |||
* Fix buffer size and sample rate handling in JackAlsaAdapter. | |||
* Add control for adapter ringbuffer size. | |||
* Fix buffer size and sample rate handling in JackAlsaAdapter. | |||
* Add control for adapter ringbuffer size. | |||
* Fix JackAlsaAdapter.h for 64 bits compilation. | |||
2009-02-24 Stephane Letz <letz@grame.fr> | |||
@@ -219,10 +219,12 @@ extern "C" | |||
thread_routine routine, | |||
void *arg); | |||
EXPORT int jack_drop_real_time_scheduling (pthread_t thread); | |||
EXPORT int jack_client_stop_thread (jack_client_t* client, pthread_t thread); | |||
EXPORT int jack_client_kill_thread (jack_client_t* client, pthread_t thread); | |||
#ifndef WIN32 | |||
EXPORT void jack_set_thread_creator (jack_thread_creator_t jtc); | |||
#endif | |||
EXPORT char * jack_get_internal_client_name (jack_client_t *client, | |||
jack_intclient_t intclient); | |||
EXPORT jack_intclient_t jack_internal_client_handle (jack_client_t *client, | |||
@@ -1759,8 +1761,8 @@ EXPORT int jack_client_max_real_time_priority(jack_client_t* ext_client) | |||
JackEngineControl* control = GetEngineControl(); | |||
return (control->fRealTime) ? control->fMaxClientPriority : -1; | |||
} | |||
} | |||
} | |||
EXPORT int jack_acquire_real_time_scheduling(pthread_t thread, int priority) | |||
{ | |||
JackEngineControl* control = GetEngineControl(); | |||
@@ -1792,6 +1794,13 @@ EXPORT int jack_client_kill_thread(jack_client_t* client, pthread_t thread) | |||
return JackThread::KillImp(thread); | |||
} | |||
#ifndef WIN32 | |||
EXPORT void jack_set_thread_creator (jack_thread_creator_t jtc) | |||
{ | |||
JackGlobals::fJackThreadCreator = jtc; | |||
} | |||
#endif | |||
// intclient.h | |||
EXPORT int jack_internal_client_new (const char *client_name, | |||
const char *load_name, | |||
@@ -36,20 +36,21 @@ namespace Jack | |||
int JackAudioAdapter::Process (jack_nframes_t frames, void* arg) | |||
{ | |||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | |||
if (!adapter->fAudioAdapter->IsRunning()) | |||
return 0; | |||
float* inputBuffer[adapter->fAudioAdapter->GetInputs()]; | |||
float* outputBuffer[adapter->fAudioAdapter->GetOutputs()]; | |||
// Always clear output | |||
for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { | |||
inputBuffer[i] = (float*)jack_port_get_buffer(adapter->fCapturePortList[i], frames); | |||
memset(inputBuffer[i], 0, frames * sizeof(float)); | |||
} | |||
for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { | |||
outputBuffer[i] = (float*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); | |||
} | |||
adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames); | |||
return 0; | |||
return 0; | |||
} | |||
int JackAudioAdapter::BufferSize ( jack_nframes_t buffer_size, void* arg ) | |||
@@ -70,23 +71,23 @@ namespace Jack | |||
//JackAudioAdapter ********************************************************* | |||
JackAudioAdapter::JackAudioAdapter (jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params, bool system) | |||
JackAudioAdapter::JackAudioAdapter (jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params, bool system) | |||
:fJackClient(jack_client), fAudioAdapter(audio_io) | |||
{ | |||
const JSList* node; | |||
const jack_driver_param_t* param; | |||
fAutoConnect = false; | |||
for (node = params; node; node = jack_slist_next(node)) { | |||
param = (const jack_driver_param_t*) node->data; | |||
switch (param->character) { | |||
case 'c': | |||
fAutoConnect = param->value.i; | |||
fAutoConnect = true; | |||
break; | |||
} | |||
} | |||
} | |||
JackAudioAdapter::~JackAudioAdapter() | |||
{ | |||
// When called, Close has already been used for the client, thus ports are already unregistered. | |||
@@ -105,11 +106,11 @@ namespace Jack | |||
delete[] fCapturePortList; | |||
delete[] fPlaybackPortList; | |||
} | |||
void JackAudioAdapter::ConnectPorts() | |||
{ | |||
const char **ports; | |||
ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||
if (ports != NULL) { | |||
for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) { | |||
@@ -117,7 +118,7 @@ namespace Jack | |||
} | |||
free(ports); | |||
} | |||
ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||
if (ports != NULL) { | |||
for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) { | |||
@@ -137,7 +138,7 @@ namespace Jack | |||
char name[32]; | |||
jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs()); | |||
fAudioAdapter->Create(); | |||
//jack ports | |||
fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()]; | |||
fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()]; | |||
@@ -165,7 +166,7 @@ namespace Jack | |||
goto fail; | |||
if ( jack_activate ( fJackClient ) < 0 ) | |||
goto fail; | |||
if (fAutoConnect) | |||
ConnectPorts(); | |||
@@ -52,13 +52,12 @@ namespace Jack | |||
for (int i = 1; i < max; i++) | |||
{ | |||
fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n", | |||
fTable[i].delta, fTable[i+1].time1 - fTable[i].time1, | |||
fTable[i+1].time2 - fTable[i].time2, | |||
fTable[i].delta, fTable[i].time1, fTable[i].time2, | |||
fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2); | |||
} | |||
fclose(file); | |||
/* No used for now | |||
// No used for now | |||
// Adapter timing 1 | |||
file = fopen("AdapterTiming1.plot", "w"); | |||
fprintf(file, "set multiplot\n"); | |||
@@ -68,9 +67,9 @@ namespace Jack | |||
fprintf(file, "set xlabel \"audio cycles\"\n"); | |||
fprintf(file, "set ylabel \"frames\"\n"); | |||
fprintf(file, "plot "); | |||
sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,"); | |||
sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,"); | |||
fprintf(file, buffer); | |||
sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines"); | |||
sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines"); | |||
fprintf(file, buffer); | |||
fprintf(file, "\n unset multiplot\n"); | |||
@@ -89,8 +88,7 @@ namespace Jack | |||
fprintf(file, buffer); | |||
fclose(file); | |||
*/ | |||
// Adapter timing 2 | |||
file = fopen("AdapterTiming2.plot", "w"); | |||
fprintf(file, "set multiplot\n"); | |||
@@ -155,16 +153,32 @@ namespace Jack | |||
} | |||
#endif | |||
void JackAudioAdapterInterface::GrowRingBufferSize() | |||
{ | |||
fRingbufferCurSize *= 2; | |||
} | |||
void JackAudioAdapterInterface::AdaptRingBufferSize() | |||
{ | |||
if (fHostBufferSize > fAdaptedBufferSize) | |||
fRingbufferCurSize = 4 * fHostBufferSize; | |||
else | |||
fRingbufferCurSize = 4 * fAdaptedBufferSize; | |||
} | |||
void JackAudioAdapterInterface::ResetRingBuffers() | |||
{ | |||
if (fRingbufferCurSize > DEFAULT_RB_SIZE) | |||
fRingbufferCurSize = DEFAULT_RB_SIZE; | |||
for (int i = 0; i < fCaptureChannels; i++) | |||
fCaptureRingBuffer[i]->Reset(); | |||
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); | |||
for (int i = 0; i < fPlaybackChannels; i++) | |||
fPlaybackRingBuffer[i]->Reset(); | |||
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); | |||
} | |||
void JackAudioAdapterInterface::Reset() | |||
void JackAudioAdapterInterface::Reset() | |||
{ | |||
ResetRingBuffers(); | |||
fRunning = false; | |||
@@ -179,11 +193,25 @@ namespace Jack | |||
//ringbuffers | |||
fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; | |||
fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; | |||
for (int i = 0; i < fCaptureChannels; i++ ) | |||
fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality, fRingbufferSize); | |||
for (int i = 0; i < fPlaybackChannels; i++ ) | |||
fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality, fRingbufferSize); | |||
if (fAdaptative) { | |||
AdaptRingBufferSize(); | |||
jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize); | |||
} else { | |||
if (fRingbufferCurSize > DEFAULT_RB_SIZE) | |||
fRingbufferCurSize = DEFAULT_RB_SIZE; | |||
jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize); | |||
} | |||
for (int i = 0; i < fCaptureChannels; i++ ) { | |||
fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality); | |||
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); | |||
} | |||
for (int i = 0; i < fPlaybackChannels; i++ ) { | |||
fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality); | |||
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); | |||
} | |||
if (fCaptureChannels > 0) | |||
jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); | |||
if (fPlaybackChannels > 0) | |||
@@ -206,14 +234,14 @@ namespace Jack | |||
{ | |||
bool failure = false; | |||
fRunning = true; | |||
// Finer estimation of the position in the ringbuffer | |||
int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0; | |||
double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames); | |||
/* | |||
Finer estimation of the position in the ringbuffer ?? | |||
int delta_frames = (int)(float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f; | |||
double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetOffset() - delta_frames); | |||
*/ | |||
double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetOffset()); | |||
#ifdef JACK_MONITOR | |||
fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace()); | |||
#endif | |||
// Push/pull from ringbuffer | |||
for (int i = 0; i < fCaptureChannels; i++) { | |||
@@ -223,18 +251,17 @@ namespace Jack | |||
} | |||
for (int i = 0; i < fPlaybackChannels; i++) { | |||
fPlaybackRingBuffer[i]->SetRatio(1 / ratio); | |||
fPlaybackRingBuffer[i]->SetRatio(1/ratio); | |||
if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) | |||
failure = true; | |||
} | |||
#ifdef JACK_MONITOR | |||
fTable.Write(0, 0, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace()); | |||
#endif | |||
// Reset all ringbuffers in case of failure | |||
if (failure) { | |||
jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset"); | |||
if (fAdaptative) { | |||
GrowRingBufferSize(); | |||
jack_info("Ringbuffer size = %d frames", fRingbufferCurSize); | |||
} | |||
ResetRingBuffers(); | |||
return -1; | |||
} else { | |||
@@ -244,28 +271,24 @@ namespace Jack | |||
int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames) | |||
{ | |||
bool failure = false; | |||
fPullAndPushTime = GetMicroSeconds(); | |||
if (!fRunning) | |||
return 0; | |||
int res = 0; | |||
// Push/pull from ringbuffer | |||
for (int i = 0; i < fCaptureChannels; i++) { | |||
if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) | |||
failure = true; | |||
res = -1; | |||
} | |||
for (int i = 0; i < fPlaybackChannels; i++) { | |||
if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) | |||
failure = true; | |||
} | |||
// Reset all ringbuffers in case of failure | |||
if (failure) { | |||
jack_error("JackCallbackAudioAdapter::PullAndPush ringbuffer failure... reset"); | |||
Reset(); | |||
return -1; | |||
} else { | |||
return 0; | |||
res = -1; | |||
} | |||
return res; | |||
} | |||
} // namespace |
@@ -23,6 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackResampler.h" | |||
#include "JackFilters.h" | |||
#include "JackConstants.h" | |||
#include <stdio.h> | |||
namespace Jack | |||
{ | |||
@@ -89,12 +90,15 @@ namespace Jack | |||
JackResampler** fPlaybackRingBuffer; | |||
unsigned int fQuality; | |||
unsigned int fRingbufferSize; | |||
unsigned int fRingbufferCurSize; | |||
jack_time_t fPullAndPushTime; | |||
bool fRunning; | |||
bool fAdaptative; | |||
void ResetRingBuffers(); | |||
void AdaptRingBufferSize(); | |||
void GrowRingBufferSize(); | |||
public: | |||
@@ -107,9 +111,11 @@ namespace Jack | |||
fAdaptedSampleRate ( sample_rate ), | |||
fPIControler(sample_rate / sample_rate, 256), | |||
fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL), | |||
fQuality(0), fRingbufferSize(DEFAULT_RB_SIZE), | |||
fQuality(0), | |||
fRingbufferCurSize(DEFAULT_ADAPTATIVE_SIZE), | |||
fPullAndPushTime(0), | |||
fRunning(false) | |||
fRunning(false), | |||
fAdaptative(true) | |||
{} | |||
JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, | |||
jack_nframes_t host_sample_rate, | |||
@@ -123,7 +129,6 @@ namespace Jack | |||
fAdaptedSampleRate ( adapted_sample_rate ), | |||
fPIControler(host_sample_rate / host_sample_rate, 256), | |||
fQuality(0), | |||
fRingbufferSize(DEFAULT_RB_SIZE), | |||
fPullAndPushTime(0), | |||
fRunning ( false ) | |||
{} | |||
@@ -131,11 +136,6 @@ namespace Jack | |||
virtual ~JackAudioAdapterInterface() | |||
{} | |||
bool IsRunning() | |||
{ | |||
return fRunning; | |||
} | |||
virtual void Reset(); | |||
virtual void Create(); | |||
@@ -154,12 +154,16 @@ namespace Jack | |||
virtual int SetHostBufferSize ( jack_nframes_t buffer_size ) | |||
{ | |||
fHostBufferSize = buffer_size; | |||
if (fAdaptative) | |||
AdaptRingBufferSize(); | |||
return 0; | |||
} | |||
virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size ) | |||
{ | |||
fAdaptedBufferSize = buffer_size; | |||
if (fAdaptative) | |||
AdaptRingBufferSize(); | |||
return 0; | |||
} | |||
@@ -217,7 +221,7 @@ namespace Jack | |||
int PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames); | |||
int PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames); | |||
}; | |||
} | |||
@@ -674,13 +674,11 @@ int JackClient::TransportReposition(jack_position_t* pos) | |||
jack_transport_state_t JackClient::TransportQuery(jack_position_t* pos) | |||
{ | |||
jack_log("TransportQuery"); | |||
return GetEngineControl()->fTransport.Query(pos); | |||
} | |||
jack_nframes_t JackClient::GetCurrentTransportFrame() | |||
{ | |||
jack_log("GetCurrentTransportFrame"); | |||
return GetEngineControl()->fTransport.GetCurrentFrame(); | |||
} | |||
@@ -83,11 +83,6 @@ bool JackConnectionManager::IsLoopPathAux(int ref1, int ref2) const | |||
// External API | |||
//-------------- | |||
int JackConnectionManager::GetActivation(int refnum) const | |||
{ | |||
return fInputCounter[refnum].GetValue(); | |||
} | |||
/*! | |||
\brief Connect port_src to port_dst. | |||
*/ | |||
@@ -440,7 +440,12 @@ class SERVER_EXPORT JackConnectionManager | |||
void DirectConnect(int ref1, int ref2); | |||
void DirectDisconnect(int ref1, int ref2); | |||
int GetActivation(int refnum) const; | |||
int GetActivation(int refnum) const | |||
{ | |||
return fInputCounter[refnum].GetValue(); | |||
} | |||
// Graph | |||
void ResetGraph(JackClientTiming* timing); | |||
@@ -33,44 +33,6 @@ static inline jack_time_t JACK_MAX(jack_time_t a, jack_time_t b) | |||
return (a < b) ? b : a; | |||
} | |||
void JackEngineControl::CycleIncTime(jack_time_t callback_usecs) | |||
{ | |||
// Timer | |||
fFrameTimer.IncFrameTime(fBufferSize, callback_usecs, fPeriodUsecs); | |||
} | |||
void JackEngineControl::CycleBegin(JackClientInterface** table, | |||
JackGraphManager* manager, | |||
jack_time_t cur_cycle_begin, | |||
jack_time_t prev_cycle_end) | |||
{ | |||
fTransport.CycleBegin(fSampleRate, cur_cycle_begin); | |||
CalcCPULoad(table, manager, cur_cycle_begin, prev_cycle_end); | |||
#ifdef JACK_MONITOR | |||
fProfiler.Profile(table, manager, fPeriodUsecs, cur_cycle_begin, prev_cycle_end); | |||
#endif | |||
} | |||
void JackEngineControl::CycleEnd(JackClientInterface** table) | |||
{ | |||
fTransport.CycleEnd(table, fSampleRate, fBufferSize); | |||
} | |||
void JackEngineControl::InitFrameTime() | |||
{ | |||
fFrameTimer.InitFrameTime(); | |||
} | |||
void JackEngineControl::ResetFrameTime(jack_time_t cur_cycle_begin) | |||
{ | |||
fFrameTimer.ResetFrameTime(fSampleRate, cur_cycle_begin, fPeriodUsecs); | |||
} | |||
void JackEngineControl::ReadFrameTime(JackTimer* timer) | |||
{ | |||
fFrameTimer.ReadFrameTime(timer); | |||
} | |||
void JackEngineControl::CalcCPULoad(JackClientInterface** table, | |||
JackGraphManager* manager, | |||
jack_time_t cur_cycle_begin, | |||
@@ -126,9 +88,4 @@ void JackEngineControl::NotifyXRun(float delayed_usecs) | |||
fMaxDelayedUsecs = delayed_usecs; | |||
} | |||
void JackEngineControl::ResetXRun() | |||
{ | |||
fMaxDelayedUsecs = 0.f; | |||
} | |||
} // end of namespace |
@@ -119,18 +119,48 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem | |||
{} | |||
// Cycle | |||
void CycleIncTime(jack_time_t callback_usecs); | |||
void CycleBegin(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end); | |||
void CycleEnd(JackClientInterface** table); | |||
void CycleIncTime(jack_time_t callback_usecs) | |||
{ | |||
// Timer | |||
fFrameTimer.IncFrameTime(fBufferSize, callback_usecs, fPeriodUsecs); | |||
} | |||
void CycleBegin(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end) | |||
{ | |||
fTransport.CycleBegin(fSampleRate, cur_cycle_begin); | |||
CalcCPULoad(table, manager, cur_cycle_begin, prev_cycle_end); | |||
#ifdef JACK_MONITOR | |||
fProfiler.Profile(table, manager, fPeriodUsecs, cur_cycle_begin, prev_cycle_end); | |||
#endif | |||
} | |||
void CycleEnd(JackClientInterface** table) | |||
{ | |||
fTransport.CycleEnd(table, fSampleRate, fBufferSize); | |||
} | |||
// Timer | |||
void InitFrameTime(); | |||
void ResetFrameTime(jack_time_t callback_usecs); | |||
void ReadFrameTime(JackTimer* timer); | |||
void InitFrameTime() | |||
{ | |||
fFrameTimer.InitFrameTime(); | |||
} | |||
void ResetFrameTime(jack_time_t callback_usecs) | |||
{ | |||
fFrameTimer.ResetFrameTime(fSampleRate, callback_usecs, fPeriodUsecs); | |||
} | |||
void ReadFrameTime(JackTimer* timer) | |||
{ | |||
fFrameTimer.ReadFrameTime(timer); | |||
} | |||
// XRun | |||
void NotifyXRun(float delayed_usecs); | |||
void ResetXRun(); | |||
void ResetXRun() | |||
{ | |||
fMaxDelayedUsecs = 0.f; | |||
} | |||
// Private | |||
void CalcCPULoad(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end); | |||
@@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
namespace Jack | |||
{ | |||
#define TIME_POINTS 125000 | |||
#define TIME_POINTS 100000 | |||
#define FAILURE_TIME_POINTS 10000 | |||
#define FAILURE_WINDOW 10 | |||
#define MEASURED_CLIENTS 32 | |||
@@ -263,20 +263,21 @@ namespace Jack | |||
static_resample_factor = resample_factor; | |||
} | |||
/* | |||
double GetRatio(int fill_level) | |||
{ | |||
double offset = fill_level; | |||
// Save offset. | |||
offset_array[(offset_differential_index++) % smooth_size] = offset; | |||
// Build the mean of the windowed offset array basically fir lowpassing. | |||
double smooth_offset = 0.0; | |||
for (int i = 0; i < smooth_size; i++) { | |||
smooth_offset += offset_array[(i + offset_differential_index - 1) % smooth_size] * window_array[i]; | |||
} | |||
smooth_offset /= double(smooth_size); | |||
// This is the integral of the smoothed_offset | |||
offset_integral += smooth_offset; | |||
@@ -284,13 +285,13 @@ namespace Jack | |||
// It only used in the P component and the I component is used for the fine tuning anyways. | |||
if (fabs(smooth_offset) < pclamp) | |||
smooth_offset = 0.0; | |||
// Ok, now this is the PI controller. | |||
// u(t) = K * (e(t) + 1/T \int e(t') dt') | |||
// Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T | |||
double current_resample_factor | |||
= static_resample_factor - smooth_offset / catch_factor - offset_integral / catch_factor / catch_factor2; | |||
// Now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt. | |||
current_resample_factor = floor((current_resample_factor - resample_mean) * controlquant + 0.5) / controlquant + resample_mean; | |||
@@ -298,6 +299,21 @@ namespace Jack | |||
resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor; | |||
return current_resample_factor; | |||
} | |||
*/ | |||
double GetRatio(int error) | |||
{ | |||
double smooth_offset = error; | |||
// This is the integral of the smoothed_offset | |||
offset_integral += smooth_offset; | |||
// Ok, now this is the PI controller. | |||
// u(t) = K * (e(t) + 1/T \int e(t') dt') | |||
// Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T | |||
return static_resample_factor - smooth_offset/catch_factor - offset_integral/catch_factor/catch_factor2; | |||
} | |||
void OurOfBounds() | |||
{ | |||
@@ -73,7 +73,7 @@ class SERVER_EXPORT JackTimer | |||
\brief A class using the JackAtomicState to manage jack time. | |||
*/ | |||
class JackFrameTimer : public JackAtomicState<JackTimer> | |||
class SERVER_EXPORT JackFrameTimer : public JackAtomicState<JackTimer> | |||
{ | |||
private: | |||
@@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
@@ -32,4 +32,8 @@ JackMutex* JackGlobals::fOpenMutex = new JackMutex(); | |||
bool JackGlobals::fServerRunning = false; | |||
JackClient* JackGlobals::fClientTable[CLIENT_NUM] = {}; | |||
#ifndef WIN32 | |||
jack_thread_creator_t JackGlobals::fJackThreadCreator = pthread_create; | |||
#endif | |||
} // end of namespace |
@@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
@@ -36,7 +36,10 @@ struct JackGlobals { | |||
static JackMutex* fOpenMutex; | |||
static bool fServerRunning; | |||
static JackClient* fClientTable[]; | |||
#ifndef WIN32 | |||
static jack_thread_creator_t fJackThreadCreator; | |||
#endif | |||
}; | |||
} // end of namespace | |||
@@ -101,11 +101,6 @@ int JackGraphManager::SuspendRefNum(JackClientControl* control, JackSynchro* tab | |||
return manager->SuspendRefNum(control, table, fClientTiming, usec); | |||
} | |||
JackClientTiming* JackGraphManager::GetClientTiming(int ref) | |||
{ | |||
return &fClientTiming[ref]; | |||
} | |||
// Server | |||
void JackGraphManager::DirectConnect(int ref1, int ref2) | |||
{ | |||
@@ -120,7 +120,11 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState | |||
int ResumeRefNum(JackClientControl* control, JackSynchro* table); | |||
int SuspendRefNum(JackClientControl* control, JackSynchro* table, long usecs); | |||
JackClientTiming* GetClientTiming(int refnum); | |||
JackClientTiming* GetClientTiming(int refnum) | |||
{ | |||
return &fClientTiming[refnum]; | |||
} | |||
void Save(JackConnectionManager* dst); | |||
void Restore(JackConnectionManager* src); | |||
@@ -31,8 +31,8 @@ JackLibSampleRateResampler::JackLibSampleRateResampler() | |||
jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | |||
} | |||
JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality, unsigned int ringbuffer_size) | |||
:JackResampler(ringbuffer_size) | |||
JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality) | |||
:JackResampler() | |||
{ | |||
switch (quality) { | |||
case 0: | |||
@@ -67,9 +67,9 @@ JackLibSampleRateResampler::~JackLibSampleRateResampler() | |||
src_delete(fResampler); | |||
} | |||
void JackLibSampleRateResampler::Reset() | |||
void JackLibSampleRateResampler::Reset(unsigned int new_size) | |||
{ | |||
JackResampler::Reset(); | |||
JackResampler::Reset(new_size); | |||
src_reset(fResampler); | |||
} | |||
@@ -40,13 +40,13 @@ class JackLibSampleRateResampler : public JackResampler | |||
public: | |||
JackLibSampleRateResampler(); | |||
JackLibSampleRateResampler(unsigned int quality, unsigned int ringbuffer_size); | |||
JackLibSampleRateResampler(unsigned int quality); | |||
virtual ~JackLibSampleRateResampler(); | |||
unsigned int ReadResample(float* buffer, unsigned int frames); | |||
unsigned int WriteResample(float* buffer, unsigned int frames); | |||
void Reset(); | |||
void Reset(unsigned int new_size); | |||
}; | |||
} | |||
@@ -738,9 +738,9 @@ struct JackNetAdapter : public JackAudioAdapterInterface { | |||
fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; | |||
fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; | |||
for (int i = 0; i < fCaptureChannels; i++ ) | |||
fCaptureRingBuffer[i] = new JackResampler(fRingbufferSize); | |||
fCaptureRingBuffer[i] = new JackResampler(); | |||
for (int i = 0; i < fPlaybackChannels; i++ ) | |||
fPlaybackRingBuffer[i] = new JackResampler(fRingbufferSize); | |||
fPlaybackRingBuffer[i] = new JackResampler(); | |||
if (fCaptureChannels > 0) | |||
jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); | |||
@@ -96,7 +96,8 @@ namespace Jack | |||
fQuality = param->value.ui; | |||
break; | |||
case 'g': | |||
fRingbufferSize = param->value.ui; | |||
fRingbufferCurSize = param->value.ui; | |||
fAdaptative = false; | |||
break; | |||
} | |||
} | |||
@@ -242,27 +243,24 @@ namespace Jack | |||
bool JackNetAdapter::Execute() | |||
{ | |||
try | |||
{ | |||
try { | |||
// Keep running even in case of error | |||
while ( fThread.GetStatus() == JackThread::kRunning ) | |||
if ( Process() == SOCKET_ERROR ) | |||
while (fThread.GetStatus() == JackThread::kRunning) | |||
if (Process() == SOCKET_ERROR) | |||
return false; | |||
return false; | |||
} | |||
catch ( JackNetException& e ) | |||
{ | |||
} catch (JackNetException& e) { | |||
e.PrintMessage(); | |||
jack_log ( "NetAdapter is restarted." ); | |||
jack_info("NetAdapter is restarted."); | |||
Reset(); | |||
fThread.DropRealTime(); | |||
fThread.SetStatus ( JackThread::kIniting ); | |||
if ( Init() ) | |||
{ | |||
fThread.SetStatus ( JackThread::kRunning ); | |||
fThread.SetStatus(JackThread::kIniting); | |||
if (Init()) { | |||
fThread.SetStatus(JackThread::kRunning); | |||
return true; | |||
} | |||
else | |||
} else { | |||
return false; | |||
} | |||
} | |||
} | |||
@@ -472,9 +470,9 @@ extern "C" | |||
strcpy(desc->params[i].name, "ring-buffer"); | |||
desc->params[i].character = 'g'; | |||
desc->params[i].type = JackDriverParamInt; | |||
desc->params[i].value.ui = 0; | |||
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 16384)"); | |||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
desc->params[i].value.ui = 32768; | |||
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); | |||
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); | |||
i++; | |||
strcpy ( desc->params[i].name, "auto-connect" ); | |||
@@ -45,6 +45,9 @@ namespace Jack | |||
fSocket.GetName ( fParams.fSlaveNetName ); | |||
fParams.fTransportSync = transport_sync; | |||
fParams.fNetworkMode = network_mode; | |||
fSendTransportData.fState = -1; | |||
fReturnTransportData.fState = -1; | |||
fLastTransportState = -1; | |||
fLastTimebaseMaster = -1; | |||
fMidiCapturePortList = NULL; | |||
fMidiPlaybackPortList = NULL; | |||
@@ -411,7 +414,7 @@ namespace Jack | |||
case JackTransportStarting : | |||
fEngineControl->fTransport.RequestNewPos ( &fSendTransportData.fPosition ); | |||
fEngineControl->fTransport.SetCommand ( TransportCommandStart ); | |||
jack_info ( "Master starts transport." ); | |||
jack_info ( "Master starts transport frame = %d", fSendTransportData.fPosition.frame); | |||
break; | |||
case JackTransportRolling : | |||
@@ -34,6 +34,9 @@ namespace Jack | |||
//settings | |||
fClientName = const_cast<char*> ( fParams.fName ); | |||
fJackClient = NULL; | |||
fSendTransportData.fState = -1; | |||
fReturnTransportData.fState = -1; | |||
fLastTransportState = -1; | |||
uint port_index; | |||
//jack audio ports | |||
@@ -279,7 +282,7 @@ namespace Jack | |||
fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) && | |||
( fSendTransportData.fState != fReturnTransportData.fState ) ); | |||
if ( fSendTransportData.fNewState ) | |||
jack_info ( "Sending '%s' to '%s'.", GetTransportState ( fSendTransportData.fState ), fParams.fName ); | |||
jack_info ( "Sending '%s' to '%s' frame = %ld", GetTransportState ( fSendTransportData.fState ), fParams.fName, fSendTransportData.fPosition.frame ); | |||
fLastTransportState = fSendTransportData.fState; | |||
} | |||
@@ -328,10 +331,10 @@ namespace Jack | |||
jack_info ( "'%s' stops transport.", fParams.fName ); | |||
break; | |||
case JackTransportStarting : | |||
if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) < 0 ) | |||
if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) == EINVAL ) | |||
jack_error ( "Can't set new position." ); | |||
jack_transport_start ( fJackClient ); | |||
jack_info ( "'%s' starts transport.", fParams.fName ); | |||
jack_info ( "'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame); | |||
break; | |||
case JackTransportNetStarting : | |||
jack_info ( "'%s' is ready to roll..", fParams.fName ); | |||
@@ -30,23 +30,17 @@ JackResampler::JackResampler() | |||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * fRingBufferSize) / 2); | |||
} | |||
JackResampler::JackResampler(unsigned int ringbuffer_size) | |||
:fRatio(1),fRingBufferSize(ringbuffer_size) | |||
{ | |||
fRingBuffer = jack_ringbuffer_create(sizeof(float) * fRingBufferSize); | |||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * fRingBufferSize) / 2); | |||
} | |||
JackResampler::~JackResampler() | |||
{ | |||
if (fRingBuffer) | |||
jack_ringbuffer_free(fRingBuffer); | |||
} | |||
void JackResampler::Reset() | |||
void JackResampler::Reset(unsigned int new_size) | |||
{ | |||
jack_ringbuffer_reset(fRingBuffer); | |||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * fRingBufferSize) / 2); | |||
fRingBufferSize = new_size; | |||
jack_ringbuffer_reset_size(fRingBuffer, sizeof(float) * fRingBufferSize); | |||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * fRingBufferSize / 2)); | |||
} | |||
unsigned int JackResampler::ReadSpace() | |||
@@ -26,7 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
namespace Jack | |||
{ | |||
#define DEFAULT_RB_SIZE 16384 | |||
#define DEFAULT_RB_SIZE 32768 | |||
#define DEFAULT_ADAPTATIVE_SIZE 2048 | |||
inline float Range(float min, float max, float val) | |||
{ | |||
@@ -49,10 +50,9 @@ class JackResampler | |||
public: | |||
JackResampler(); | |||
JackResampler(unsigned int ringbuffer_size); | |||
virtual ~JackResampler(); | |||
virtual void Reset(); | |||
virtual void Reset(unsigned int new_size); | |||
virtual unsigned int ReadResample(float* buffer, unsigned int frames); | |||
virtual unsigned int WriteResample(float* buffer, unsigned int frames); | |||
@@ -63,7 +63,7 @@ class JackResampler | |||
virtual unsigned int ReadSpace(); | |||
virtual unsigned int WriteSpace(); | |||
unsigned int GetOffset() | |||
unsigned int GetError() | |||
{ | |||
return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(float)) - (fRingBufferSize / 2); | |||
} | |||
@@ -209,6 +209,7 @@ bool JackThreadedDriver::Init() | |||
if (fDriver->IsRealTime()) { | |||
jack_log("JackThreadedDriver::Init IsRealTime"); | |||
// Will do "something" on OSX only... | |||
GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000; | |||
fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); | |||
if (fThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) { | |||
jack_error("AcquireRealTime error"); | |||
@@ -86,12 +86,6 @@ int JackTransportEngine::SetTimebaseMaster(int refnum, bool conditionnal) | |||
} | |||
} | |||
void JackTransportEngine::GetTimebaseMaster(int& refnum, bool& conditionnal) | |||
{ | |||
refnum = fTimeBaseMaster; | |||
conditionnal = fConditionnal; | |||
} | |||
// RT | |||
bool JackTransportEngine::CheckAllRolling(JackClientInterface** table) | |||
{ | |||
@@ -144,7 +144,11 @@ class SERVER_EXPORT JackTransportEngine : public JackAtomicArrayState<jack_posit | |||
*/ | |||
int SetTimebaseMaster(int refnum, bool conditionnal); | |||
void GetTimebaseMaster(int& refnum, bool& conditionnal); | |||
void GetTimebaseMaster(int& refnum, bool& conditionnal) | |||
{ | |||
refnum = fTimeBaseMaster; | |||
conditionnal = fConditionnal; | |||
} | |||
/* | |||
\brief | |||
@@ -46,6 +46,7 @@ bool JackWaitThreadedDriver::Execute() | |||
if (fDriver->IsRealTime()) { | |||
jack_log("JackWaitThreadedDriver::Init IsRealTime"); | |||
// Will do "something" on OSX only... | |||
GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000; | |||
fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); | |||
if (fThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) { | |||
jack_error("AcquireRealTime error"); | |||
@@ -61,7 +62,7 @@ bool JackWaitThreadedDriver::Execute() | |||
return false; | |||
} catch (JackNetException& e) { | |||
e.PrintMessage(); | |||
jack_log("Driver is restarted"); | |||
jack_info("Driver is restarted"); | |||
fThread.DropRealTime(); | |||
// Thread in kIniting status again... | |||
fThread.SetStatus(JackThread::kIniting); | |||
@@ -192,6 +192,16 @@ int jack_ringbuffer_mlock(jack_ringbuffer_t *rb); | |||
*/ | |||
void jack_ringbuffer_reset(jack_ringbuffer_t *rb); | |||
/** | |||
* Reset the internal "available" size, and read and write pointers, making an empty buffer. | |||
* | |||
* This is not thread safe. | |||
* | |||
* @param rb a pointer to the ringbuffer structure. | |||
* @param sz the new size, that must be less than allocated size. | |||
*/ | |||
void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz); | |||
/** | |||
* Write data into the ringbuffer. | |||
* | |||
@@ -33,15 +33,15 @@ extern "C" | |||
* clients. These interfaces hide some system variations in the | |||
* handling of realtime scheduling and associated privileges. | |||
*/ | |||
/** | |||
* @defgroup ClientThreads Creating and managing client threads | |||
* @{ | |||
*/ | |||
/** | |||
* @returns if JACK is running with realtime scheduling, this returns | |||
* the priority that any JACK-created client threads will run at. | |||
* the priority that any JACK-created client threads will run at. | |||
* Otherwise returns -1. | |||
*/ | |||
@@ -114,8 +114,35 @@ int jack_client_stop_thread(jack_client_t* client, pthread_t thread); | |||
* @param thread POSIX thread ID. | |||
* | |||
* @returns 0, if successful; otherwise an error number. | |||
*/ | |||
*/ | |||
int jack_client_kill_thread(jack_client_t* client, pthread_t thread); | |||
#ifndef WIN32 | |||
typedef int (*jack_thread_creator_t)(pthread_t*, | |||
const pthread_attr_t*, | |||
void* (*function)(void*), | |||
void* arg); | |||
/** | |||
* This function can be used in very very specialized cases | |||
* where it is necessary that client threads created by JACK | |||
* are created by something other than pthread_create(). After | |||
* it is used, any threads that JACK needs for the client will | |||
* will be created by calling the function passed to this | |||
* function. | |||
* | |||
* No normal application/client should consider calling this. | |||
* The specific case for which it was created involves running | |||
* win32/x86 plugins under Wine on Linux, where it is necessary | |||
* that all threads that might call win32 functions are known | |||
* to Wine. | |||
* | |||
* @param creator a function that creates a new thread | |||
* | |||
*/ | |||
void jack_set_thread_creator (jack_thread_creator_t creator); | |||
#endif | |||
/* @} */ | |||
@@ -55,6 +55,7 @@ EXPORT void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt); | |||
EXPORT size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb); | |||
EXPORT int jack_ringbuffer_mlock(jack_ringbuffer_t *rb); | |||
EXPORT void jack_ringbuffer_reset(jack_ringbuffer_t *rb); | |||
EXPORT void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz); | |||
EXPORT size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src, | |||
size_t cnt); | |||
void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt); | |||
@@ -123,6 +124,19 @@ jack_ringbuffer_reset (jack_ringbuffer_t * rb) | |||
rb->write_ptr = 0; | |||
} | |||
/* Reset the read and write pointers to zero. This is not thread | |||
safe. */ | |||
EXPORT void | |||
jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz) | |||
{ | |||
rb->size = sz; | |||
rb->size_mask = rb->size; | |||
rb->size_mask -= 1; | |||
rb->read_ptr = 0; | |||
rb->write_ptr = 0; | |||
} | |||
/* Return the number of bytes available for reading. This is the | |||
number of bytes in front of the read pointer and behind the write | |||
pointer. */ | |||
@@ -190,6 +190,7 @@ def build(bld): | |||
'JackAudioAdapterInterface.cpp', | |||
'JackLibSampleRateResampler.cpp', | |||
'JackResampler.cpp', | |||
'JackGlobals.cpp', | |||
'ringbuffer.c'] | |||
if bld.env['IS_LINUX']: | |||
@@ -77,7 +77,8 @@ namespace Jack | |||
fQuality = param->value.ui; | |||
break; | |||
case 'g': | |||
fRingbufferSize = param->value.ui; | |||
fRingbufferCurSize = param->value.ui; | |||
fAdaptative = false; | |||
break; | |||
} | |||
} | |||
@@ -104,7 +105,6 @@ namespace Jack | |||
//turn the thread realtime | |||
fThread.AcquireRealTime ( JackServerGlobals::fInstance->GetEngineControl()->fClientPriority ); | |||
return 0; | |||
} | |||
@@ -251,7 +251,7 @@ extern "C" | |||
strcpy ( desc->params[i].name, "duplex" ); | |||
desc->params[i].character = 'D'; | |||
desc->params[i].type = JackDriverParamBool; | |||
desc->params[i].value.i = 1; | |||
desc->params[i].value.i = true; | |||
strcpy ( desc->params[i].short_desc, | |||
"Provide both capture and playback ports" ); | |||
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | |||
@@ -286,9 +286,9 @@ extern "C" | |||
strcpy(desc->params[i].name, "ring-buffer"); | |||
desc->params[i].character = 'g'; | |||
desc->params[i].type = JackDriverParamInt; | |||
desc->params[i].value.ui = 0; | |||
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 16384)"); | |||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
desc->params[i].value.ui = 32768; | |||
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); | |||
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); | |||
return desc; | |||
} | |||
@@ -22,6 +22,7 @@ def create_jack_driver_obj(bld, target, sources, uselib = None): | |||
driver.install_path = '${ADDON_DIR}/' | |||
if uselib: | |||
driver.uselib = uselib | |||
driver.uselib_local = 'serverlib' | |||
return driver | |||
def build(bld): | |||
@@ -378,7 +378,8 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra | |||
break; | |||
case 'g': | |||
fRingbufferSize = param->value.ui; | |||
fRingbufferCurSize = param->value.ui; | |||
fAdaptative = false; | |||
break; | |||
} | |||
} | |||
@@ -1080,9 +1081,9 @@ extern "C" | |||
strcpy(desc->params[i].name, "ring-buffer"); | |||
desc->params[i].character = 'g'; | |||
desc->params[i].type = JackDriverParamInt; | |||
desc->params[i].value.ui = 0; | |||
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 16384)"); | |||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
desc->params[i].value.ui = 32768; | |||
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); | |||
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); | |||
return desc; | |||
} | |||
@@ -52,6 +52,10 @@ | |||
4B1A945A0F49C03600D3626B /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; | |||
4B1A947F0F49C42300D3626B /* JackAudioQueueAdapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A947D0F49C42300D3626B /* JackAudioQueueAdapter.cpp */; }; | |||
4B1A95760F49CEAB00D3626B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; | |||
4B2791880F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; | |||
4B2791890F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; | |||
4B27918A0F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; | |||
4B27918B0F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; | |||
4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BBDC8F90F5420C000465F9C /* freeverb.mm */; }; | |||
4BF1360F0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; | |||
4BF136100F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; | |||
@@ -104,6 +108,7 @@ | |||
4B1A947D0F49C42300D3626B /* JackAudioQueueAdapter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioQueueAdapter.cpp; path = ../coreaudio/JackAudioQueueAdapter.cpp; sourceTree = SOURCE_ROOT; }; | |||
4B1A947E0F49C42300D3626B /* JackAudioQueueAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackAudioQueueAdapter.h; path = ../coreaudio/JackAudioQueueAdapter.h; sourceTree = SOURCE_ROOT; }; | |||
4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; }; | |||
4B2791870F72570C000536B7 /* JackGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobals.cpp; path = ../../common/JackGlobals.cpp; sourceTree = SOURCE_ROOT; }; | |||
4BBDC8F90F5420C000465F9C /* freeverb.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = freeverb.mm; sourceTree = SOURCE_ROOT; }; | |||
4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapterInterface.cpp; path = ../../common/JackAudioAdapterInterface.cpp; sourceTree = SOURCE_ROOT; }; | |||
4BF136120F4B0B5E00218A3F /* JackAudioAdapterInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackAudioAdapterInterface.h; path = ../../common/JackAudioAdapterInterface.h; sourceTree = SOURCE_ROOT; }; | |||
@@ -204,6 +209,7 @@ | |||
4B1A93110F49AB3400D3626B /* JackNetTool.cpp */, | |||
4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */, | |||
4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */, | |||
4B2791870F72570C000536B7 /* JackGlobals.cpp */, | |||
32CA4F630368D1EE00C91783 /* iPhoneNet_Prefix.pch */, | |||
4B0772490F54021B000DC657 /* main_slave.mm */, | |||
4B0772500F54022D000DC657 /* main_master.mm */, | |||
@@ -383,6 +389,7 @@ | |||
4BF136550F4B0F9F00218A3F /* ringbuffer.c in Sources */, | |||
4B07724A0F54021B000DC657 /* main_slave.mm in Sources */, | |||
4B0773870F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, | |||
4B27918A0F72570C000536B7 /* JackGlobals.cpp in Sources */, | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
}; | |||
@@ -403,6 +410,7 @@ | |||
4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */, | |||
4B0772510F54022D000DC657 /* main_master.mm in Sources */, | |||
4B0773860F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, | |||
4B27918B0F72570C000536B7 /* JackGlobals.cpp in Sources */, | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
}; | |||
@@ -420,6 +428,7 @@ | |||
4BF136100F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */, | |||
4BF1364E0F4B0F7700218A3F /* JackResampler.cpp in Sources */, | |||
4BF136560F4B0F9F00218A3F /* ringbuffer.c in Sources */, | |||
4B2791890F72570C000536B7 /* JackGlobals.cpp in Sources */, | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
}; | |||
@@ -440,6 +449,7 @@ | |||
4BFF456D0F4D5D9700106083 /* ringbuffer.c in Sources */, | |||
4B0773880F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, | |||
4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */, | |||
4B2791880F72570C000536B7 /* JackGlobals.cpp in Sources */, | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
}; | |||
@@ -30,9 +30,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
namespace Jack | |||
{ | |||
void JackFifo::BuildName(const char* name, const char* server_name, char* res) | |||
void JackFifo::BuildName(const char* client_name, const char* server_name, char* res) | |||
{ | |||
sprintf(res, "%s/jack_fifo.%d_%s_%s", jack_client_dir, JackTools::GetUID(), server_name, name); | |||
char ext_client_name[JACK_CLIENT_NAME_SIZE + 1]; | |||
JackTools::RewriteName(client_name, ext_client_name); | |||
sprintf(res, "%s/jack_fifo.%d_%s_%s", jack_client_dir, JackTools::GetUID(), server_name, ext_client_name); | |||
} | |||
bool JackFifo::Signal() | |||
@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#include "JackPosixThread.h" | |||
#include "JackError.h" | |||
#include "JackTime.h" | |||
#include "JackGlobals.h" | |||
#include <string.h> // for memset | |||
#include <unistd.h> // for _POSIX_PRIORITY_SCHEDULING check | |||
@@ -139,7 +140,7 @@ int JackPosixThread::StartImp(pthread_t* thread, int priority, int realtime, voi | |||
return -1; | |||
} | |||
if ((res = pthread_create(thread, &attributes, start_routine, arg))) { | |||
if ((res = JackGlobals::fJackThreadCreator(thread, &attributes, start_routine, arg))) { | |||
jack_error("Cannot create thread res = %d err = %s", res, strerror(errno)); | |||
return -1; | |||
} | |||
@@ -29,6 +29,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
namespace Jack | |||
{ | |||
static void BuildName(const char* client_name, char* res, const char* dir, int which) | |||
{ | |||
char ext_client_name[JACK_CLIENT_NAME_SIZE + 1]; | |||
JackTools::RewriteName(client_name, ext_client_name); | |||
sprintf(res, "%s/jack_%s_%d_%d", dir, ext_client_name, JackTools::GetUID(), which); | |||
} | |||
JackClientSocket::JackClientSocket(int socket): fSocket(socket),fTimeOut(0) | |||
{} | |||
@@ -112,36 +119,7 @@ int JackClientSocket::Connect(const char* dir, const char* name, int which) // A | |||
} | |||
addr.sun_family = AF_UNIX; | |||
snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%s/jack_%s_%d_%d", dir, name, JackTools::GetUID(), which); | |||
jack_log("Connect: addr.sun_path %s", addr.sun_path); | |||
if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | |||
jack_error("Cannot connect to server socket err = %s", strerror(errno)); | |||
close(fSocket); | |||
return -1; | |||
} | |||
#ifdef __APPLE__ | |||
int on = 1 ; | |||
if (setsockopt(fSocket, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) { | |||
jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fSocket, strerror(errno)); | |||
} | |||
#endif | |||
return 0; | |||
} | |||
int JackClientSocket::Connect(const char* dir, int which) | |||
{ | |||
struct sockaddr_un addr; | |||
if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { | |||
jack_error("Cannot create socket err = %s", strerror(errno)); | |||
return -1; | |||
} | |||
addr.sun_family = AF_UNIX; | |||
snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%s/jack_%d_%d", dir, JackTools::GetUID(), which); | |||
BuildName(name, addr.sun_path, dir, which); | |||
jack_log("Connect: addr.sun_path %s", addr.sun_path); | |||
if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | |||
@@ -271,67 +249,9 @@ int JackServerSocket::Bind(const char* dir, const char* name, int which) // A re | |||
} | |||
addr.sun_family = AF_UNIX; | |||
// TO CORRECT: always reuse the same name for now... | |||
snprintf(fName, sizeof(addr.sun_path) - 1, "%s/jack_%s_%d_%d", dir, name, JackTools::GetUID(), which); | |||
BuildName(name, fName, dir, which); | |||
strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1); | |||
/* | |||
if (access(addr.sun_path, F_OK) == 0) { | |||
goto error; | |||
} | |||
*/ | |||
jack_log("Bind: addr.sun_path %s", addr.sun_path); | |||
unlink(fName); // Security... | |||
if (bind(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | |||
jack_error("Cannot bind server to socket err = %s", strerror(errno)); | |||
goto error; | |||
} | |||
if (listen(fSocket, 1) < 0) { | |||
jack_error("Cannot enable listen on server socket err = %s", strerror(errno)); | |||
goto error; | |||
} | |||
return 0; | |||
error: | |||
unlink(fName); | |||
close(fSocket); | |||
return -1; | |||
} | |||
int JackServerSocket::Bind(const char* dir, int which) // A revoir : utilisation de "which" | |||
{ | |||
struct sockaddr_un addr; | |||
if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { | |||
jack_error("Cannot create server socket err = %s", strerror(errno)); | |||
return -1; | |||
} | |||
addr.sun_family = AF_UNIX; | |||
/* | |||
for (int i = 0; i < 999; i++) { | |||
snprintf(addr.sun_path, sizeof(addr.sun_path) - 1,"%s/jack_%d", dir, i); | |||
snprintf(fName, sizeof(addr.sun_path) - 1,"%s/jack_%d", dir, i); | |||
if (access(addr.sun_path, F_OK) != 0) { | |||
break; | |||
} | |||
} | |||
*/ | |||
// TO CORRECT: always reuse the same name for now... | |||
snprintf(fName, sizeof(addr.sun_path) - 1, "%s/jack_%d_%d", dir, JackTools::GetUID(), which); | |||
strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1); | |||
/* | |||
if (access(addr.sun_path, F_OK) == 0) { | |||
goto error; | |||
} | |||
*/ | |||
jack_log("Bind: addr.sun_path %s", addr.sun_path); | |||
unlink(fName); // Security... | |||
@@ -50,7 +50,6 @@ class JackClientSocket | |||
{} | |||
JackClientSocket(int socket); | |||
int Connect(const char* dir, int which); | |||
int Connect(const char* dir, const char* name, int which); | |||
int Close(); | |||
int Read(void* data, int len); | |||
@@ -69,13 +68,16 @@ class JackClientSocket | |||
\brief Server socket. | |||
*/ | |||
#define SOCKET_MAX_NAME_SIZE 256 | |||
class JackServerSocket | |||
{ | |||
private: | |||
int fSocket; | |||
char fName[256]; | |||
char fName[SOCKET_MAX_NAME_SIZE]; | |||
public: | |||
@@ -84,7 +86,6 @@ class JackServerSocket | |||
~JackServerSocket() | |||
{} | |||
int Bind(const char* dir, int which); | |||
int Bind(const char* dir, const char* name, int which); | |||
JackClientSocket* Accept(); | |||
int Close(); | |||
@@ -26,4 +26,6 @@ | |||
typedef unsigned long long UInt64; | |||
typedef pthread_key_t jack_tls_key; | |||
typedef int (*jack_thread_creator_t)(pthread_t*, const pthread_attr_t*, void* (*function)(void*), void* arg); | |||
#endif |
@@ -183,7 +183,8 @@ JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample | |||
break; | |||
case 'g': | |||
fRingbufferSize = param->value.ui; | |||
fRingbufferCurSize = param->value.ui; | |||
fAdaptative = false; | |||
break; | |||
} | |||
@@ -494,9 +495,16 @@ int JackOSSAdapter::Open() | |||
} | |||
DisplayDeviceInfo(); | |||
//start adapter thread | |||
if (fThread.StartSync() < 0) { | |||
jack_error ( "Cannot start audioadapter thread" ); | |||
return -1; | |||
} | |||
//turn the thread realtime | |||
fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority); | |||
return fThread.StartSync(); | |||
return 0; | |||
error: | |||
CloseAux(); | |||
@@ -742,10 +750,10 @@ extern "C" | |||
strcpy(desc->params[i].name, "ring-buffer"); | |||
desc->params[i].character = 'g'; | |||
desc->params[i].type = JackDriverParamInt; | |||
desc->params[i].value.ui = 0; | |||
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 16384)"); | |||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
desc->params[i].value.ui = 32768; | |||
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); | |||
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); | |||
return desc; | |||
} | |||
@@ -97,7 +97,8 @@ namespace Jack | |||
fQuality = param->value.ui; | |||
break; | |||
case 'g': | |||
fRingbufferSize = param->value.ui; | |||
fRingbufferCurSize = param->value.ui; | |||
fAdaptative = false; | |||
break; | |||
} | |||
} | |||
@@ -282,7 +283,7 @@ extern "C" | |||
strcpy(desc->params[i].name, "list-devices"); | |||
desc->params[i].character = 'l'; | |||
desc->params[i].type = JackDriverParamBool; | |||
desc->params[i].value.i = TRUE; | |||
desc->params[i].value.i = true; | |||
strcpy(desc->params[i].short_desc, "Display available PortAudio devices"); | |||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
@@ -298,9 +299,9 @@ extern "C" | |||
strcpy(desc->params[i].name, "ring-buffer"); | |||
desc->params[i].character = 'g'; | |||
desc->params[i].type = JackDriverParamInt; | |||
desc->params[i].value.ui = 0; | |||
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 16384)"); | |||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
desc->params[i].value.ui = 32768; | |||
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); | |||
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); | |||
return desc; | |||
} | |||