git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2294 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
| @@ -23,6 +23,7 @@ Fernando Lopez-Lezcano | |||||
| 2008-05-20 Stephane Letz <letz@grame.fr> | 2008-05-20 Stephane Letz <letz@grame.fr> | ||||
| * Package number bumped to 1.90 everywhere. | * Package number bumped to 1.90 everywhere. | ||||
| * Implementation of jack_get_max_delayed_usecs, jack_get_xrun_delayed_usecs and jack_reset_max_delayed_usecs. | |||||
| 2008-05-19 Stephane Letz <letz@grame.fr> | 2008-05-19 Stephane Letz <letz@grame.fr> | ||||
| @@ -1493,17 +1493,29 @@ EXPORT float jack_get_max_delayed_usecs(jack_client_t* ext_client) | |||||
| #ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
| JackLibGlobals::CheckContext(); | JackLibGlobals::CheckContext(); | ||||
| #endif | #endif | ||||
| jack_log("jack_get_max_delayed_usecs: not yet implemented"); | |||||
| return 0.f; | |||||
| } | |||||
| JackClient* client = (JackClient*)ext_client; | |||||
| if (client == NULL) { | |||||
| jack_error("jack_get_max_delayed_usecs called with a NULL client"); | |||||
| return 0.f; | |||||
| } else { | |||||
| JackEngineControl* control = GetEngineControl(); | |||||
| return (control ? control->fMaxDelayedUsecs : 0.f); | |||||
| } | |||||
| } | |||||
| EXPORT float jack_get_xrun_delayed_usecs(jack_client_t* ext_client) | EXPORT float jack_get_xrun_delayed_usecs(jack_client_t* ext_client) | ||||
| { | { | ||||
| #ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
| JackLibGlobals::CheckContext(); | JackLibGlobals::CheckContext(); | ||||
| #endif | #endif | ||||
| jack_log("jack_get_xrun_delayed_usecs: not yet implemented"); | |||||
| return 0.f; | |||||
| JackClient* client = (JackClient*)ext_client; | |||||
| if (client == NULL) { | |||||
| jack_error("jack_get_xrun_delayed_usecs called with a NULL client"); | |||||
| return 0.f; | |||||
| } else { | |||||
| JackEngineControl* control = GetEngineControl(); | |||||
| return (control ? control->fXrunDelayedUsecs : 0.f); | |||||
| } | |||||
| } | } | ||||
| EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client) | EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client) | ||||
| @@ -1511,7 +1523,13 @@ EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client) | |||||
| #ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
| JackLibGlobals::CheckContext(); | JackLibGlobals::CheckContext(); | ||||
| #endif | #endif | ||||
| jack_log("jack_reset_max_delayed_usecs: not yet implemented"); | |||||
| JackClient* client = (JackClient*)ext_client; | |||||
| if (client == NULL) { | |||||
| jack_error("jack_reset_max_delayed_usecs called with a NULL client"); | |||||
| } else { | |||||
| JackEngineControl* control = GetEngineControl(); | |||||
| control->ResetXRun(); | |||||
| } | |||||
| } | } | ||||
| // thread.h | // thread.h | ||||
| @@ -247,9 +247,9 @@ int JackAudioDriver::ProcessSync() | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| void JackAudioDriver::NotifyXRun(jack_time_t callback_usecs) | |||||
| void JackAudioDriver::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) | |||||
| { | { | ||||
| fEngine->NotifyXRun(callback_usecs); | |||||
| fEngine->NotifyXRun(callback_usecs, delayed_usecs); | |||||
| } | } | ||||
| jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index) | jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index) | ||||
| @@ -81,7 +81,7 @@ class EXPORT JackAudioDriver : public JackDriver | |||||
| virtual int SetBufferSize(jack_nframes_t buffer_size); | virtual int SetBufferSize(jack_nframes_t buffer_size); | ||||
| virtual int SetSampleRate(jack_nframes_t sample_rate); | virtual int SetSampleRate(jack_nframes_t sample_rate); | ||||
| virtual void NotifyXRun(jack_time_t callback_usecs); // XRun notification sent by the driver | |||||
| virtual void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); // XRun notification sent by the driver | |||||
| }; | }; | ||||
| @@ -47,6 +47,7 @@ JackDriver::JackDriver(const char* name, JackEngine* engine, JackSynchro** table | |||||
| fEngine = engine; | fEngine = engine; | ||||
| fGraphManager = NULL; | fGraphManager = NULL; | ||||
| fLastWaitUst = 0; | fLastWaitUst = 0; | ||||
| fDelayedUsecs = 0.f; | |||||
| fIsMaster = true; | fIsMaster = true; | ||||
| } | } | ||||
| @@ -178,9 +179,9 @@ JackClientControl* JackDriver::GetClientControl() const | |||||
| return fClientControl; | return fClientControl; | ||||
| } | } | ||||
| void JackDriver::NotifyXRun(jack_time_t callback_usecs) | |||||
| void JackDriver::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) | |||||
| { | { | ||||
| fEngine->NotifyXRun(callback_usecs); | |||||
| fEngine->NotifyXRun(callback_usecs, delayed_usecs); | |||||
| } | } | ||||
| void JackDriverClient::SetMaster(bool onoff) | void JackDriverClient::SetMaster(bool onoff) | ||||
| @@ -148,6 +148,7 @@ class EXPORT JackDriver : public JackDriverClient | |||||
| jack_nframes_t fCaptureLatency; | jack_nframes_t fCaptureLatency; | ||||
| jack_nframes_t fPlaybackLatency; | jack_nframes_t fPlaybackLatency; | ||||
| jack_time_t fLastWaitUst; | jack_time_t fLastWaitUst; | ||||
| jack_time_t fDelayedUsecs; | |||||
| JackEngine* fEngine; | JackEngine* fEngine; | ||||
| JackGraphManager* fGraphManager; | JackGraphManager* fGraphManager; | ||||
| JackSynchro** fSynchroTable; | JackSynchro** fSynchroTable; | ||||
| @@ -220,7 +221,7 @@ class EXPORT JackDriver : public JackDriverClient | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| void NotifyXRun(jack_time_t callback_usecs); // XRun notification sent by the driver | |||||
| void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); // XRun notification sent by the driver | |||||
| virtual bool IsRealTime(); | virtual bool IsRealTime(); | ||||
| @@ -269,10 +269,11 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum) | |||||
| } | } | ||||
| // Coming from the driver | // Coming from the driver | ||||
| void JackEngine::NotifyXRun(jack_time_t callback_usecs) | |||||
| void JackEngine::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) | |||||
| { | { | ||||
| // Use the audio thread => request thread communication channel | // Use the audio thread => request thread communication channel | ||||
| fEngineControl->ResetFrameTime(callback_usecs); | fEngineControl->ResetFrameTime(callback_usecs); | ||||
| fEngineControl->NotifyXRun(delayed_usecs); | |||||
| fChannel->Notify(ALL_CLIENTS, kXRunCallback, 0); | fChannel->Notify(ALL_CLIENTS, kXRunCallback, 0); | ||||
| } | } | ||||
| @@ -108,7 +108,7 @@ class JackEngine | |||||
| virtual bool Process(jack_time_t callback_usecs); | virtual bool Process(jack_time_t callback_usecs); | ||||
| // Notifications | // Notifications | ||||
| virtual void NotifyXRun(jack_time_t callback_usecs); | |||||
| virtual void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); | |||||
| virtual void NotifyXRun(int refnum); | virtual void NotifyXRun(int refnum); | ||||
| virtual void NotifyGraphReorder(); | virtual void NotifyGraphReorder(); | ||||
| virtual void NotifyBufferSize(jack_nframes_t nframes); | virtual void NotifyBufferSize(jack_nframes_t nframes); | ||||
| @@ -155,5 +155,17 @@ void JackEngineControl::ClearTimeMeasures() | |||||
| } | } | ||||
| fLastTime = fCurTime = 0; | fLastTime = fCurTime = 0; | ||||
| } | } | ||||
| void JackEngineControl::NotifyXRun(float delayed_usecs) | |||||
| { | |||||
| fXrunDelayedUsecs = delayed_usecs; | |||||
| if (delayed_usecs > fMaxDelayedUsecs) | |||||
| fMaxDelayedUsecs = delayed_usecs; | |||||
| } | |||||
| void JackEngineControl::ResetXRun() | |||||
| { | |||||
| fMaxDelayedUsecs = 0.f; | |||||
| } | |||||
| } // end of namespace | } // end of namespace | ||||
| @@ -73,6 +73,8 @@ struct JackEngineControl : public JackShmMem | |||||
| bool fTemporary; | bool fTemporary; | ||||
| jack_time_t fPeriodUsecs; | jack_time_t fPeriodUsecs; | ||||
| jack_time_t fTimeOutUsecs; | jack_time_t fTimeOutUsecs; | ||||
| float fMaxDelayedUsecs; | |||||
| float fXrunDelayedUsecs; | |||||
| bool fTimeOut; | bool fTimeOut; | ||||
| bool fRealTime; | bool fRealTime; | ||||
| int fPriority; | int fPriority; | ||||
| @@ -128,6 +130,8 @@ struct JackEngineControl : public JackShmMem | |||||
| fPeriod = 0; | fPeriod = 0; | ||||
| fComputation = 0; | fComputation = 0; | ||||
| fConstraint = 0; | fConstraint = 0; | ||||
| fMaxDelayedUsecs = 0.f; | |||||
| fXrunDelayedUsecs = 0.f; | |||||
| } | } | ||||
| ~JackEngineControl() | ~JackEngineControl() | ||||
| {} | {} | ||||
| @@ -140,6 +144,10 @@ struct JackEngineControl : public JackShmMem | |||||
| void InitFrameTime(); | void InitFrameTime(); | ||||
| void ResetFrameTime(jack_time_t callback_usecs); | void ResetFrameTime(jack_time_t callback_usecs); | ||||
| void ReadFrameTime(JackTimer* timer); | void ReadFrameTime(JackTimer* timer); | ||||
| // XRun | |||||
| void NotifyXRun(float delayed_usecs); | |||||
| void ResetXRun(); | |||||
| // Private | // Private | ||||
| void CalcCPULoad(JackClientInterface** table, JackGraphManager* manager); | void CalcCPULoad(JackClientInterface** table, JackGraphManager* manager); | ||||
| @@ -154,10 +154,10 @@ class JackLockedEngine : public JackEngine, public JackLockAble | |||||
| } | } | ||||
| // Notifications | // Notifications | ||||
| void NotifyXRun(jack_time_t callback_usecs) | |||||
| void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) | |||||
| { | { | ||||
| // RT : no lock | |||||
| fEngine->NotifyXRun(callback_usecs); | |||||
| // RT : no lock | |||||
| fEngine->NotifyXRun(callback_usecs, delayed_usecs); | |||||
| } | } | ||||
| void NotifyXRun(int refnum) | void NotifyXRun(int refnum) | ||||
| @@ -2268,52 +2268,33 @@ int JackAlsaDriver::Stop() | |||||
| int JackAlsaDriver::Read() | int JackAlsaDriver::Read() | ||||
| { | { | ||||
| /* Taken from alsa_driver_run_cycle */ | /* Taken from alsa_driver_run_cycle */ | ||||
| //jack_engine_t *engine = driver->engine; | |||||
| int wait_status; | |||||
| float delayed_usecs; | |||||
| int wait_status; | |||||
| jack_nframes_t nframes; | jack_nframes_t nframes; | ||||
| //DEBUG ("alsa run cycle wait\n"); | |||||
| nframes = alsa_driver_wait((alsa_driver_t *)fDriver, -1, &wait_status, &delayed_usecs); | |||||
| //DEBUG ("alsaback from wait, nframes = %lu", nframes); | |||||
| nframes = alsa_driver_wait((alsa_driver_t *)fDriver, -1, &wait_status, &fDelayedUsecs); | |||||
| if (wait_status < 0) | if (wait_status < 0) | ||||
| return -1; /* driver failed */ | return -1; /* driver failed */ | ||||
| if (nframes == 0) { | if (nframes == 0) { | ||||
| /* we detected an xrun and restarted: notify | /* we detected an xrun and restarted: notify | ||||
| * clients about the delay. | * clients about the delay. | ||||
| */ | */ | ||||
| //engine->delay (engine, delayed_usecs); | |||||
| jack_log("ALSA XRun"); | jack_log("ALSA XRun"); | ||||
| NotifyXRun(fLastWaitUst); | |||||
| NotifyXRun(fLastWaitUst, fDelayedUsecs); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| //fLastWaitUst = GetMicroSeconds(); // Take callback date here | |||||
| if (nframes != fEngineControl->fBufferSize) | if (nframes != fEngineControl->fBufferSize) | ||||
| jack_log("JackAlsaDriver::Read nframes = %ld", nframes); | jack_log("JackAlsaDriver::Read nframes = %ld", nframes); | ||||
| //return engine->run_cycle (engine, nframes, delayed_usecs); | |||||
| fDelayedUst = (jack_time_t)delayed_usecs; | fDelayedUst = (jack_time_t)delayed_usecs; | ||||
| return alsa_driver_read((alsa_driver_t *)fDriver, fEngineControl->fBufferSize); | return alsa_driver_read((alsa_driver_t *)fDriver, fEngineControl->fBufferSize); | ||||
| } | } | ||||
| int JackAlsaDriver::Write() | int JackAlsaDriver::Write() | ||||
| { | { | ||||
| //jack_log("write"); | |||||
| int res = alsa_driver_write((alsa_driver_t *)fDriver, fEngineControl->fBufferSize); | |||||
| jack_time_t write_time = GetMicroSeconds(); | |||||
| /* | |||||
| if (write_time > (fLastWaitUst - fDelayedUst) + fEngineControl->fPeriodUsecs) { | |||||
| jack_log("ALSA write XRun "); | |||||
| NotifyXRun(write_time); | |||||
| } | |||||
| */ | |||||
| return res; | |||||
| return alsa_driver_write((alsa_driver_t *)fDriver, fEngineControl->fBufferSize); | |||||
| } | } | ||||
| void | void | ||||
| @@ -250,7 +250,8 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, | |||||
| case kAudioDeviceProcessorOverload: | case kAudioDeviceProcessorOverload: | ||||
| jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload"); | jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload"); | ||||
| driver->NotifyXRun(GetMicroSeconds()); | |||||
| jack_time_t cur_time = GetMicroSeconds(); | |||||
| driver->NotifyXRun(cur_time, float(cur_time - driver->fLastWaitUst)); // Better this value than nothing... | |||||
| break; | break; | ||||
| case kAudioDevicePropertyStreamConfiguration: | case kAudioDevicePropertyStreamConfiguration: | ||||