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; | |||
| } | |||