1 // Copyright 2004 "Gilles Degottex"
3 // This file is part of "Music"
5 // "Music" is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 2.1 of the License, or
8 // (at your option) any later version.
10 // "Music" is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "CaptureThread.h"
31 #include <qdatetime.h>
33 double DecodeUnsigned8Bits(void* buffer, int i) {return 2*(((unsigned char*)buffer)[i])/256.0 - 1;}
34 double DecodeSigned8Bits(void* buffer, int i) {return (((signed char*)buffer)[i])/128.0;}
35 double DecodeUnsigned16Bits(void* buffer, int i){return 2*((unsigned short*)buffer)[i]/65536.0 - 1;}
36 double DecodeSigned16Bits(void* buffer, int i) {return ((signed short*)buffer)[i]/32768.0;}
37 void AddValue2ChannelFirst(CaptureThreadImpl* impl, double value, int i)
40 impl->m_capture_thread->m_values.push_front(value);
42 void AddValue2ChannelMix(CaptureThreadImpl* impl, double value, int i)
45 impl->m_capture_thread->m_values.push_front(value);
47 impl->m_capture_thread->m_values[0] = (impl->m_capture_thread->m_values[0]+value)/2.0;
49 void AddValue1Channel(CaptureThreadImpl* impl, double value, int i)
51 impl->m_capture_thread->m_values.push_front(value);
54 CaptureThread::CaptureThread(const QString& name)
56 m_current_impl = NULL;
61 m_packet_size_sll = 0;
64 m_mix_multiple_channel = false;
69 m_impls.push_back(new CaptureThreadImplJACK(this));
72 m_impls.push_back(new CaptureThreadImplALSA(this));
75 m_impls.push_back(new CaptureThreadImplOSS(this));
77 #ifdef CAPTURE_PORTAUDIO
78 m_impls.push_back(new CaptureThreadImplPortAudio(this));
84 void CaptureThread::autoDetectTransport()
86 bool was_capturing = isCapturing();
91 if(m_current_impl!=NULL)
92 old_name = m_current_impl->m_name;
94 cerr << "CaptureThread: INFO: Auto detecting a working transport ... " << flush;
96 CaptureThreadImpl* impl = NULL;
97 for(vector<CaptureThreadImpl*>::iterator it=m_impls.begin(); impl==NULL && it!=m_impls.end(); it++)
98 if((*it)->is_available())
103 m_current_impl = impl;
105 cerr << "using " << m_current_impl->m_name << endl;
107 if(m_current_impl->m_name!=old_name)
108 emit(transportChanged(m_current_impl->m_name));
115 cerr << "no working transport !" << endl;
118 emit(transportChanged(""));
121 void CaptureThread::selectTransport(const QString& name)
123 cerr << "CaptureThread: INFO: using " << name << " transport" << endl;
124 if(getCurrentTransport() && name==getCurrentTransport()->getName()) return;
126 bool was_capturing = isCapturing();
131 if(m_current_impl!=NULL)
132 old_name = m_current_impl->m_name;
134 CaptureThreadImpl* impl = NULL;
135 for(vector<CaptureThreadImpl*>::iterator it=m_impls.begin(); impl==NULL && it!=m_impls.end(); it++)
136 if((*it)->m_name==name)
141 cerr << "CaptureThread: ERROR: unknown transport '" << name << "'" << endl;
142 throw QString("CaptureThread: ERROR: unknown transport '")+name+"'";
145 m_current_impl = impl;
147 if(m_current_impl->m_name!=old_name)
148 emit(transportChanged(m_current_impl->m_name));
153 void CaptureThread::selectTransport(int index)
155 assert(index>=0 && index<m_impls.size());
157 if(m_impls[index]==getCurrentTransport()) return;
158 cerr << "CaptureThread: INFO: change transport to " << m_impls[index]->getName() << " transport" << endl;
160 bool was_capturing = isCapturing();
164 m_current_impl = m_impls[index];
166 emit(transportChanged(m_current_impl->m_name));
171 const vector<CaptureThreadImpl*>& CaptureThread::getTransports() const
175 void CaptureThread::listTransports()
177 cerr << "CaptureThread: INFO: Built in transports" << endl;
178 for(vector<CaptureThreadImpl*>::iterator it=m_impls.begin(); it!=m_impls.end(); it++)
179 cerr << "CaptureThread: INFO: " << (*it)->getStatus() << " " << (*it)->m_name << " " << (*it)->m_descr << endl;
181 const CaptureThreadImpl* CaptureThread::getCurrentTransport() const
183 return m_current_impl;
185 int CaptureThread::getCurrentTransportIndex() const
187 for(int i=0; i<m_impls.size(); i++)
188 if(m_impls[i]==getCurrentTransport())
193 QString CaptureThread::getCurrentTransportDescr() const
195 if(m_current_impl==NULL)
198 return m_current_impl->m_descr;
200 const CaptureThreadImpl* CaptureThread::getTransport(const QString& name) const
202 for(vector<CaptureThreadImpl*>::const_iterator it=m_impls.begin(); it!=m_impls.end(); it++)
203 if((*it)->m_name==name)
208 QString CaptureThread::getFormatDescr() const
210 if(m_current_impl==NULL)
216 void CaptureThread::emitError(const QString& error)
218 emit(errorRaised(error));
220 void CaptureThread::emitSamplingRateChanged()
222 if(m_current_impl->m_sampling_rate>0)
223 emit(samplingRateChanged(m_current_impl->m_sampling_rate));
225 void CaptureThread::emitCaptureStarted()
227 emit(captureStarted());
229 void CaptureThread::emitCaptureStoped()
231 emit(captureStoped());
233 void CaptureThread::emitCaptureToggled(bool value)
235 emit(captureToggled(value));
238 void CaptureThread::startCapture()
240 if(m_current_impl==NULL) return;
242 m_current_impl->startCapture();
244 void CaptureThread::stopCapture()
246 // cerr << "CaptureThread::stopCapture" << endl;
248 if(m_current_impl==NULL) return;
250 m_current_impl->stopCapture();
252 // cerr << "/CaptureThread::stopCapture" << endl;
255 void CaptureThread::toggleCapture(bool run)
257 if(run && !m_capturing) startCapture();
258 if(!run && m_capturing) stopCapture();
261 void CaptureThread::reset()
267 void CaptureThread::togglePause(bool pause)
272 int CaptureThread::getSamplingRate() const
274 if(m_current_impl==NULL) return SAMPLING_RATE_UNKNOWN;
276 return m_current_impl->m_sampling_rate;
278 void CaptureThread::setSamplingRate(int rate)
280 if(m_current_impl!=NULL)
281 m_current_impl->setSamplingRate(rate);
283 void CaptureThread::setSource(const QString& name)
285 if(m_current_impl==NULL)
287 cerr << "CaptureThread: setSource: ERROR: select a transport first" << endl;
291 if(name!=m_current_impl->m_source)
293 m_current_impl->m_source = name;
300 emit(sourceChanged(m_current_impl->m_source));
304 void CaptureThread::setMixMultipleChannels(bool mix)
306 m_mix_multiple_channel = mix;
309 CaptureThread::~CaptureThread()
313 for(vector<CaptureThreadImpl*>::iterator it=m_impls.begin(); it!=m_impls.end(); it++)
317 // -------------------------------- implementation ------------------------------
319 CaptureThreadImpl::CaptureThreadImpl(CaptureThread* capture_thread, const QString& name, const QString& descr)
320 : m_capture_thread(capture_thread)
326 m_sampling_rate = CaptureThread::SAMPLING_RATE_UNKNOWN;
328 m_format_signed = true;
333 const QString& CaptureThreadImpl::getStatus()
341 void CaptureThreadImpl::setFormatDescrsAndFns(int format_size, bool format_signed, bool format_float, int channel_count)
343 m_format_size = format_size;
344 m_format_signed = format_signed;
345 m_format_float = format_float;
346 m_channel_count = channel_count;
348 if(m_format_size==2) // 16bits
350 if(m_format_signed) decodeValue = DecodeSigned16Bits;
351 else decodeValue = DecodeUnsigned16Bits;
355 if(m_format_signed) decodeValue = DecodeSigned8Bits;
356 else decodeValue = DecodeUnsigned8Bits;
359 if(m_channel_count==1)
360 addValue = AddValue1Channel;
361 else if(m_channel_count==2)
363 if(m_capture_thread->m_mix_multiple_channel)
364 addValue = AddValue2ChannelMix;
366 addValue = AddValue2ChannelFirst;
369 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;
372 // ------------------------------ ALSA implementation ----------------------------
375 #define ALSA_BUFF_SIZE 1024
377 void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt, ...)
379 cerr << "alsa_error_handler: " << file << ":" << line << " " << function << " err=" << err << endl;
382 CaptureThreadImplALSA::CaptureThreadImplALSA(CaptureThread* capture_thread)
383 : CaptureThreadImpl(capture_thread, "ALSA", QString("Advanced Linux Sound Architecture (lib:")+snd_asoundlib_version()+")")
385 m_alsa_capture_handle = NULL;
386 m_alsa_hw_params = NULL;
387 m_alsa_buffer = NULL;
388 m_format = SND_PCM_FORMAT_UNKNOWN;
396 // snd_lib_error_set_handler(alsa_error_handler);
399 bool CaptureThreadImplALSA::is_available()
401 if(m_alsa_capture_handle==NULL)
406 if((err=snd_pcm_open(&m_alsa_capture_handle, m_source.latin1(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
408 if(err==-19) // TODO risks of changes for the error code
409 throw QString("invalid source '")+m_source+"'";
411 throw QString("device '")+m_source+"' busy";
413 throw QString("cannot open pcm: ")+QString(snd_strerror(err));
418 m_alsa_capture_handle = NULL;
420 m_status = "N/A ("+error+")";
425 if(m_alsa_capture_handle!=NULL)
427 snd_pcm_close(m_alsa_capture_handle);
428 m_alsa_capture_handle = NULL;
434 // cerr << "CaptureThread: INFO: ALSA seems available" << endl;
439 void CaptureThreadImplALSA::startCapture()
446 m_wait_for_start = true;
447 while(m_wait_for_start) // some implementations take a long time to start
450 void CaptureThreadImplALSA::stopCapture()
458 void CaptureThreadImplALSA::set_params(bool test)
460 // cerr << "ALSA: Recognized sample formats are" << endl;
461 // for (int k = 0; k < SND_PCM_FORMAT_LAST; ++(unsigned long) k) {
462 // const char *s = snd_pcm_format_name((snd_pcm_format_t)k);
463 // if (s) cerr << s << endl;
468 throw QString("ALSA: set the source first");
469 if((err=snd_pcm_open(&m_alsa_capture_handle, m_source.latin1(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
471 // cerr << "err=" << err << ":" << snd_strerror(err) << endl;
473 if(err==-19) // TODO risks of changes for the error code
474 throw QString("ALSA: Invalid Source '")+m_source+"'";
476 throw QString("ALSA: Device '")+m_source+"' busy";
478 throw QString("ALSA: Cannot open pcm: ")+QString(snd_strerror(err));
481 snd_pcm_hw_params_alloca(&m_alsa_hw_params);
483 if((err=snd_pcm_hw_params_any(m_alsa_capture_handle, m_alsa_hw_params)) < 0)
484 throw QString("ALSA: cannot initialize hardware parameter structure (")+QString(snd_strerror(err))+")";
486 if((err=snd_pcm_hw_params_set_access(m_alsa_capture_handle, m_alsa_hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
487 throw QString("ALSA: cannot set access type (")+QString(snd_strerror(err))+")";
494 list<snd_pcm_format_t> formats;
495 formats.push_back(SND_PCM_FORMAT_S16); formats.push_back(SND_PCM_FORMAT_U16);
496 formats.push_back(SND_PCM_FORMAT_S8); formats.push_back(SND_PCM_FORMAT_U8);
502 throw QString("ALSA: cannot set any format (")+QString(snd_strerror(err))+")";
504 m_format = formats.front();
505 cerr << "CaptureThread: INFO: ALSA: try to set format to " << snd_pcm_format_description(m_format) << flush;
506 err=snd_pcm_hw_params_set_format(m_alsa_capture_handle, m_alsa_hw_params, m_format);
508 if(err<0) cerr << " failed" << endl;
509 else cerr << " success" << endl;
516 if((err=snd_pcm_hw_params_set_format(m_alsa_capture_handle, m_alsa_hw_params, m_format))<0)
518 QString err_msg = QString("ALSA: cannot set format (")+QString(snd_strerror(err))+")";
519 cerr << "CaptureThread: ERROR: " << err_msg << endl;
524 unsigned int channel_count = 1;
525 if((err=snd_pcm_hw_params_set_channels_near(m_alsa_capture_handle, m_alsa_hw_params, &channel_count)) < 0)
527 QString err_msg = QString("ALSA: cannot set channel count (")+QString(snd_strerror(err))+")";
528 cerr << "CaptureThread: WARNING: " << err_msg << endl;
532 QString err_msg = QString("ALSA: cannot set channel count to one (")+QString::number(channel_count)+" instead)";
533 cerr << "CaptureThread: WARNING: " << err_msg << endl;
536 setFormatDescrsAndFns(snd_pcm_format_width(m_format)/8, snd_pcm_format_signed(m_format), false, channel_count);
539 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
541 int old_sampling_rate = m_sampling_rate;
543 cerr << "CaptureThread: INFO: ALSA: sampling rate set to max or undefined, try to determinate it." << endl;
545 list<int> sampling_rates;
546 sampling_rates.push_front(8000); sampling_rates.push_front(11025); sampling_rates.push_front(16000);
547 sampling_rates.push_front(22050); sampling_rates.push_front(24000); sampling_rates.push_front(32000);
548 sampling_rates.push_front(44100); sampling_rates.push_front(48000); sampling_rates.push_front(96000);
553 if(sampling_rates.empty())
554 throw QString("ALSA: cannot set any sample rate (")+QString(snd_strerror(err))+")";
556 m_sampling_rate = sampling_rates.front();
557 cerr << "CaptureThread: INFO: ALSA: try to set sampling rate to " << m_sampling_rate << flush;
558 unsigned int rrate = m_sampling_rate;
559 err = snd_pcm_hw_params_set_rate(m_alsa_capture_handle, m_alsa_hw_params, rrate, 0);
561 if(err<0) cerr << " failed" << endl;
562 else cerr << " success" << endl;
564 sampling_rates.pop_front();
567 if(old_sampling_rate!=m_sampling_rate)
568 m_capture_thread->emitSamplingRateChanged();
574 unsigned int rrate = m_sampling_rate;
575 if((err = snd_pcm_hw_params_set_rate_near(m_alsa_capture_handle, m_alsa_hw_params, &rrate, &dir))<0)
576 throw QString("ALSA: cannot set sampling rate (")+QString(snd_strerror(err))+")";
577 if(m_sampling_rate!=rrate)
578 m_capture_thread->emitSamplingRateChanged();
579 m_sampling_rate = rrate;
582 if((err=snd_pcm_hw_params(m_alsa_capture_handle, m_alsa_hw_params)) < 0)
583 throw QString("ALSA: cannot set parameters (")+QString(snd_strerror(err))+")";
586 void CaptureThreadImplALSA::setSamplingRate(int value)
588 // cerr << "CaptureThreadImplALSA::setSamplingRate " << value << endl;
590 assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
592 if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
594 bool was_running = m_capture_thread->isCapturing();
595 if(was_running) m_capture_thread->stopCapture();
597 m_sampling_rate = value;
599 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
607 cerr << "CaptureThread: ERROR: " << error << endl;
608 m_capture_thread->emitError(error);
611 // it was just for testing
615 m_capture_thread->emitSamplingRateChanged();
617 if(was_running) m_capture_thread->startCapture();
620 // cerr << "~CaptureThreadImplALSA::setSamplingRate" << endl;
623 void CaptureThreadImplALSA::capture_init()
627 snd_pcm_nonblock(m_alsa_capture_handle, 0);
629 m_alsa_buffer = new char[m_channel_count*ALSA_BUFF_SIZE*snd_pcm_format_width(m_format)/8];
633 if((err=snd_pcm_prepare(m_alsa_capture_handle)) < 0)
634 throw QString("ALSA: cannot prepare audio interface for use (")+QString(snd_strerror(err))+")";
636 void CaptureThreadImplALSA::capture_loop()
638 // cerr << "CaptureThreadImplALSA::capture_loop" << endl;
640 m_wait_for_start = false;
643 int ret_val = snd_pcm_readi(m_alsa_capture_handle, m_alsa_buffer, ALSA_BUFF_SIZE);
646 cerr << "CaptureThread: WARNING: ALSA: " << snd_strerror(ret_val) << endl;
647 while((ret_val = snd_pcm_prepare(m_alsa_capture_handle)) < 0)
650 cerr << QString("ALSA: cannot prepare audio interface (")+QString(snd_strerror(ret_val))+")" << endl;
651 // throw QString("ALSA: cannot prepare audio interface (")+QString(snd_strerror(ret_val))+")";
656 if(!m_capture_thread->m_pause)
658 m_capture_thread->m_lock.lock();
660 // cerr << "CaptureThreadImplALSA::capture_loop " << m_capture_thread->m_values.size() << endl;
662 for(int i=0; i<ret_val*m_channel_count; i++)
663 addValue(this, decodeValue(m_alsa_buffer, i), i);
665 m_capture_thread->m_packet_size = ret_val;
666 if(m_capture_thread->m_ext_lock)
668 m_capture_thread->m_packet_size_sll = 0;
669 m_capture_thread->m_ext_lock = false;
671 m_capture_thread->m_packet_size_sll += ret_val;
673 m_capture_thread->m_lock.unlock();
678 // cerr << "~CaptureThreadImplALSA::capture_loop" << endl;
680 void CaptureThreadImplALSA::capture_finished()
682 if(m_alsa_buffer!=NULL)
684 delete[] m_alsa_buffer;
685 m_alsa_buffer = NULL;
688 if(m_alsa_capture_handle!=NULL)
690 snd_pcm_hw_free(m_alsa_capture_handle);
691 snd_pcm_close(m_alsa_capture_handle);
692 m_alsa_capture_handle = NULL;
696 void CaptureThreadImplALSA::run()
698 // cerr << "CaptureThread: INFO: ALSA: capture thread entered" << endl;
700 // while(m_alive) // TODO need to keep alsa thread alive to let PortAudio working after ALSA !!
702 while(m_alive && !m_loop)
709 // cerr << "CaptureThread: INFO: capture thread running" << endl;
713 m_capture_thread->m_capturing = true;
714 m_capture_thread->emitCaptureStarted();
715 m_capture_thread->emitCaptureToggled(true);
719 m_capture_thread->m_capturing = false;
720 m_capture_thread->emitCaptureStoped();
721 m_capture_thread->emitCaptureToggled(false);
726 cerr << "CaptureThread: ERROR: " << error << endl;
727 m_capture_thread->emitError(error);
729 m_wait_for_start = false;
735 // cerr << "CaptureThread: INFO: capture thread stop running" << endl;
738 // cerr << "CaptureThread: INFO: ALSA: capture thread exited" << endl;
741 CaptureThreadImplALSA::~CaptureThreadImplALSA()
743 // cerr << "CaptureThreadImplALSA::~CaptureThreadImplALSA" << endl;
752 // cerr << "~CaptureThreadImplALSA::~CaptureThreadImplALSA" << endl;
757 // ------------------------------ JACK implementation ----------------------------
759 CaptureThreadImplJACK::CaptureThreadImplJACK(CaptureThread* capture_thread)
760 : CaptureThreadImpl(capture_thread, "JACK", "Jack Audio Connection Kit")
762 m_jack_client = NULL;
766 bool CaptureThreadImplJACK::is_available()
768 if(m_jack_client==NULL)
772 m_jack_client = jack_client_new((m_capture_thread->m_name+"_test").latin1());
773 if(m_jack_client==NULL)
774 throw QString("unknown reason");
778 m_jack_client = NULL;
785 m_status = "available";
790 void CaptureThreadImplJACK::setSamplingRate(int value)
792 cerr << "CaptureThread: ERROR: JACK: setSamplingRate not available with JACK ! change the JACK server sampling rate instead" << endl;
795 void CaptureThreadImplJACK::startCapture()
804 cerr << "CaptureThread: ERROR: " << error << endl;
805 m_capture_thread->emitError(error);
808 void CaptureThreadImplJACK::stopCapture()
816 cerr << "CaptureThread: ERROR: " << error << endl;
817 m_capture_thread->emitError(error);
821 void CaptureThreadImplJACK::JackShutdown(void* arg){((CaptureThreadImplJACK*)arg)->jackShutdown();}
822 void CaptureThreadImplJACK::jackShutdown()
824 m_jack_client = NULL;
826 m_capture_thread->emitError("JACK: server shutdown !");
829 int CaptureThreadImplJACK::JackSampleRate(jack_nframes_t nframes, void* arg){return ((CaptureThreadImplJACK*)arg)->jackSampleRate(nframes);}
830 int CaptureThreadImplJACK::jackSampleRate(jack_nframes_t nframes)
832 if(m_sampling_rate!=int(nframes))
834 m_sampling_rate = nframes;
835 m_capture_thread->emitSamplingRateChanged();
841 int CaptureThreadImplJACK::JackProcess(jack_nframes_t nframes, void* arg){return ((CaptureThreadImplJACK*)arg)->jackProcess(nframes);}
842 int CaptureThreadImplJACK::jackProcess(jack_nframes_t nframes)
844 // cerr << "'" << nframes << "'" << endl;
846 if(m_capture_thread->m_pause || !m_capture_thread->m_capturing || nframes<=0) return 0;
848 void* pin = jack_port_get_buffer(m_jack_port, nframes);
852 jack_default_audio_sample_t* in = (jack_default_audio_sample_t*)pin;
854 m_capture_thread->m_lock.lock();
856 for(jack_nframes_t i=0; i<nframes; i++)
857 m_capture_thread->m_values.push_front(in[i]);
859 m_capture_thread->m_lock.unlock();
861 m_capture_thread->m_packet_size = nframes;
862 if(m_capture_thread->m_ext_lock)
864 m_capture_thread->m_packet_size_sll = 0;
865 m_capture_thread->m_ext_lock = false;
867 m_capture_thread->m_packet_size_sll += nframes;
872 void CaptureThreadImplJACK::capture_init()
874 m_jack_client = jack_client_new(m_capture_thread->m_name.latin1());
876 throw QString("JACK: cannot create client, JACK deamon is running ?");
878 jack_set_process_callback(m_jack_client, JackProcess, (void*)this);
879 jack_on_shutdown(m_jack_client, JackShutdown, (void*)this);
880 jack_set_error_function(jack_error_callback);
881 jack_set_sample_rate_callback(m_jack_client, JackSampleRate, (void*)this);
884 if((err=jack_activate(m_jack_client))!=0)
885 throw QString("JACK: cannot activate client");
887 setFormatDescrsAndFns(sizeof(jack_default_audio_sample_t), true, true, 1);
889 m_jack_port = jack_port_register(m_jack_client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput,0);
892 if((err=jack_connect(m_jack_client, m_source.latin1(), (m_capture_thread->m_name+":input").latin1()))!=0)
893 m_capture_thread->emitError(QString("JACK: Invalid source '")+m_source+"'");
895 int old_sampling_rate = m_sampling_rate;
896 m_sampling_rate = jack_get_sample_rate(m_jack_client);
897 if(m_sampling_rate!=old_sampling_rate)
898 m_capture_thread->emitSamplingRateChanged();
900 m_capture_thread->m_capturing = true;
901 m_capture_thread->emitCaptureStarted();
902 m_capture_thread->emitCaptureToggled(true);
904 void CaptureThreadImplJACK::capture_finished()
906 // cerr << "CaptureThreadImplJACK::capture_finished" << endl;
908 if(m_jack_client!=NULL)
910 jack_client_close(m_jack_client);
911 m_jack_client = NULL;
913 m_capture_thread->m_capturing = false;
914 m_capture_thread->emitCaptureStoped();
915 m_capture_thread->emitCaptureToggled(false);
920 // ------------------------------ PortAudio implementation ----------------------------
921 #ifdef CAPTURE_PORTAUDIO
922 CaptureThreadImplPortAudio::CaptureThreadImplPortAudio(CaptureThread* capture_thread)
923 : CaptureThreadImpl(capture_thread, "PortAudio", QString("Portable cross-platform Audio API (lib:")+Pa_GetVersionText()+"["+QString::number(Pa_GetVersion())+"])")
927 m_source = "default";
930 bool CaptureThreadImplPortAudio::is_available()
936 m_err = Pa_Initialize();
937 if(m_err != paNoError) throw QString("PortAudio: is_available:Pa_Initialize ")+Pa_GetErrorText(m_err);
942 numDevices = Pa_GetDeviceCount();
944 throw QString("PortAudio: is_available:Pa_GetDeviceCount ")+Pa_GetErrorText(numDevices);
945 else if(numDevices == 0)
946 throw QString("PortAudio: is_available:Pa_GetDeviceCount no devices available")+Pa_GetErrorText(numDevices);
948 /* const PaDeviceInfo *deviceInfo;
950 for(int i=0; i<numDevices; i++ )
952 deviceInfo = Pa_GetDeviceInfo( i );
953 cerr << deviceInfo->name << endl;
954 cerr << deviceInfo->defaultSampleRate << endl;
972 void CaptureThreadImplPortAudio::setSamplingRate(int value)
974 // cerr << "CaptureThreadImplPortAudio::setSamplingRate " << value << endl;
976 assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
978 if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
980 bool was_running = m_capture_thread->isCapturing();
981 if(was_running) m_capture_thread->stopCapture();
983 m_sampling_rate = value;
985 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
993 cerr << "CaptureThread: ERROR: " << error << endl;
994 m_capture_thread->emitError(error);
998 // it was just for testing
1001 catch(QString error)
1003 cerr << "CaptureThread: ERROR: " << error << endl;
1004 m_capture_thread->emitError(error);
1008 m_capture_thread->emitSamplingRateChanged();
1010 if(was_running) m_capture_thread->startCapture();
1013 // cerr << "~CaptureThreadImplPortAudio::setSamplingRate" << endl;
1016 int CaptureThreadImplPortAudio::PortAudioCallback( const void *inputBuffer, void *outputBuffer,
1017 unsigned long framesPerBuffer,
1018 const PaStreamCallbackTimeInfo* timeInfo,
1019 PaStreamCallbackFlags statusFlags,
1021 {((CaptureThreadImplPortAudio*)userData)->portAudioCallback(inputBuffer, framesPerBuffer, timeInfo, statusFlags);}
1022 int CaptureThreadImplPortAudio::portAudioCallback(const void *inputBuffer,
1023 unsigned long framesPerBuffer,
1024 const PaStreamCallbackTimeInfo* timeInfo,
1025 PaStreamCallbackFlags statusFlags)
1027 if(m_capture_thread->m_pause)
1030 m_capture_thread->m_lock.lock();
1032 float *in = (float*)inputBuffer;
1034 for(unsigned long i=0; i<framesPerBuffer; i++)
1035 m_capture_thread->m_values.push_front(*in++);
1036 // addValue(*in++, i, m_channel_count); // TODO
1038 m_capture_thread->m_packet_size = framesPerBuffer;
1039 if(m_capture_thread->m_ext_lock)
1041 m_capture_thread->m_packet_size_sll = 0;
1042 m_capture_thread->m_ext_lock = false;
1044 m_capture_thread->m_packet_size_sll += framesPerBuffer;
1046 m_capture_thread->m_lock.unlock();
1051 void CaptureThreadImplPortAudio::set_params(bool test)
1053 m_err = Pa_Initialize();
1054 if(m_err != paNoError) throw QString("PortAudio: set_params:Pa_Initialize ")+Pa_GetErrorText(m_err);
1056 PaStreamParameters params;
1057 params.device = paNoDevice;
1058 params.channelCount = 1;
1059 params.sampleFormat = paFloat32;
1060 params.suggestedLatency = 0;
1061 params.hostApiSpecificStreamInfo = NULL;
1063 if(m_source!="default") // TODO hum hum
1065 int numDevices = Pa_GetDeviceCount();
1066 const PaDeviceInfo* deviceInfo;
1068 for(int i=0; params.device==paNoDevice && i<numDevices; i++)
1070 deviceInfo = Pa_GetDeviceInfo(i);
1071 if(QString(deviceInfo->name)==m_source)
1075 if(params.device==paNoDevice)
1076 cerr << "CaptureThread: INFO: PortAudio: cannot determine selected source \"" << m_source << "\"" << endl;
1081 if(params.device==paNoDevice)
1082 cerr << "CaptureThread: INFO: PortAudio: using default device" << endl;
1084 cerr << "CaptureThread: INFO: PortAudio: using \"" << m_source << "\"" << endl;
1086 setFormatDescrsAndFns(4, true, true, 1);
1089 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
1091 int old_sampling_rate = m_sampling_rate;
1093 cerr << "CaptureThread: INFO: PortAudio: sampling rate set to max or undefined, try to determinate it." << endl;
1095 list<int> sampling_rates;
1096 sampling_rates.push_front(8000); sampling_rates.push_front(11025); sampling_rates.push_front(16000);
1097 sampling_rates.push_front(22050); sampling_rates.push_front(24000); sampling_rates.push_front(32000);
1098 sampling_rates.push_front(44100); sampling_rates.push_front(48000); sampling_rates.push_front(96000);
1101 while(m_err!=paNoError)
1103 if(sampling_rates.empty())
1104 throw QString("PortAudio: cannot set any sample rate (")+Pa_GetErrorText(m_err)+")";
1106 m_err = Pa_Initialize();
1107 if(m_err != paNoError) throw QString("PortAudio: set_params:Pa_Initialize ")+Pa_GetErrorText(m_err);
1109 m_sampling_rate = sampling_rates.front();
1110 cerr << "CaptureThread: INFO: PortAudio: try to set sampling rate to " << m_sampling_rate << flush;
1112 // cerr << "nbc1 " << params.channelCount << endl;
1114 if(params.device==paNoDevice)
1115 m_err = Pa_OpenDefaultStream(&m_stream, 1, 0, paFloat32, m_sampling_rate, 0, PortAudioCallback, this);
1117 m_err = Pa_OpenStream(&m_stream, ¶ms, NULL, m_sampling_rate, 0, paNoFlag, PortAudioCallback, this);
1119 if(m_err != paNoError) cerr << " failed" << endl;
1120 else cerr << " success" << endl;
1122 sampling_rates.pop_front();
1125 if(old_sampling_rate!=m_sampling_rate)
1126 m_capture_thread->emitSamplingRateChanged();
1130 // cerr << "nbc2 " << params.channelCount << endl;
1131 // cerr << "dev2 " << params.device << "/" << paNoDevice << endl;
1133 if(params.device==paNoDevice)
1135 m_err = Pa_OpenDefaultStream(&m_stream, 1, 0, paFloat32, m_sampling_rate, 0, PortAudioCallback, this);
1136 if(m_err != paNoError)
1137 throw QString("PortAudio: set_params:Pa_OpenDefaultStream ")+Pa_GetErrorText(m_err);
1141 m_err = Pa_OpenStream(&m_stream, ¶ms, NULL, m_sampling_rate, 0, paNoFlag, PortAudioCallback, this);
1142 if(m_err != paNoError)
1143 throw QString("PortAudio: set_params:Pa_OpenStream ")+Pa_GetErrorText(m_err);
1148 void CaptureThreadImplPortAudio::capture_init()
1152 m_err = Pa_StartStream(m_stream);
1153 if(m_err != paNoError)
1154 throw QString("PortAudio: capture_init:Pa_StartStream ")+Pa_GetErrorText(m_err);
1156 m_capture_thread->m_capturing = true;
1157 m_capture_thread->emitCaptureStarted();
1158 m_capture_thread->emitCaptureToggled(true);
1160 void CaptureThreadImplPortAudio::capture_finished()
1164 if(!Pa_IsStreamStopped(m_stream))
1166 m_err = Pa_StopStream(m_stream);
1167 if(m_err != paNoError) throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
1172 m_err = Pa_CloseStream(m_stream);
1173 if(m_err != paNoError) throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
1178 m_capture_thread->m_capturing = false;
1179 m_capture_thread->emitCaptureStoped();
1180 m_capture_thread->emitCaptureToggled(false);
1183 m_err = Pa_Terminate();
1184 // if(m_err != paNoError) throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
1186 void CaptureThreadImplPortAudio::startCapture()
1192 catch(QString error)
1195 cerr << "CaptureThread: ERROR: " << error << endl;
1196 m_capture_thread->emitError(error);
1199 void CaptureThreadImplPortAudio::stopCapture()
1205 catch(QString error)
1207 cerr << "CaptureThread: ERROR: " << error << endl;
1208 m_capture_thread->emitError(error);
1211 CaptureThreadImplPortAudio::~CaptureThreadImplPortAudio()
1218 // ------------------------------ OSS implementation ----------------------------
1225 #include <sys/ioctl.h>
1226 #include <sys/soundcard.h>
1229 #define OSS_BUFF_SIZE 1024
1231 CaptureThreadImplOSS::CaptureThreadImplOSS(CaptureThread* capture_thread)
1232 : CaptureThreadImpl(capture_thread, "OSS", QString("Open Sound System"))
1235 m_oss_buffer = NULL;
1238 m_source = "/dev/dsp";
1240 // oss_sysinfo si; // definition ??
1241 // ioctl(m_fd_in, OSS_SYSINFO, &si);
1242 // m_fd_in = open(m_source, O_RDONLY, 0));
1243 // m_descr = QString("Open Sound System (")+QString::number(SOUND_VERSION, 16)+":"+si.version+")");
1246 m_descr = QString("Open Sound System (lib:")+QString::number(SOUND_VERSION, 16)+")";
1253 bool CaptureThreadImplOSS::is_available()
1259 if((m_fd_in = open (m_source.latin1(), O_RDONLY, 0)) == -1)
1260 throw QString(strerror(errno));
1262 catch(QString error)
1266 m_status = "N/A ("+error+")";
1276 // cerr << "CaptureThread: INFO: OSS seems available" << endl;
1281 void CaptureThreadImplOSS::startCapture()
1288 m_wait_for_start = true;
1289 while(m_wait_for_start) // some implementations take a long time to start
1292 void CaptureThreadImplOSS::stopCapture()
1300 void CaptureThreadImplOSS::set_params(bool test)
1303 throw QString("OSS: set the source first");
1304 if((m_fd_in = open (m_source.latin1(), O_RDONLY, 0))==-1)
1305 throw QString("OSS: ")+QString(strerror(errno));
1312 m_format = AFMT_S16_NE; /* Native 16 bits */
1313 if(ioctl(m_fd_in, SNDCTL_DSP_SETFMT, &m_format)==-1)
1314 throw QString("OSS: cannot set format (")+strerror(errno)+")";
1316 if(m_format != AFMT_S16_NE)
1317 throw QString("OSS: cannot set format to signed 16bits");
1321 if(ioctl(m_fd_in, SNDCTL_DSP_SETFMT, &m_format)==-1)
1322 throw QString("OSS: cannot set format (")+strerror(errno)+")";
1326 m_format_signed = true;
1327 m_format_float = false;
1330 unsigned int channel_count = 1;
1331 if(ioctl(m_fd_in, SNDCTL_DSP_CHANNELS, &channel_count)==-1)
1332 throw QString("OSS: cannot set channel count to 1 (")+strerror(errno)+")";
1334 if(channel_count != 1)
1335 throw QString("OSS: the device doesn't support mono mode");
1337 /* if(m_channel_count>1) // TODO
1339 QString err_msg = QString("OSS: cannot set channel count to one (")+QString::number(m_channel_count)+" instead)";
1340 cerr << "CaptureThread: WARNING: " << err_msg << endl;
1343 setFormatDescrsAndFns(2, true, false, channel_count);
1346 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
1348 int old_sampling_rate = m_sampling_rate;
1350 cerr << "CaptureThread: INFO: OSS: sampling rate set to max or undefined, try to determinate it." << endl;
1352 list<int> sampling_rates;
1353 sampling_rates.push_front(8000); sampling_rates.push_front(11025); sampling_rates.push_front(16000);
1354 sampling_rates.push_front(22050); sampling_rates.push_front(24000); sampling_rates.push_front(32000);
1355 sampling_rates.push_front(44100); sampling_rates.push_front(48000); sampling_rates.push_front(96000);
1360 if(sampling_rates.empty())
1361 throw QString("OSS: cannot set any sample rate (")+strerror(errno)+")";
1363 m_sampling_rate = sampling_rates.front();
1364 cerr << "CaptureThread: INFO: OSS: try to set sampling rate to " << m_sampling_rate << flush;
1365 err = ioctl(m_fd_in, SNDCTL_DSP_SPEED, &m_sampling_rate);
1367 if(err==-1) cerr << " failed" << endl;
1368 else cerr << " success" << endl;
1370 sampling_rates.pop_front();
1373 if(old_sampling_rate!=m_sampling_rate)
1374 m_capture_thread->emitSamplingRateChanged();
1378 if(ioctl(m_fd_in, SNDCTL_DSP_SPEED, &m_sampling_rate)==-1)
1379 throw QString("OSS: cannot set sampling rate (")+QString(strerror(errno))+")";
1383 void CaptureThreadImplOSS::setSamplingRate(int value)
1385 // cerr << "CaptureThreadImplOSS::setSamplingRate " << value << endl;
1387 assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
1389 if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
1391 bool was_running = m_capture_thread->isCapturing();
1392 if(was_running) m_capture_thread->stopCapture();
1394 m_sampling_rate = value;
1396 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
1402 catch(QString error)
1404 cerr << "CaptureThread: ERROR: " << error << endl;
1405 m_capture_thread->emitError(error);
1408 // it was just for testing
1412 m_capture_thread->emitSamplingRateChanged();
1414 if(was_running) m_capture_thread->startCapture();
1417 // cerr << "~CaptureThreadImplOSS::setSamplingRate" << endl;
1420 void CaptureThreadImplOSS::capture_init()
1424 m_oss_buffer = new char[m_channel_count*OSS_BUFF_SIZE*16/8];
1426 void CaptureThreadImplOSS::capture_loop()
1428 // cerr << "CaptureThreadImplOSS::capture_loop" << endl;
1430 bool format_signed = true;
1433 m_wait_for_start = false;
1436 int ret_val = read(m_fd_in, m_oss_buffer, sizeof(m_oss_buffer));
1440 cerr << "CaptureThread: WARNING: OSS: " << strerror(errno) << endl;
1441 msleep(1000); // TODO which behavior ?
1442 // m_loop = false;// TODO which behavior ?
1446 ret_val /= m_format_size;
1448 if(!m_capture_thread->m_pause)
1450 m_capture_thread->m_lock.lock();
1452 for(int i=0; i<ret_val*m_channel_count; i++)
1453 addValue(this, decodeValue(m_oss_buffer, i), i);
1455 m_capture_thread->m_packet_size = ret_val;
1456 if(m_capture_thread->m_ext_lock)
1458 m_capture_thread->m_packet_size_sll = 0;
1459 m_capture_thread->m_ext_lock = false;
1461 m_capture_thread->m_packet_size_sll += ret_val;
1463 m_capture_thread->m_lock.unlock();
1468 // cerr << "~CaptureThreadImplOSS::capture_loop" << endl;
1470 void CaptureThreadImplOSS::capture_finished()
1472 if(m_oss_buffer!=NULL)
1474 delete[] m_oss_buffer;
1475 m_oss_buffer = NULL;
1485 void CaptureThreadImplOSS::run()
1487 // cerr << "CaptureThread: INFO: OSS: capture thread entered" << endl;
1489 // while(m_alive) // TODO ?? need to keep oss thread alive to let PortAudio working after ALSA ??
1491 while(m_alive && !m_loop)
1498 // cerr << "CaptureThread: INFO: capture thread running" << endl;
1502 m_capture_thread->m_capturing = true;
1503 m_capture_thread->emitCaptureStarted();
1504 m_capture_thread->emitCaptureToggled(true);
1508 m_capture_thread->m_capturing = false;
1509 m_capture_thread->emitCaptureStoped();
1510 m_capture_thread->emitCaptureToggled(false);
1512 catch(QString error)
1515 cerr << "CaptureThread: ERROR: " << error << endl;
1516 m_capture_thread->emitError(error);
1518 m_wait_for_start = false;
1524 // cerr << "CaptureThread: INFO: capture thread stop running" << endl;
1527 // cerr << "CaptureThread: INFO: OSS: capture thread exited" << endl;
1530 CaptureThreadImplOSS::~CaptureThreadImplOSS()
1532 // cerr << "CaptureThreadImplOSS::~CaptureThreadImplOSS" << endl;
1541 // cerr << "~CaptureThreadImplOSS::~CaptureThreadImplOSS" << endl;