X-Git-Url: http://git.johnwright.org/?p=fmit.git;a=blobdiff_plain;f=src%2FCaptureThread.cpp;fp=src%2FCaptureThread.cpp;h=9b933033692c824b94fa48c74d30fddb4370e5d6;hp=5c6f86b062cfefa1c8d1e517ea098b466c86243b;hb=49947d1cd4506f5574b3be62ee90e9f00227d9fd;hpb=82c9faab9421b3d87a0faa84a73f55aaccbbb689 diff --git a/src/CaptureThread.cpp b/src/CaptureThread.cpp index 5c6f86b..9b93303 100644 --- a/src/CaptureThread.cpp +++ b/src/CaptureThread.cpp @@ -42,9 +42,11 @@ void AddValue2ChannelFirst(CaptureThreadImpl* impl, double value, int i) 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) { @@ -102,7 +104,7 @@ void CaptureThread::autoDetectTransport() { 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)); @@ -120,7 +122,7 @@ void CaptureThread::autoDetectTransport() } 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(); @@ -138,7 +140,7 @@ void CaptureThread::selectTransport(const QString& name) 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+"'"; } @@ -155,7 +157,7 @@ void CaptureThread::selectTransport(int index) assert(index>=0 && indexgetName() << " transport" << endl; + cerr << "CaptureThread: INFO: change transport to " << m_impls[index]->getName().toStdString() << " transport" << endl; bool was_capturing = isCapturing(); if(was_capturing) @@ -176,7 +178,7 @@ void CaptureThread::listTransports() { cerr << "CaptureThread: INFO: Built in transports" << endl; for(vector::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 { @@ -368,1177 +370,3 @@ void CaptureThreadImpl::setFormatDescrsAndFns(int format_size, bool format_signe 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 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 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; im_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; im_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; iname << 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; im_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 && iname)==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 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 -#include -#include -#include -#include -#include -#include - - -#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 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; im_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