void AddValue2ChannelMix(CaptureThreadImpl* impl, double value, int i)
{
if(i%2==0)
- impl->m_capture_thread->m_values.push_front(value);
+ impl->m_tmp_value = value;
+// impl->m_capture_thread->m_values.push_front(value);
else
- impl->m_capture_thread->m_values[0] = (impl->m_capture_thread->m_values[0]+value)/2.0;
+ impl->m_capture_thread->m_values.push_front((impl->m_tmp_value+value)/2.0);
+// impl->m_capture_thread->m_values[0] = (impl->m_capture_thread->m_values[0]+value)/2.0;
}
void AddValue1Channel(CaptureThreadImpl* impl, double value, int i)
{
{
m_current_impl = impl;
- cerr << "using " << m_current_impl->m_name << endl;
+ cerr << "using " << m_current_impl->m_name.toStdString() << endl;
if(m_current_impl->m_name!=old_name)
emit(transportChanged(m_current_impl->m_name));
}
void CaptureThread::selectTransport(const QString& name)
{
- cerr << "CaptureThread: INFO: using " << name << " transport" << endl;
+ cerr << "CaptureThread: INFO: using " << name.toStdString() << " transport" << endl;
if(getCurrentTransport() && name==getCurrentTransport()->getName()) return;
bool was_capturing = isCapturing();
if(impl==NULL)
{
- cerr << "CaptureThread: ERROR: unknown transport '" << name << "'" << endl;
+ cerr << "CaptureThread: ERROR: unknown transport '" << name.toStdString() << "'" << endl;
throw QString("CaptureThread: ERROR: unknown transport '")+name+"'";
}
assert(index>=0 && index<m_impls.size());
if(m_impls[index]==getCurrentTransport()) return;
- cerr << "CaptureThread: INFO: change transport to " << m_impls[index]->getName() << " transport" << endl;
+ cerr << "CaptureThread: INFO: change transport to " << m_impls[index]->getName().toStdString() << " transport" << endl;
bool was_capturing = isCapturing();
if(was_capturing)
{
cerr << "CaptureThread: INFO: Built in transports" << endl;
for(vector<CaptureThreadImpl*>::iterator it=m_impls.begin(); it!=m_impls.end(); it++)
- cerr << "CaptureThread: INFO: " << (*it)->getStatus() << " " << (*it)->m_name << " " << (*it)->m_descr << endl;
+ cerr << "CaptureThread: INFO: " << (*it)->getStatus().toStdString() << " " << (*it)->m_name.toStdString() << " " << (*it)->m_descr.toStdString() << endl;
}
const CaptureThreadImpl* CaptureThread::getCurrentTransport() const
{
cerr << "CaptureThread: INFO: format is " << (m_format_signed?"signed":"unsigned") << " " << (m_format_float?"float":"integer") << " " << m_format_size*8 << "bits with " << m_channel_count << " channel(s)" << endl;
}
-
-// ------------------------------ ALSA implementation ----------------------------
-#ifdef CAPTURE_ALSA
-
-#define ALSA_BUFF_SIZE 1024
-
-void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt, ...)
-{
- cerr << "alsa_error_handler: " << file << ":" << line << " " << function << " err=" << err << endl;
-}
-
-CaptureThreadImplALSA::CaptureThreadImplALSA(CaptureThread* capture_thread)
- : CaptureThreadImpl(capture_thread, "ALSA", QString("Advanced Linux Sound Architecture (lib:")+snd_asoundlib_version()+")")
-{
- m_alsa_capture_handle = NULL;
- m_alsa_hw_params = NULL;
- m_alsa_buffer = NULL;
- m_format = SND_PCM_FORMAT_UNKNOWN;
-
- m_source = "hw:0";
-
- m_alive = true;
- m_in_run = false;
- m_loop = false;
-
-// snd_lib_error_set_handler(alsa_error_handler);
-}
-
-bool CaptureThreadImplALSA::is_available()
-{
- if(m_alsa_capture_handle==NULL)
- {
- try
- {
- int err = -1;
- if((err=snd_pcm_open(&m_alsa_capture_handle, m_source.latin1(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
- {
- if(err==-19) // TODO risks of changes for the error code
- throw QString("invalid source '")+m_source+"'";
- else if(err==-16)
- throw QString("device '")+m_source+"' busy";
- else
- throw QString("cannot open pcm: ")+QString(snd_strerror(err));
- }
- }
- catch(QString error)
- {
- m_alsa_capture_handle = NULL;
-
- m_status = "N/A ("+error+")";
-
- return false;
- }
-
- if(m_alsa_capture_handle!=NULL)
- {
- snd_pcm_close(m_alsa_capture_handle);
- m_alsa_capture_handle = NULL;
- }
- }
-
- m_status = "OK";
-
- // cerr << "CaptureThread: INFO: ALSA seems available" << endl;
-
- return true;
-}
-
-void CaptureThreadImplALSA::startCapture()
-{
- if(!running())
- start();
-
- m_loop = true;
-
- m_wait_for_start = true;
- while(m_wait_for_start) // some implementations take a long time to start
- msleep(10);
-}
-void CaptureThreadImplALSA::stopCapture()
-{
- m_loop = false;
-
- while(m_in_run)
- msleep(10);
-}
-
-void CaptureThreadImplALSA::set_params(bool test)
-{
-// cerr << "ALSA: Recognized sample formats are" << endl;
-// for (int k = 0; k < SND_PCM_FORMAT_LAST; ++(unsigned long) k) {
-// const char *s = snd_pcm_format_name((snd_pcm_format_t)k);
-// if (s) cerr << s << endl;
-// }
- int err=0;
-
- if(m_source=="")
- throw QString("ALSA: set the source first");
- if((err=snd_pcm_open(&m_alsa_capture_handle, m_source.latin1(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
- {
- // cerr << "err=" << err << ":" << snd_strerror(err) << endl;
-
- if(err==-19) // TODO risks of changes for the error code
- throw QString("ALSA: Invalid Source '")+m_source+"'";
- else if(err==-16)
- throw QString("ALSA: Device '")+m_source+"' busy";
- else
- throw QString("ALSA: Cannot open pcm: ")+QString(snd_strerror(err));
- }
-
- snd_pcm_hw_params_alloca(&m_alsa_hw_params);
-
- if((err=snd_pcm_hw_params_any(m_alsa_capture_handle, m_alsa_hw_params)) < 0)
- throw QString("ALSA: cannot initialize hardware parameter structure (")+QString(snd_strerror(err))+")";
-
- if((err=snd_pcm_hw_params_set_access(m_alsa_capture_handle, m_alsa_hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
- throw QString("ALSA: cannot set access type (")+QString(snd_strerror(err))+")";
-
- if(!test)
- {
- // Formats
- if(m_format==-1)
- {
- list<snd_pcm_format_t> formats;
- formats.push_back(SND_PCM_FORMAT_S16); formats.push_back(SND_PCM_FORMAT_U16);
- formats.push_back(SND_PCM_FORMAT_S8); formats.push_back(SND_PCM_FORMAT_U8);
-
- err = -1;
- while(err<0)
- {
- if(formats.empty())
- throw QString("ALSA: cannot set any format (")+QString(snd_strerror(err))+")";
-
- m_format = formats.front();
- cerr << "CaptureThread: INFO: ALSA: try to set format to " << snd_pcm_format_description(m_format) << flush;
- err=snd_pcm_hw_params_set_format(m_alsa_capture_handle, m_alsa_hw_params, m_format);
-
- if(err<0) cerr << " failed" << endl;
- else cerr << " success" << endl;
-
- formats.pop_front();
- }
- }
- else
- {
- if((err=snd_pcm_hw_params_set_format(m_alsa_capture_handle, m_alsa_hw_params, m_format))<0)
- {
- QString err_msg = QString("ALSA: cannot set format (")+QString(snd_strerror(err))+")";
- cerr << "CaptureThread: ERROR: " << err_msg << endl;
- }
- }
-
- // Channel count
- unsigned int channel_count = 1;
- if((err=snd_pcm_hw_params_set_channels_near(m_alsa_capture_handle, m_alsa_hw_params, &channel_count)) < 0)
- {
- QString err_msg = QString("ALSA: cannot set channel count (")+QString(snd_strerror(err))+")";
- cerr << "CaptureThread: WARNING: " << err_msg << endl;
- }
- if(channel_count>1)
- {
- QString err_msg = QString("ALSA: cannot set channel count to one (")+QString::number(channel_count)+" instead)";
- cerr << "CaptureThread: WARNING: " << err_msg << endl;
- }
-
- setFormatDescrsAndFns(snd_pcm_format_width(m_format)/8, snd_pcm_format_signed(m_format), false, channel_count);
- }
-
- if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
- {
- int old_sampling_rate = m_sampling_rate;
-
- cerr << "CaptureThread: INFO: ALSA: sampling rate set to max or undefined, try to determinate it." << endl;
-
- list<int> sampling_rates;
- sampling_rates.push_front(8000); sampling_rates.push_front(11025); sampling_rates.push_front(16000);
- sampling_rates.push_front(22050); sampling_rates.push_front(24000); sampling_rates.push_front(32000);
- sampling_rates.push_front(44100); sampling_rates.push_front(48000); sampling_rates.push_front(96000);
-
- err = -1;
- while(err<0)
- {
- if(sampling_rates.empty())
- throw QString("ALSA: cannot set any sample rate (")+QString(snd_strerror(err))+")";
-
- m_sampling_rate = sampling_rates.front();
- cerr << "CaptureThread: INFO: ALSA: try to set sampling rate to " << m_sampling_rate << flush;
- unsigned int rrate = m_sampling_rate;
- err = snd_pcm_hw_params_set_rate(m_alsa_capture_handle, m_alsa_hw_params, rrate, 0);
-
- if(err<0) cerr << " failed" << endl;
- else cerr << " success" << endl;
-
- sampling_rates.pop_front();
- }
-
- if(old_sampling_rate!=m_sampling_rate)
- m_capture_thread->emitSamplingRateChanged();
- }
- else
- {
- int err;
- int dir = 0;
- unsigned int rrate = m_sampling_rate;
- if((err = snd_pcm_hw_params_set_rate_near(m_alsa_capture_handle, m_alsa_hw_params, &rrate, &dir))<0)
- throw QString("ALSA: cannot set sampling rate (")+QString(snd_strerror(err))+")";
- if(m_sampling_rate!=rrate)
- m_capture_thread->emitSamplingRateChanged();
- m_sampling_rate = rrate;
- }
-
- if((err=snd_pcm_hw_params(m_alsa_capture_handle, m_alsa_hw_params)) < 0)
- throw QString("ALSA: cannot set parameters (")+QString(snd_strerror(err))+")";
-}
-
-void CaptureThreadImplALSA::setSamplingRate(int value)
-{
-// cerr << "CaptureThreadImplALSA::setSamplingRate " << value << endl;
-
- assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
-
- if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
- {
- bool was_running = m_capture_thread->isCapturing();
- if(was_running) m_capture_thread->stopCapture();
-
- m_sampling_rate = value;
-
- if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
- {
- try
- {
- set_params(true);
- }
- catch(QString error)
- {
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
-
- // it was just for testing
- capture_finished();
- }
- else
- m_capture_thread->emitSamplingRateChanged();
-
- if(was_running) m_capture_thread->startCapture();
- }
-
-// cerr << "~CaptureThreadImplALSA::setSamplingRate" << endl;
-}
-
-void CaptureThreadImplALSA::capture_init()
-{
- set_params();
-
- snd_pcm_nonblock(m_alsa_capture_handle, 0);
-
- m_alsa_buffer = new char[m_channel_count*ALSA_BUFF_SIZE*snd_pcm_format_width(m_format)/8];
-
- int err=0;
-
- if((err=snd_pcm_prepare(m_alsa_capture_handle)) < 0)
- throw QString("ALSA: cannot prepare audio interface for use (")+QString(snd_strerror(err))+")";
-}
-void CaptureThreadImplALSA::capture_loop()
-{
-// cerr << "CaptureThreadImplALSA::capture_loop" << endl;
-
- m_wait_for_start = false;
- while(m_loop)
- {
- int ret_val = snd_pcm_readi(m_alsa_capture_handle, m_alsa_buffer, ALSA_BUFF_SIZE);
- if(ret_val<0)
- {
- cerr << "CaptureThread: WARNING: ALSA: " << snd_strerror(ret_val) << endl;
- while((ret_val = snd_pcm_prepare(m_alsa_capture_handle)) < 0)
- {
- msleep(1000);
- cerr << QString("ALSA: cannot prepare audio interface (")+QString(snd_strerror(ret_val))+")" << endl;
-// throw QString("ALSA: cannot prepare audio interface (")+QString(snd_strerror(ret_val))+")";
- }
- }
- else
- {
- if(!m_capture_thread->m_pause)
- {
- m_capture_thread->m_lock.lock();
-
-// cerr << "CaptureThreadImplALSA::capture_loop " << m_capture_thread->m_values.size() << endl;
-
- for(int i=0; i<ret_val*m_channel_count; i++)
- addValue(this, decodeValue(m_alsa_buffer, i), i);
-
- m_capture_thread->m_packet_size = ret_val;
- if(m_capture_thread->m_ext_lock)
- {
- m_capture_thread->m_packet_size_sll = 0;
- m_capture_thread->m_ext_lock = false;
- }
- m_capture_thread->m_packet_size_sll += ret_val;
-
- m_capture_thread->m_lock.unlock();
- }
- }
- }
-
-// cerr << "~CaptureThreadImplALSA::capture_loop" << endl;
-}
-void CaptureThreadImplALSA::capture_finished()
-{
- if(m_alsa_buffer!=NULL)
- {
- delete[] m_alsa_buffer;
- m_alsa_buffer = NULL;
- }
-
- if(m_alsa_capture_handle!=NULL)
- {
- snd_pcm_hw_free(m_alsa_capture_handle);
- snd_pcm_close(m_alsa_capture_handle);
- m_alsa_capture_handle = NULL;
- }
-}
-
-void CaptureThreadImplALSA::run()
-{
-// cerr << "CaptureThread: INFO: ALSA: capture thread entered" << endl;
-
-// while(m_alive) // TODO need to keep alsa thread alive to let PortAudio working after ALSA !!
- {
- while(m_alive && !m_loop)
- msleep(10);
-
- m_in_run = true;
-
- try
- {
- // cerr << "CaptureThread: INFO: capture thread running" << endl;
-
- capture_init();
-
- m_capture_thread->m_capturing = true;
- m_capture_thread->emitCaptureStarted();
- m_capture_thread->emitCaptureToggled(true);
-
- capture_loop();
-
- m_capture_thread->m_capturing = false;
- m_capture_thread->emitCaptureStoped();
- m_capture_thread->emitCaptureToggled(false);
- }
- catch(QString error)
- {
- m_loop = false;
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
- m_wait_for_start = false;
-
- capture_finished();
-
- m_in_run = false;
-
- // cerr << "CaptureThread: INFO: capture thread stop running" << endl;
- }
-
-// cerr << "CaptureThread: INFO: ALSA: capture thread exited" << endl;
-}
-
-CaptureThreadImplALSA::~CaptureThreadImplALSA()
-{
-// cerr << "CaptureThreadImplALSA::~CaptureThreadImplALSA" << endl;
-
- m_alive = false;
-
- stopCapture();
-
- while(running())
- msleep(10);
-
-// cerr << "~CaptureThreadImplALSA::~CaptureThreadImplALSA" << endl;
-}
-
-#endif
-
-// ------------------------------ JACK implementation ----------------------------
-#ifdef CAPTURE_JACK
-CaptureThreadImplJACK::CaptureThreadImplJACK(CaptureThread* capture_thread)
-: CaptureThreadImpl(capture_thread, "JACK", "Jack Audio Connection Kit")
-{
- m_jack_client = NULL;
- m_jack_port = NULL;
-}
-
-bool CaptureThreadImplJACK::is_available()
-{
- if(m_jack_client==NULL)
- {
- try
- {
- m_jack_client = jack_client_new((m_capture_thread->m_name+"_test").latin1());
- if(m_jack_client==NULL)
- throw QString("unknown reason");
- }
- catch(QString error)
- {
- m_jack_client = NULL;
- m_status = "N/A";
- return false;
- }
- capture_finished();
- }
-
- m_status = "available";
-
- return true;
-}
-
-void CaptureThreadImplJACK::setSamplingRate(int value)
-{
- cerr << "CaptureThread: ERROR: JACK: setSamplingRate not available with JACK ! change the JACK server sampling rate instead" << endl;
-}
-
-void CaptureThreadImplJACK::startCapture()
-{
- try
- {
- capture_init();
- }
- catch(QString error)
- {
- capture_finished();
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
-}
-void CaptureThreadImplJACK::stopCapture()
-{
- try
- {
- capture_finished();
- }
- catch(QString error)
- {
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
-}
-
-void CaptureThreadImplJACK::JackShutdown(void* arg){((CaptureThreadImplJACK*)arg)->jackShutdown();}
-void CaptureThreadImplJACK::jackShutdown()
-{
- m_jack_client = NULL;
-
- m_capture_thread->emitError("JACK: server shutdown !");
-}
-
-int CaptureThreadImplJACK::JackSampleRate(jack_nframes_t nframes, void* arg){return ((CaptureThreadImplJACK*)arg)->jackSampleRate(nframes);}
-int CaptureThreadImplJACK::jackSampleRate(jack_nframes_t nframes)
-{
- if(m_sampling_rate!=int(nframes))
- {
- m_sampling_rate = nframes;
- m_capture_thread->emitSamplingRateChanged();
- }
-
- return 0;
-}
-
-int CaptureThreadImplJACK::JackProcess(jack_nframes_t nframes, void* arg){return ((CaptureThreadImplJACK*)arg)->jackProcess(nframes);}
-int CaptureThreadImplJACK::jackProcess(jack_nframes_t nframes)
-{
-// cerr << "'" << nframes << "'" << endl;
-
- if(m_capture_thread->m_pause || !m_capture_thread->m_capturing || nframes<=0) return 0;
-
- void* pin = jack_port_get_buffer(m_jack_port, nframes);
-
- if(!pin) return 0;
-
- jack_default_audio_sample_t* in = (jack_default_audio_sample_t*)pin;
-
- m_capture_thread->m_lock.lock();
-
- for(jack_nframes_t i=0; i<nframes; i++)
- m_capture_thread->m_values.push_front(in[i]);
-
- m_capture_thread->m_lock.unlock();
-
- m_capture_thread->m_packet_size = nframes;
- if(m_capture_thread->m_ext_lock)
- {
- m_capture_thread->m_packet_size_sll = 0;
- m_capture_thread->m_ext_lock = false;
- }
- m_capture_thread->m_packet_size_sll += nframes;
-
- return 0;
-}
-
-void CaptureThreadImplJACK::capture_init()
-{
- m_jack_client = jack_client_new(m_capture_thread->m_name.latin1());
- if(!m_jack_client)
- throw QString("JACK: cannot create client, JACK deamon is running ?");
-
- jack_set_process_callback(m_jack_client, JackProcess, (void*)this);
- jack_on_shutdown(m_jack_client, JackShutdown, (void*)this);
- jack_set_error_function(jack_error_callback);
- jack_set_sample_rate_callback(m_jack_client, JackSampleRate, (void*)this);
-
- int err=0;
- if((err=jack_activate(m_jack_client))!=0)
- throw QString("JACK: cannot activate client");
-
- setFormatDescrsAndFns(sizeof(jack_default_audio_sample_t), true, true, 1);
-
- m_jack_port = jack_port_register(m_jack_client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput,0);
-
- if(m_source!="")
- if((err=jack_connect(m_jack_client, m_source.latin1(), (m_capture_thread->m_name+":input").latin1()))!=0)
- m_capture_thread->emitError(QString("JACK: Invalid source '")+m_source+"'");
-
- int old_sampling_rate = m_sampling_rate;
- m_sampling_rate = jack_get_sample_rate(m_jack_client);
- if(m_sampling_rate!=old_sampling_rate)
- m_capture_thread->emitSamplingRateChanged();
-
- m_capture_thread->m_capturing = true;
- m_capture_thread->emitCaptureStarted();
- m_capture_thread->emitCaptureToggled(true);
-}
-void CaptureThreadImplJACK::capture_finished()
-{
-// cerr << "CaptureThreadImplJACK::capture_finished" << endl;
-
- if(m_jack_client!=NULL)
- {
- jack_client_close(m_jack_client);
- m_jack_client = NULL;
-
- m_capture_thread->m_capturing = false;
- m_capture_thread->emitCaptureStoped();
- m_capture_thread->emitCaptureToggled(false);
- }
-}
-#endif
-
-// ------------------------------ PortAudio implementation ----------------------------
-#ifdef CAPTURE_PORTAUDIO
-CaptureThreadImplPortAudio::CaptureThreadImplPortAudio(CaptureThread* capture_thread)
- : CaptureThreadImpl(capture_thread, "PortAudio", QString("Portable cross-platform Audio API (lib:")+Pa_GetVersionText()+"["+QString::number(Pa_GetVersion())+"])")
-{
- m_stream = NULL;
-
- m_source = "default";
-}
-
-bool CaptureThreadImplPortAudio::is_available()
-{
- if(!m_stream)
- {
- try
- {
- m_err = Pa_Initialize();
- if(m_err != paNoError) throw QString("PortAudio: is_available:Pa_Initialize ")+Pa_GetErrorText(m_err);
-
- PaError err;
- int numDevices;
-
- numDevices = Pa_GetDeviceCount();
- if(numDevices < 0)
- throw QString("PortAudio: is_available:Pa_GetDeviceCount ")+Pa_GetErrorText(numDevices);
- else if(numDevices == 0)
- throw QString("PortAudio: is_available:Pa_GetDeviceCount no devices available")+Pa_GetErrorText(numDevices);
-
-/* const PaDeviceInfo *deviceInfo;
-
- for(int i=0; i<numDevices; i++ )
- {
- deviceInfo = Pa_GetDeviceInfo( i );
- cerr << deviceInfo->name << endl;
- cerr << deviceInfo->defaultSampleRate << endl;
- }*/
- }
- catch(QString error)
- {
- Pa_Terminate();
- m_stream = NULL;
- m_status = "N/A";
- return false;
- }
- capture_finished();
- }
-
- m_status = "OK";
-
- return true;
-}
-
-void CaptureThreadImplPortAudio::setSamplingRate(int value)
-{
-// cerr << "CaptureThreadImplPortAudio::setSamplingRate " << value << endl;
-
- assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
-
- if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
- {
- bool was_running = m_capture_thread->isCapturing();
- if(was_running) m_capture_thread->stopCapture();
-
- m_sampling_rate = value;
-
- if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
- {
- try
- {
- set_params(true);
- }
- catch(QString error)
- {
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
-
- try{
- // it was just for testing
- capture_finished();
- }
- catch(QString error)
- {
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
- }
- else
- m_capture_thread->emitSamplingRateChanged();
-
- if(was_running) m_capture_thread->startCapture();
- }
-
-// cerr << "~CaptureThreadImplPortAudio::setSamplingRate" << endl;
-}
-
-int CaptureThreadImplPortAudio::PortAudioCallback( const void *inputBuffer, void *outputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData )
-{((CaptureThreadImplPortAudio*)userData)->portAudioCallback(inputBuffer, framesPerBuffer, timeInfo, statusFlags);}
-int CaptureThreadImplPortAudio::portAudioCallback(const void *inputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags)
-{
- if(m_capture_thread->m_pause)
- return 0;
-
- m_capture_thread->m_lock.lock();
-
- float *in = (float*)inputBuffer;
-
- for(unsigned long i=0; i<framesPerBuffer; i++)
- m_capture_thread->m_values.push_front(*in++);
-// addValue(*in++, i, m_channel_count); // TODO
-
- m_capture_thread->m_packet_size = framesPerBuffer;
- if(m_capture_thread->m_ext_lock)
- {
- m_capture_thread->m_packet_size_sll = 0;
- m_capture_thread->m_ext_lock = false;
- }
- m_capture_thread->m_packet_size_sll += framesPerBuffer;
-
- m_capture_thread->m_lock.unlock();
-
- return 0;
-}
-
-void CaptureThreadImplPortAudio::set_params(bool test)
-{
- m_err = Pa_Initialize();
- if(m_err != paNoError) throw QString("PortAudio: set_params:Pa_Initialize ")+Pa_GetErrorText(m_err);
-
- PaStreamParameters params;
- params.device = paNoDevice;
- params.channelCount = 1;
- params.sampleFormat = paFloat32;
- params.suggestedLatency = 0;
- params.hostApiSpecificStreamInfo = NULL;
-
- if(m_source!="default") // TODO hum hum
- {
- int numDevices = Pa_GetDeviceCount();
- const PaDeviceInfo* deviceInfo;
- int index = -1;
- for(int i=0; params.device==paNoDevice && i<numDevices; i++)
- {
- deviceInfo = Pa_GetDeviceInfo(i);
- if(QString(deviceInfo->name)==m_source)
- params.device = i;
- }
-
- if(params.device==paNoDevice)
- cerr << "CaptureThread: INFO: PortAudio: cannot determine selected source \"" << m_source << "\"" << endl;
- }
-
- if(!test)
- {
- if(params.device==paNoDevice)
- cerr << "CaptureThread: INFO: PortAudio: using default device" << endl;
- else
- cerr << "CaptureThread: INFO: PortAudio: using \"" << m_source << "\"" << endl;
-
- setFormatDescrsAndFns(4, true, true, 1);
- }
-
- if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
- {
- int old_sampling_rate = m_sampling_rate;
-
- cerr << "CaptureThread: INFO: PortAudio: sampling rate set to max or undefined, try to determinate it." << endl;
-
- list<int> sampling_rates;
- sampling_rates.push_front(8000); sampling_rates.push_front(11025); sampling_rates.push_front(16000);
- sampling_rates.push_front(22050); sampling_rates.push_front(24000); sampling_rates.push_front(32000);
- sampling_rates.push_front(44100); sampling_rates.push_front(48000); sampling_rates.push_front(96000);
-
- m_err = -1;
- while(m_err!=paNoError)
- {
- if(sampling_rates.empty())
- throw QString("PortAudio: cannot set any sample rate (")+Pa_GetErrorText(m_err)+")";
-
- m_err = Pa_Initialize();
- if(m_err != paNoError) throw QString("PortAudio: set_params:Pa_Initialize ")+Pa_GetErrorText(m_err);
-
- m_sampling_rate = sampling_rates.front();
- cerr << "CaptureThread: INFO: PortAudio: try to set sampling rate to " << m_sampling_rate << flush;
-
-// cerr << "nbc1 " << params.channelCount << endl;
-
- if(params.device==paNoDevice)
- m_err = Pa_OpenDefaultStream(&m_stream, 1, 0, paFloat32, m_sampling_rate, 0, PortAudioCallback, this);
- else
- m_err = Pa_OpenStream(&m_stream, ¶ms, NULL, m_sampling_rate, 0, paNoFlag, PortAudioCallback, this);
-
- if(m_err != paNoError) cerr << " failed" << endl;
- else cerr << " success" << endl;
-
- sampling_rates.pop_front();
- }
-
- if(old_sampling_rate!=m_sampling_rate)
- m_capture_thread->emitSamplingRateChanged();
- }
- else
- {
-// cerr << "nbc2 " << params.channelCount << endl;
-// cerr << "dev2 " << params.device << "/" << paNoDevice << endl;
-
- if(params.device==paNoDevice)
- {
- m_err = Pa_OpenDefaultStream(&m_stream, 1, 0, paFloat32, m_sampling_rate, 0, PortAudioCallback, this);
- if(m_err != paNoError)
- throw QString("PortAudio: set_params:Pa_OpenDefaultStream ")+Pa_GetErrorText(m_err);
- }
- else
- {
- m_err = Pa_OpenStream(&m_stream, ¶ms, NULL, m_sampling_rate, 0, paNoFlag, PortAudioCallback, this);
- if(m_err != paNoError)
- throw QString("PortAudio: set_params:Pa_OpenStream ")+Pa_GetErrorText(m_err);
- }
- }
-}
-
-void CaptureThreadImplPortAudio::capture_init()
-{
- set_params(false);
-
- m_err = Pa_StartStream(m_stream);
- if(m_err != paNoError)
- throw QString("PortAudio: capture_init:Pa_StartStream ")+Pa_GetErrorText(m_err);
-
- m_capture_thread->m_capturing = true;
- m_capture_thread->emitCaptureStarted();
- m_capture_thread->emitCaptureToggled(true);
-}
-void CaptureThreadImplPortAudio::capture_finished()
-{
- if(m_stream)
- {
- if(!Pa_IsStreamStopped(m_stream))
- {
- m_err = Pa_StopStream(m_stream);
- if(m_err != paNoError) throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
- }
-
- if(m_stream)
- {
- m_err = Pa_CloseStream(m_stream);
- if(m_err != paNoError) throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
- }
-
- m_stream = NULL;
-
- m_capture_thread->m_capturing = false;
- m_capture_thread->emitCaptureStoped();
- m_capture_thread->emitCaptureToggled(false);
- }
-
- m_err = Pa_Terminate();
-// if(m_err != paNoError) throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
-}
-void CaptureThreadImplPortAudio::startCapture()
-{
- try
- {
- capture_init();
- }
- catch(QString error)
- {
- capture_finished();
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
-}
-void CaptureThreadImplPortAudio::stopCapture()
-{
- try
- {
- capture_finished();
- }
- catch(QString error)
- {
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
-}
-CaptureThreadImplPortAudio::~CaptureThreadImplPortAudio()
-{
- stopCapture();
-}
-
-#endif
-
-// ------------------------------ OSS implementation ----------------------------
-#ifdef CAPTURE_OSS
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/soundcard.h>
-
-
-#define OSS_BUFF_SIZE 1024
-
-CaptureThreadImplOSS::CaptureThreadImplOSS(CaptureThread* capture_thread)
- : CaptureThreadImpl(capture_thread, "OSS", QString("Open Sound System"))
-{
- m_fd_in = 0;
- m_oss_buffer = NULL;
- m_format = -1;
-
- m_source = "/dev/dsp";
-
- // oss_sysinfo si; // definition ??
-// ioctl(m_fd_in, OSS_SYSINFO, &si);
-// m_fd_in = open(m_source, O_RDONLY, 0));
-// m_descr = QString("Open Sound System (")+QString::number(SOUND_VERSION, 16)+":"+si.version+")");
-// close(m_fd_in);
-// m_fd_in = 0;
- m_descr = QString("Open Sound System (lib:")+QString::number(SOUND_VERSION, 16)+")";
-
- m_alive = true;
- m_in_run = false;
- m_loop = false;
-}
-
-bool CaptureThreadImplOSS::is_available()
-{
- if(m_fd_in==0)
- {
- try
- {
- if((m_fd_in = open (m_source.latin1(), O_RDONLY, 0)) == -1)
- throw QString(strerror(errno));
- }
- catch(QString error)
- {
- m_fd_in = 0;
-
- m_status = "N/A ("+error+")";
-
- return false;
- }
-
- capture_finished();
- }
-
- m_status = "OK";
-
- // cerr << "CaptureThread: INFO: OSS seems available" << endl;
-
- return true;
-}
-
-void CaptureThreadImplOSS::startCapture()
-{
- if(!running())
- start();
-
- m_loop = true;
-
- m_wait_for_start = true;
- while(m_wait_for_start) // some implementations take a long time to start
- msleep(10);
-}
-void CaptureThreadImplOSS::stopCapture()
-{
- m_loop = false;
-
- while(m_in_run)
- msleep(10);
-}
-
-void CaptureThreadImplOSS::set_params(bool test)
-{
- if(m_source=="")
- throw QString("OSS: set the source first");
- if((m_fd_in = open (m_source.latin1(), O_RDONLY, 0))==-1)
- throw QString("OSS: ")+QString(strerror(errno));
-
- if(!test)
- {
- if(m_format==-1)
- {
- // Formats
- m_format = AFMT_S16_NE; /* Native 16 bits */
- if(ioctl(m_fd_in, SNDCTL_DSP_SETFMT, &m_format)==-1)
- throw QString("OSS: cannot set format (")+strerror(errno)+")";
-
- if(m_format != AFMT_S16_NE)
- throw QString("OSS: cannot set format to signed 16bits");
- }
- else
- {
- if(ioctl(m_fd_in, SNDCTL_DSP_SETFMT, &m_format)==-1)
- throw QString("OSS: cannot set format (")+strerror(errno)+")";
- }
-
- m_format_size = 2;
- m_format_signed = true;
- m_format_float = false;
-
- // Channel count
- unsigned int channel_count = 1;
- if(ioctl(m_fd_in, SNDCTL_DSP_CHANNELS, &channel_count)==-1)
- throw QString("OSS: cannot set channel count to 1 (")+strerror(errno)+")";
-
- if(channel_count != 1)
- throw QString("OSS: the device doesn't support mono mode");
-
- /* if(m_channel_count>1) // TODO
- {
- QString err_msg = QString("OSS: cannot set channel count to one (")+QString::number(m_channel_count)+" instead)";
- cerr << "CaptureThread: WARNING: " << err_msg << endl;
- }*/
-
- setFormatDescrsAndFns(2, true, false, channel_count);
- }
-
- if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
- {
- int old_sampling_rate = m_sampling_rate;
-
- cerr << "CaptureThread: INFO: OSS: sampling rate set to max or undefined, try to determinate it." << endl;
-
- list<int> sampling_rates;
- sampling_rates.push_front(8000); sampling_rates.push_front(11025); sampling_rates.push_front(16000);
- sampling_rates.push_front(22050); sampling_rates.push_front(24000); sampling_rates.push_front(32000);
- sampling_rates.push_front(44100); sampling_rates.push_front(48000); sampling_rates.push_front(96000);
-
- int err = -1;
- while(err<0)
- {
- if(sampling_rates.empty())
- throw QString("OSS: cannot set any sample rate (")+strerror(errno)+")";
-
- m_sampling_rate = sampling_rates.front();
- cerr << "CaptureThread: INFO: OSS: try to set sampling rate to " << m_sampling_rate << flush;
- err = ioctl(m_fd_in, SNDCTL_DSP_SPEED, &m_sampling_rate);
-
- if(err==-1) cerr << " failed" << endl;
- else cerr << " success" << endl;
-
- sampling_rates.pop_front();
- }
-
- if(old_sampling_rate!=m_sampling_rate)
- m_capture_thread->emitSamplingRateChanged();
- }
- else
- {
- if(ioctl(m_fd_in, SNDCTL_DSP_SPEED, &m_sampling_rate)==-1)
- throw QString("OSS: cannot set sampling rate (")+QString(strerror(errno))+")";
- }
-}
-
-void CaptureThreadImplOSS::setSamplingRate(int value)
-{
-// cerr << "CaptureThreadImplOSS::setSamplingRate " << value << endl;
-
- assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
-
- if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
- {
- bool was_running = m_capture_thread->isCapturing();
- if(was_running) m_capture_thread->stopCapture();
-
- m_sampling_rate = value;
-
- if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
- {
- try
- {
- set_params(true);
- }
- catch(QString error)
- {
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
-
- // it was just for testing
- capture_finished();
- }
- else
- m_capture_thread->emitSamplingRateChanged();
-
- if(was_running) m_capture_thread->startCapture();
- }
-
-// cerr << "~CaptureThreadImplOSS::setSamplingRate" << endl;
-}
-
-void CaptureThreadImplOSS::capture_init()
-{
- set_params(false);
-
- m_oss_buffer = new char[m_channel_count*OSS_BUFF_SIZE*16/8];
-}
-void CaptureThreadImplOSS::capture_loop()
-{
-// cerr << "CaptureThreadImplOSS::capture_loop" << endl;
-
- bool format_signed = true;
- int l=0;
-
- m_wait_for_start = false;
- while(m_loop)
- {
- int ret_val = read(m_fd_in, m_oss_buffer, sizeof(m_oss_buffer));
-
- if(ret_val==-1)
- {
- cerr << "CaptureThread: WARNING: OSS: " << strerror(errno) << endl;
- msleep(1000); // TODO which behavior ?
-// m_loop = false;// TODO which behavior ?
- }
- else
- {
- ret_val /= m_format_size;
-
- if(!m_capture_thread->m_pause)
- {
- m_capture_thread->m_lock.lock();
-
- for(int i=0; i<ret_val*m_channel_count; i++)
- addValue(this, decodeValue(m_oss_buffer, i), i);
-
- m_capture_thread->m_packet_size = ret_val;
- if(m_capture_thread->m_ext_lock)
- {
- m_capture_thread->m_packet_size_sll = 0;
- m_capture_thread->m_ext_lock = false;
- }
- m_capture_thread->m_packet_size_sll += ret_val;
-
- m_capture_thread->m_lock.unlock();
- }
- }
- }
-
-// cerr << "~CaptureThreadImplOSS::capture_loop" << endl;
-}
-void CaptureThreadImplOSS::capture_finished()
-{
- if(m_oss_buffer!=NULL)
- {
- delete[] m_oss_buffer;
- m_oss_buffer = NULL;
- }
-
- if(m_fd_in!=0)
- {
- close(m_fd_in);
- m_fd_in = 0;
- }
-}
-
-void CaptureThreadImplOSS::run()
-{
-// cerr << "CaptureThread: INFO: OSS: capture thread entered" << endl;
-
-// while(m_alive) // TODO ?? need to keep oss thread alive to let PortAudio working after ALSA ??
- {
- while(m_alive && !m_loop)
- msleep(10);
-
- m_in_run = true;
-
- try
- {
- // cerr << "CaptureThread: INFO: capture thread running" << endl;
-
- capture_init();
-
- m_capture_thread->m_capturing = true;
- m_capture_thread->emitCaptureStarted();
- m_capture_thread->emitCaptureToggled(true);
-
- capture_loop();
-
- m_capture_thread->m_capturing = false;
- m_capture_thread->emitCaptureStoped();
- m_capture_thread->emitCaptureToggled(false);
- }
- catch(QString error)
- {
- m_loop = false;
- cerr << "CaptureThread: ERROR: " << error << endl;
- m_capture_thread->emitError(error);
- }
- m_wait_for_start = false;
-
- capture_finished();
-
- m_in_run = false;
-
- // cerr << "CaptureThread: INFO: capture thread stop running" << endl;
- }
-
-// cerr << "CaptureThread: INFO: OSS: capture thread exited" << endl;
-}
-
-CaptureThreadImplOSS::~CaptureThreadImplOSS()
-{
-// cerr << "CaptureThreadImplOSS::~CaptureThreadImplOSS" << endl;
-
- m_alive = false;
-
- stopCapture();
-
- while(running())
- msleep(10);
-
-// cerr << "~CaptureThreadImplOSS::~CaptureThreadImplOSS" << endl;
-}
-
-#endif