Browse Source

Correct use of JackResampler

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2595 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.90
sletz 17 years ago
parent
commit
09b784a243
13 changed files with 76 additions and 56 deletions
  1. +26
    -25
      common/JackCallbackNetIOAdapter.cpp
  2. +2
    -2
      common/JackCallbackNetIOAdapter.h
  3. +0
    -1
      common/JackFilters.h
  4. +4
    -4
      common/JackIOAdapter.h
  5. +3
    -1
      common/JackLibSampleRateResampler.cpp
  6. +1
    -1
      common/JackLibSampleRateResampler.h
  7. +5
    -3
      common/JackNetIOAdapter.cpp
  8. +2
    -2
      common/JackResampler.cpp
  9. +1
    -1
      common/JackResampler.h
  10. +2
    -2
      common/wscript
  11. +9
    -7
      macosx/JackCoreAudioIOAdapter.cpp
  12. BIN
      macosx/libportaudio.a
  13. +21
    -7
      windows/JackPortAudioIOAdapter.cpp

+ 26
- 25
common/JackCallbackNetIOAdapter.cpp View File

@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */


#include "JackCallbackNetIOAdapter.h" #include "JackCallbackNetIOAdapter.h"
#include "JackLibSampleRateResampler.h"
#include "JackError.h" #include "JackError.h"
#include "JackExports.h" #include "JackExports.h"
#include <stdio.h> #include <stdio.h>
@@ -51,17 +52,17 @@ int JackCallbackNetIOAdapter::Process(jack_nframes_t frames, void* arg)
//jack_info("ReadSpace = %ld", adapter->fCaptureRingBuffer[0].ReadSpace()); //jack_info("ReadSpace = %ld", adapter->fCaptureRingBuffer[0].ReadSpace());
//jack_info("WriteSpace = %ld", adapter->fPlaybackRingBuffer[0].WriteSpace()); //jack_info("WriteSpace = %ld", adapter->fPlaybackRingBuffer[0].WriteSpace());
printf("ReadSpace = %ld\n", adapter->fCaptureRingBuffer[0].ReadSpace());
printf("WriteSpace = %ld\n", adapter->fPlaybackRingBuffer[0].WriteSpace());
printf("ReadSpace = %ld\n", adapter->fCaptureRingBuffer[0]->ReadSpace());
printf("WriteSpace = %ld\n", adapter->fPlaybackRingBuffer[0]->WriteSpace());
for (i = 0; i < adapter->fCaptureChannels; i++) { for (i = 0; i < adapter->fCaptureChannels; i++) {
buffer = static_cast<float*>(jack_port_get_buffer(adapter->fCapturePortList[i], frames)); buffer = static_cast<float*>(jack_port_get_buffer(adapter->fCapturePortList[i], frames));
adapter->fCaptureRingBuffer[i].Read(buffer, frames);
adapter->fCaptureRingBuffer[i]->Read(buffer, frames);
} }
for (i = 0; i < adapter->fPlaybackChannels; i++) { for (i = 0; i < adapter->fPlaybackChannels; i++) {
buffer = static_cast<float*>(jack_port_get_buffer(adapter->fPlaybackPortList[i], frames)); buffer = static_cast<float*>(jack_port_get_buffer(adapter->fPlaybackPortList[i], frames));
adapter->fPlaybackRingBuffer[i].Write(buffer, frames);
adapter->fPlaybackRingBuffer[i]->Write(buffer, frames);
} }
return 0; return 0;
@@ -80,35 +81,25 @@ JackCallbackNetIOAdapter::JackCallbackNetIOAdapter(jack_client_t* jack_client,
int output) int output)
: JackNetIOAdapter(jack_client, audio_io, input, output) : JackNetIOAdapter(jack_client, audio_io, input, output)
{ {
int i;
fCurCallbackTime = 0; fCurCallbackTime = 0;
fLastCallbackTime = 0; fLastCallbackTime = 0;
fCaptureRingBuffer = new JackResampler[fCaptureChannels];
fPlaybackRingBuffer = new JackResampler[fPlaybackChannels];
fIOAdapter->SetRingBuffers(fCaptureRingBuffer, fPlaybackRingBuffer);
fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
// Init Ringbuffers
/*
int frames = jack_get_buffer_size(jack_client);
float buffer[frames];
int i;
for (i = 0; i < fCaptureChannels; i++) { for (i = 0; i < fCaptureChannels; i++) {
fCaptureRingBuffer[i].Read(buffer, frames);
fCaptureRingBuffer[i].Read(buffer, frames);
fCaptureRingBuffer[i].Read(buffer, frames);
fCaptureRingBuffer[i] = new JackLibSampleRateResampler();
} }
for (i = 0; i < fPlaybackChannels; i++) { for (i = 0; i < fPlaybackChannels; i++) {
fPlaybackRingBuffer[i].Write(buffer, frames);
fPlaybackRingBuffer[i].Write(buffer, frames);
fPlaybackRingBuffer[i].Write(buffer, frames);
}
*/
jack_log("ReadSpace = %ld", fCaptureRingBuffer[0].ReadSpace());
jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0].WriteSpace());
fPlaybackRingBuffer[i] = new JackLibSampleRateResampler();
}
fIOAdapter->SetRingBuffers(fCaptureRingBuffer, fPlaybackRingBuffer);
jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
if (jack_set_process_callback(fJackClient, Process, this) < 0) if (jack_set_process_callback(fJackClient, Process, this) < 0)
goto fail; goto fail;
@@ -127,6 +118,16 @@ fail:


JackCallbackNetIOAdapter::~JackCallbackNetIOAdapter() JackCallbackNetIOAdapter::~JackCallbackNetIOAdapter()
{ {
int i;
for (i = 0; i < fCaptureChannels; i++) {
delete(fCaptureRingBuffer[i]);
}
for (i = 0; i < fPlaybackChannels; i++) {
delete(fPlaybackRingBuffer[i]);
}
delete[] fCaptureRingBuffer; delete[] fCaptureRingBuffer;
delete[] fPlaybackRingBuffer; delete[] fPlaybackRingBuffer;
} }


+ 2
- 2
common/JackCallbackNetIOAdapter.h View File

@@ -31,8 +31,8 @@ namespace Jack
private: private:
JackResampler* fCaptureRingBuffer;
JackResampler* fPlaybackRingBuffer;
JackResampler** fCaptureRingBuffer;
JackResampler** fPlaybackRingBuffer;
jack_time_t fLastCallbackTime; jack_time_t fLastCallbackTime;
jack_time_t fCurCallbackTime; jack_time_t fCurCallbackTime;


+ 0
- 1
common/JackFilters.h View File

@@ -125,7 +125,6 @@ namespace Jack
} }


}; };


inline float Range(float min, float max, float val) inline float Range(float min, float max, float val)
{ {


+ 4
- 4
common/JackIOAdapter.h View File

@@ -52,10 +52,10 @@ namespace Jack
// DLL // DLL
JackDelayLockedLoop fProducerDLL; JackDelayLockedLoop fProducerDLL;
JackDelayLockedLoop fConsumerDLL; JackDelayLockedLoop fConsumerDLL;
jack_time_t fCurFrames;
JackResampler* fCaptureRingBuffer;
JackResampler* fPlaybackRingBuffer;
JackResampler** fCaptureRingBuffer;
JackResampler** fPlaybackRingBuffer;

bool fRunning; bool fRunning;
public: public:
@@ -75,7 +75,7 @@ namespace Jack
virtual ~JackIOAdapterInterface() virtual ~JackIOAdapterInterface()
{} {}
void SetRingBuffers(JackResampler* input, JackResampler* output)
void SetRingBuffers(JackResampler** input, JackResampler** output)
{ {
fCaptureRingBuffer = input; fCaptureRingBuffer = input;
fPlaybackRingBuffer = output; fPlaybackRingBuffer = output;


+ 3
- 1
common/JackLibSampleRateResampler.cpp View File

@@ -22,8 +22,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack namespace Jack
{ {


JackLibSampleRateResampler::JackLibSampleRateResampler():JackResampler(),fRatio(1)
JackLibSampleRateResampler::JackLibSampleRateResampler()
:JackResampler(),fRatio(1)
{ {
jack_log("JackLibSampleRateResampler::JackLibSampleRateResampler");
int error; int error;
fResampler = src_new(SRC_LINEAR, 1, &error); fResampler = src_new(SRC_LINEAR, 1, &error);
if (error != 0) if (error != 0)


+ 1
- 1
common/JackLibSampleRateResampler.h View File

@@ -42,7 +42,7 @@ namespace Jack
int ReadResample(float* buffer, unsigned int frames); int ReadResample(float* buffer, unsigned int frames);
int WriteResample(float* buffer, unsigned int frames); int WriteResample(float* buffer, unsigned int frames);
virtual void SetRatio(unsigned int num, unsigned int denom)
void SetRatio(unsigned int num, unsigned int denom)
{ {
JackResampler::SetRatio(num, denom); JackResampler::SetRatio(num, denom);
fRatio = double(num) / double(denom); fRatio = double(num) / double(denom);


+ 5
- 3
common/JackNetIOAdapter.cpp View File

@@ -115,15 +115,17 @@ extern "C"
return 1; return 1;
} else { } else {
jack_log("Loading NetAudio Adapter"); jack_log("Loading NetAudio Adapter");
/*
adapter = new Jack::JackCallbackNetIOAdapter(jack_client, adapter = new Jack::JackCallbackNetIOAdapter(jack_client,
new Jack::JackPortAudioIOAdapter(2, 2, jack_get_buffer_size(jack_client), jack_get_sample_rate(jack_client)), 2, 2); new Jack::JackPortAudioIOAdapter(2, 2, jack_get_buffer_size(jack_client), jack_get_sample_rate(jack_client)), 2, 2);
/*
*/
#ifdef __APPLE__ #ifdef __APPLE__
adapter = new Jack::JackCallbackNetIOAdapter(jack_client, adapter = new Jack::JackCallbackNetIOAdapter(jack_client,
new Jack::JackCoreAudioIOAdapter(2, 2, jack_get_buffer_size(jack_client), jack_get_sample_rate(jack_client)), 2, 2); new Jack::JackCoreAudioIOAdapter(2, 2, jack_get_buffer_size(jack_client), jack_get_sample_rate(jack_client)), 2, 2);
#endif #endif
*/
assert(adapter); assert(adapter);
if (adapter->Open() == 0) { if (adapter->Open() == 0) {


+ 2
- 2
common/JackResampler.cpp View File

@@ -22,9 +22,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack namespace Jack
{ {


JackResampler::JackResampler()
:fNum(1),fDenom(1)
JackResampler::JackResampler():fNum(1),fDenom(1)
{ {
jack_log("JackResampler::JackResampler");
fRingBuffer = jack_ringbuffer_create(sizeof(float) * DEFAULT_RB_SIZE); fRingBuffer = jack_ringbuffer_create(sizeof(float) * DEFAULT_RB_SIZE);
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * DEFAULT_RB_SIZE) / 2); jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * DEFAULT_RB_SIZE) / 2);
} }


+ 1
- 1
common/JackResampler.h View File

@@ -27,7 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack namespace Jack
{ {


#define DEFAULT_RB_SIZE 16384 * 4
#define DEFAULT_RB_SIZE 16384 * 1


class JackResampler class JackResampler
{ {


+ 2
- 2
common/wscript View File

@@ -194,8 +194,8 @@ def build(bld):


create_jack_process_obj(bld, 'netmanager', 'JackNetManager.cpp', serverlib) create_jack_process_obj(bld, 'netmanager', 'JackNetManager.cpp', serverlib)


#process = create_jack_process_obj(bld, 'netioadapter', 'JackResampler.cpp ackLibSampleRateResampler.cpp JackIOAdapter.cpp JackNetIOAdapter.cpp JackCallbackNetIOAdapter.cpp ../macosx/JackCoreAudioIOAdapter.cpp', serverlib)
process = create_jack_process_obj(bld, 'netioadapter', 'JackResampler.cpp JackLibSampleRateResampler.cpp JackIOAdapter.cpp JackNetIOAdapter.cpp JackCallbackNetIOAdapter.cpp ../windows/JackPortAudioIOAdapter.cpp', serverlib)
process = create_jack_process_obj(bld, 'netioadapter', 'JackResampler.cpp JackLibSampleRateResampler.cpp JackIOAdapter.cpp JackNetIOAdapter.cpp JackCallbackNetIOAdapter.cpp ../macosx/JackCoreAudioIOAdapter.cpp', serverlib)
#process = create_jack_process_obj(bld, 'netioadapter', 'JackResampler.cpp JackLibSampleRateResampler.cpp JackIOAdapter.cpp JackNetIOAdapter.cpp JackCallbackNetIOAdapter.cpp ../windows/JackPortAudioIOAdapter.cpp', serverlib)


process.env.append_value("LINKFLAGS", "-lsamplerate") process.env.append_value("LINKFLAGS", "-lsamplerate")
if bld.env()['IS_MACOSX']: if bld.env()['IS_MACOSX']:


+ 9
- 7
macosx/JackCoreAudioIOAdapter.cpp View File

@@ -122,7 +122,6 @@ OSStatus JackCoreAudioIOAdapter::Render(void *inRefCon,
{ {
JackCoreAudioIOAdapter* adapter = static_cast<JackCoreAudioIOAdapter*>(inRefCon); JackCoreAudioIOAdapter* adapter = static_cast<JackCoreAudioIOAdapter*>(inRefCon);
jack_log("JackCoreAudioIOAdapter::Render inNumberFrames %ld", inNumberFrames); jack_log("JackCoreAudioIOAdapter::Render inNumberFrames %ld", inNumberFrames);
AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
@@ -135,7 +134,7 @@ OSStatus JackCoreAudioIOAdapter::Render(void *inRefCon,
adapter->fProducerFilter.AddValue(adapter->fDeltaTime); adapter->fProducerFilter.AddValue(adapter->fDeltaTime);
*/ */
jack_log("JackCoreAudioIOAdapter::Render delta %ld", adapter->fCurCallbackTime - adapter->fLastCallbackTime);
//jack_log("JackCoreAudioIOAdapter::Render delta %ld", adapter->fCurCallbackTime - adapter->fLastCallbackTime);
//printf("JackCoreAudioIOAdapter::Render delta %ld\n", adapter->fCurCallbackTime - adapter->fLastCallbackTime); //printf("JackCoreAudioIOAdapter::Render delta %ld\n", adapter->fCurCallbackTime - adapter->fLastCallbackTime);
if (!adapter->fRunning) { if (!adapter->fRunning) {
@@ -143,7 +142,6 @@ OSStatus JackCoreAudioIOAdapter::Render(void *inRefCon,
jack_time_t time = jack_get_time(); jack_time_t time = jack_get_time();
adapter->fProducerDLL.Init(time); adapter->fProducerDLL.Init(time);
adapter->fConsumerDLL.Init(time); adapter->fConsumerDLL.Init(time);
adapter->fCurFrames = 0;
} }
// DLL based // DLL based
@@ -174,11 +172,15 @@ OSStatus JackCoreAudioIOAdapter::Render(void *inRefCon,
if (src_ratio_input < 0.8f || src_ratio_input > 1.2f) { if (src_ratio_input < 0.8f || src_ratio_input > 1.2f) {
jack_error("src_ratio_input = %f", src_ratio_input); jack_error("src_ratio_input = %f", src_ratio_input);
src_ratio_input = 1; src_ratio_input = 1;
time1 = 1;
time2 = 1;
} }
if (src_ratio_output < 0.8f || src_ratio_output > 1.2f) { if (src_ratio_output < 0.8f || src_ratio_output > 1.2f) {
jack_error("src_ratio_output = %f", src_ratio_output); jack_error("src_ratio_output = %f", src_ratio_output);
src_ratio_output = 1; src_ratio_output = 1;
time1 = 1;
time2 = 1;
} }
src_ratio_input = Range(0.8f, 1.2f, src_ratio_input); src_ratio_input = Range(0.8f, 1.2f, src_ratio_input);
@@ -189,14 +191,14 @@ OSStatus JackCoreAudioIOAdapter::Render(void *inRefCon,
printf("Callback resampler src_ratio_input = %f src_ratio_output = %f\n", src_ratio_input, src_ratio_output); printf("Callback resampler src_ratio_input = %f src_ratio_output = %f\n", src_ratio_input, src_ratio_output);
for (int i = 0; i < adapter->fCaptureChannels; i++) { for (int i = 0; i < adapter->fCaptureChannels; i++) {
adapter->fCaptureRingBuffer[i].SetRatio(time1, time2);
adapter->fCaptureRingBuffer[i].WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames);
adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames);
// adapter->fCaptureRingBuffer[i].Write((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames); // adapter->fCaptureRingBuffer[i].Write((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames);
} }
for (int i = 0; i < adapter->fPlaybackChannels; i++) { for (int i = 0; i < adapter->fPlaybackChannels; i++) {
adapter->fPlaybackRingBuffer[i].SetRatio(time2, time1);
adapter->fPlaybackRingBuffer[i].ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames);
adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames);
// adapter->fPlaybackRingBuffer[i].Read((float*)ioData->mBuffers[i].mData, inNumberFrames); // adapter->fPlaybackRingBuffer[i].Read((float*)ioData->mBuffers[i].mData, inNumberFrames);
} }


BIN
macosx/libportaudio.a View File


+ 21
- 7
windows/JackPortAudioIOAdapter.cpp View File

@@ -47,7 +47,6 @@ int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
jack_time_t time = jack_get_time(); jack_time_t time = jack_get_time();
adapter->fProducerDLL.Init(time); adapter->fProducerDLL.Init(time);
adapter->fConsumerDLL.Init(time); adapter->fConsumerDLL.Init(time);
adapter->fCurFrames = 0;
} }
/* /*
@@ -59,10 +58,21 @@ int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
//adapter->fConsumerDLL.IncFrame(adapter->fConsumerTime); //adapter->fConsumerDLL.IncFrame(adapter->fConsumerTime);
jack_time_t time = jack_get_time(); jack_time_t time = jack_get_time();
adapter->fProducerDLL.IncFrame(time); adapter->fProducerDLL.IncFrame(time);
jack_nframes_t time1 = adapter->fConsumerDLL.Time2Frames(time); jack_nframes_t time1 = adapter->fConsumerDLL.Time2Frames(time);
jack_nframes_t time2 = adapter->fProducerDLL.Time2Frames(time); jack_nframes_t time2 = adapter->fProducerDLL.Time2Frames(time);
//time1 = 1;
//time2 = 1;

/*
if ((adapter->fConsumerDLL.CurTime2Frame() / adapter->fSampleRate) > 10) {
printf("REINIT DLL\n");
adapter->fConsumerDLL.Init(time);
adapter->fConsumerDLL.Init(time);
}
*/
//printf("time1 %ld time2 %ld\n",time1, time2); //printf("time1 %ld time2 %ld\n",time1, time2);


double src_ratio_output = double(time2) / double(time1); double src_ratio_output = double(time2) / double(time1);
@@ -78,11 +88,15 @@ int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
if (src_ratio_input < 0.8f || src_ratio_input > 1.2f) { if (src_ratio_input < 0.8f || src_ratio_input > 1.2f) {
jack_error("src_ratio_input = %f", src_ratio_input); jack_error("src_ratio_input = %f", src_ratio_input);
src_ratio_input = 1; src_ratio_input = 1;
time1 = 1;
time2 = 1;
} }
if (src_ratio_output < 0.8f || src_ratio_output > 1.2f) { if (src_ratio_output < 0.8f || src_ratio_output > 1.2f) {
jack_error("src_ratio_output = %f", src_ratio_output); jack_error("src_ratio_output = %f", src_ratio_output);
src_ratio_output = 1; src_ratio_output = 1;
time1 = 1;
time2 = 1;
} }
src_ratio_input = Range(0.8f, 1.2f, src_ratio_input); src_ratio_input = Range(0.8f, 1.2f, src_ratio_input);
src_ratio_output = Range(0.8f, 1.2f, src_ratio_output); src_ratio_output = Range(0.8f, 1.2f, src_ratio_output);
@@ -92,23 +106,23 @@ int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
paBuffer = (float**)inputBuffer; paBuffer = (float**)inputBuffer;
for (int i = 0; i < adapter->fCaptureChannels; i++) { for (int i = 0; i < adapter->fCaptureChannels; i++) {
buffer = (float*)paBuffer[i]; buffer = (float*)paBuffer[i];
adapter->fCaptureRingBuffer[i].SetRatio(time1, time2);
adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
//adapter->fCaptureRingBuffer[i].WriteResample(buffer, framesPerBuffer); //adapter->fCaptureRingBuffer[i].WriteResample(buffer, framesPerBuffer);
//adapter->fCaptureRingBuffer[i].SetRatio(double(adapter->fNum) * adapter->fError1, adapter->fDenom); //adapter->fCaptureRingBuffer[i].SetRatio(double(adapter->fNum) * adapter->fError1, adapter->fDenom);
adapter->fCaptureRingBuffer[i].Write(buffer, framesPerBuffer);
adapter->fCaptureRingBuffer[i]->Write(buffer, framesPerBuffer);
} }
paBuffer = (float**)outputBuffer; paBuffer = (float**)outputBuffer;
for (int i = 0; i < adapter->fPlaybackChannels; i++) { for (int i = 0; i < adapter->fPlaybackChannels; i++) {
buffer = (float*)paBuffer[i]; buffer = (float*)paBuffer[i];
adapter->fPlaybackRingBuffer[i].SetRatio(time2, time1);
adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
//adapter->fPlaybackRingBuffer[i].ReadResample(buffer, framesPerBuffer); //adapter->fPlaybackRingBuffer[i].ReadResample(buffer, framesPerBuffer);
//adapter->fCaptureRingBuffer[i].SetRatio(double(adapter->fDenom) * adapter->fError1, adapter->fNum); //adapter->fCaptureRingBuffer[i].SetRatio(double(adapter->fDenom) * adapter->fError1, adapter->fNum);
adapter->fPlaybackRingBuffer[i].Read(buffer, framesPerBuffer);
adapter->fPlaybackRingBuffer[i]->Read(buffer, framesPerBuffer);
} }
printf("Callback resampler src_ratio_input = %f src_ratio_output = %f\n", double(time1) / double(time2), double(time2) / double(time1)); printf("Callback resampler src_ratio_input = %f src_ratio_output = %f\n", double(time1) / double(time2), double(time2) / double(time1));
return paContinue; return paContinue;
} }


Loading…
Cancel
Save