Import fmit upstream version 0.97.6
[fmit.git] / src / CaptureThread.cpp
1 // Copyright 2004 "Gilles Degottex"
2
3 // This file is part of "Music"
4
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.
9 //
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.
14 //
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
18
19
20 #include "CaptureThread.h"
21
22 #include <cassert>
23 #include <time.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <iostream>
28 #include <fstream>
29 #include <vector>
30 using namespace std;
31 #include <qdatetime.h>
32
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)
38 {
39         if(i%2==0)
40                 impl->m_capture_thread->m_values.push_front(value);
41 }
42 void AddValue2ChannelMix(CaptureThreadImpl* impl, double value, int i)
43 {
44         if(i%2==0)
45                 impl->m_capture_thread->m_values.push_front(value);
46         else
47                 impl->m_capture_thread->m_values[0] = (impl->m_capture_thread->m_values[0]+value)/2.0;
48 }
49 void AddValue1Channel(CaptureThreadImpl* impl, double value, int i)
50 {
51         impl->m_capture_thread->m_values.push_front(value);
52 }
53
54 CaptureThread::CaptureThread(const QString& name)
55 {
56         m_current_impl = NULL;
57
58         m_capturing = false;
59         m_packet_size = 0;
60         m_ext_lock = false;
61         m_packet_size_sll = 0;
62
63         m_pause = false;
64         m_mix_multiple_channel = false;
65
66         m_name = name;
67
68 #ifdef CAPTURE_JACK
69         m_impls.push_back(new CaptureThreadImplJACK(this));
70 #endif
71 #ifdef CAPTURE_ALSA
72         m_impls.push_back(new CaptureThreadImplALSA(this));
73 #endif
74 #ifdef CAPTURE_OSS
75         m_impls.push_back(new CaptureThreadImplOSS(this));
76 #endif
77 #ifdef CAPTURE_PORTAUDIO
78         m_impls.push_back(new CaptureThreadImplPortAudio(this));
79 #endif
80
81         listTransports();
82 }
83
84 void CaptureThread::autoDetectTransport()
85 {
86         bool was_capturing = isCapturing();
87         if(was_capturing)
88                 stopCapture();
89
90         QString old_name;
91         if(m_current_impl!=NULL)
92                 old_name = m_current_impl->m_name;
93
94         cerr << "CaptureThread: INFO: Auto detecting a working transport ... " << flush;
95
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())
99                         impl = *it;
100
101         if(impl!=NULL)
102         {
103                 m_current_impl = impl;
104
105                 cerr << "using " << m_current_impl->m_name << endl;
106
107                 if(m_current_impl->m_name!=old_name)
108                         emit(transportChanged(m_current_impl->m_name));
109
110                 if(was_capturing)
111                         startCapture();
112         }
113         else
114         {
115                 cerr << "no working transport !" << endl;
116
117                 if(old_name!="")
118                         emit(transportChanged(""));
119         }
120 }
121 void CaptureThread::selectTransport(const QString& name)
122 {
123         cerr << "CaptureThread: INFO: using " << name << " transport" << endl;
124         if(getCurrentTransport() && name==getCurrentTransport()->getName())     return;
125
126         bool was_capturing = isCapturing();
127         if(was_capturing)
128                 stopCapture();
129
130         QString old_name;
131         if(m_current_impl!=NULL)
132                 old_name = m_current_impl->m_name;
133
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)
137                         impl = *it;
138
139         if(impl==NULL)
140         {
141                 cerr << "CaptureThread: ERROR: unknown transport '" << name << "'" << endl;
142                 throw QString("CaptureThread: ERROR: unknown transport '")+name+"'";
143         }
144
145         m_current_impl = impl;
146
147         if(m_current_impl->m_name!=old_name)
148                 emit(transportChanged(m_current_impl->m_name));
149
150         if(was_capturing)
151                 startCapture();
152 }
153 void CaptureThread::selectTransport(int index)
154 {
155         assert(index>=0 && index<m_impls.size());
156
157         if(m_impls[index]==getCurrentTransport())       return;
158         cerr << "CaptureThread: INFO: change transport to " << m_impls[index]->getName() << " transport" << endl;
159
160         bool was_capturing = isCapturing();
161         if(was_capturing)
162                 stopCapture();
163
164         m_current_impl = m_impls[index];
165
166         emit(transportChanged(m_current_impl->m_name));
167
168         if(was_capturing)
169                 startCapture();
170 }
171 const vector<CaptureThreadImpl*>& CaptureThread::getTransports() const
172 {
173         return m_impls;
174 }
175 void CaptureThread::listTransports()
176 {
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;
180 }
181 const CaptureThreadImpl* CaptureThread::getCurrentTransport() const
182 {
183         return m_current_impl;
184 }
185 int CaptureThread::getCurrentTransportIndex() const
186 {
187         for(int i=0; i<m_impls.size(); i++)
188                 if(m_impls[i]==getCurrentTransport())
189                         return i;
190
191         return -1;
192 }
193 QString CaptureThread::getCurrentTransportDescr() const
194 {
195         if(m_current_impl==NULL)
196                 return "";
197
198         return m_current_impl->m_descr;
199 }
200 const CaptureThreadImpl* CaptureThread::getTransport(const QString& name) const
201 {
202         for(vector<CaptureThreadImpl*>::const_iterator it=m_impls.begin(); it!=m_impls.end(); it++)
203                 if((*it)->m_name==name)
204                         return *it;
205
206         return NULL;
207 }
208 QString CaptureThread::getFormatDescr() const
209 {
210         if(m_current_impl==NULL)
211                 return "";
212
213         return ""; // TODO
214 }
215
216 void CaptureThread::emitError(const QString& error)
217 {
218         emit(errorRaised(error));
219 }
220 void CaptureThread::emitSamplingRateChanged()
221 {
222         if(m_current_impl->m_sampling_rate>0)
223                 emit(samplingRateChanged(m_current_impl->m_sampling_rate));
224 }
225 void CaptureThread::emitCaptureStarted()
226 {
227         emit(captureStarted());
228 }
229 void CaptureThread::emitCaptureStoped()
230 {
231         emit(captureStoped());
232 }
233 void CaptureThread::emitCaptureToggled(bool value)
234 {
235         emit(captureToggled(value));
236 }
237
238 void CaptureThread::startCapture()
239 {
240         if(m_current_impl==NULL)        return;
241
242         m_current_impl->startCapture();
243 }
244 void CaptureThread::stopCapture()
245 {
246         //      cerr << "CaptureThread::stopCapture" << endl;
247
248         if(m_current_impl==NULL)        return;
249
250         m_current_impl->stopCapture();
251
252         //      cerr << "/CaptureThread::stopCapture" << endl;
253 }
254
255 void CaptureThread::toggleCapture(bool run)
256 {
257         if(run && !m_capturing) startCapture();
258         if(!run && m_capturing) stopCapture();
259 }
260
261 void CaptureThread::reset()
262 {
263         stopCapture();
264         startCapture();
265 }
266
267 void CaptureThread::togglePause(bool pause)
268 {
269         m_pause = pause;
270 }
271
272 int CaptureThread::getSamplingRate() const
273 {
274         if(m_current_impl==NULL)        return SAMPLING_RATE_UNKNOWN;
275
276         return m_current_impl->m_sampling_rate;
277 }
278 void CaptureThread::setSamplingRate(int rate)
279 {
280         if(m_current_impl!=NULL)
281                 m_current_impl->setSamplingRate(rate);
282 }
283 void CaptureThread::setSource(const QString& name)
284 {
285         if(m_current_impl==NULL)
286         {
287                 cerr << "CaptureThread: setSource: ERROR: select a transport first" << endl;
288                 return;
289         }
290
291         if(name!=m_current_impl->m_source)
292         {
293                 m_current_impl->m_source = name;
294                 if(isCapturing())
295                 {
296                         stopCapture();
297                         startCapture();
298                 }
299
300                 emit(sourceChanged(m_current_impl->m_source));
301         }
302 }
303
304 void CaptureThread::setMixMultipleChannels(bool mix)
305 {
306         m_mix_multiple_channel = mix;
307 }
308
309 CaptureThread::~CaptureThread()
310 {
311         stopCapture();
312
313         for(vector<CaptureThreadImpl*>::iterator it=m_impls.begin(); it!=m_impls.end(); it++)
314                 delete *it;
315 }
316
317 // -------------------------------- implementation ------------------------------
318
319 CaptureThreadImpl::CaptureThreadImpl(CaptureThread* capture_thread, const QString& name, const QString& descr)
320 : m_capture_thread(capture_thread)
321 {
322         m_name = name;
323         m_descr = descr;
324         m_status = "";
325
326         m_sampling_rate = CaptureThread::SAMPLING_RATE_UNKNOWN;
327         m_format_size = 0;
328         m_format_signed = true;
329         m_channel_count = 0;
330         m_source = "";
331 }
332
333 const QString& CaptureThreadImpl::getStatus()
334 {
335         if(m_status=="")
336                 is_available();
337
338         return m_status;
339 }
340
341 void CaptureThreadImpl::setFormatDescrsAndFns(int format_size, bool format_signed, bool format_float, int channel_count)
342 {
343         m_format_size = format_size;
344         m_format_signed = format_signed;
345         m_format_float = format_float;
346         m_channel_count = channel_count;
347
348         if(m_format_size==2) // 16bits
349         {
350                 if(m_format_signed)     decodeValue = DecodeSigned16Bits;
351                 else                            decodeValue = DecodeUnsigned16Bits;
352         }
353         else    // 8bits
354         {
355                 if(m_format_signed)     decodeValue = DecodeSigned8Bits;
356                 else                            decodeValue = DecodeUnsigned8Bits;
357         }
358
359         if(m_channel_count==1)
360                 addValue = AddValue1Channel;
361         else if(m_channel_count==2)
362         {
363                 if(m_capture_thread->m_mix_multiple_channel)
364                         addValue = AddValue2ChannelMix;
365                 else
366                         addValue = AddValue2ChannelFirst;
367         }
368
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;
370 }
371
372 // ------------------------------ ALSA implementation ----------------------------
373 #ifdef CAPTURE_ALSA
374
375 #define ALSA_BUFF_SIZE 1024
376
377 void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt, ...)
378 {
379         cerr << "alsa_error_handler: " << file << ":" << line << " " << function << " err=" << err << endl;
380 }
381
382 CaptureThreadImplALSA::CaptureThreadImplALSA(CaptureThread* capture_thread)
383         : CaptureThreadImpl(capture_thread, "ALSA", QString("Advanced Linux Sound Architecture (lib:")+snd_asoundlib_version()+")")
384 {
385         m_alsa_capture_handle = NULL;
386         m_alsa_hw_params = NULL;
387         m_alsa_buffer = NULL;
388         m_format = SND_PCM_FORMAT_UNKNOWN;
389
390         m_source = "hw:0";
391
392         m_alive = true;
393         m_in_run = false;
394         m_loop = false;
395
396 //      snd_lib_error_set_handler(alsa_error_handler);
397 }
398
399 bool CaptureThreadImplALSA::is_available()
400 {
401         if(m_alsa_capture_handle==NULL)
402         {
403                 try
404                 {
405                         int err = -1;
406                         if((err=snd_pcm_open(&m_alsa_capture_handle, m_source.latin1(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
407                         {
408                                 if(err==-19)    // TODO risks of changes for the error code
409                                         throw QString("invalid source '")+m_source+"'";
410                                 else if(err==-16)
411                                         throw QString("device '")+m_source+"' busy";
412                                 else
413                                         throw QString("cannot open pcm: ")+QString(snd_strerror(err));
414                         }
415                 }
416                 catch(QString error)
417                 {
418                         m_alsa_capture_handle = NULL;
419
420                         m_status = "N/A ("+error+")";
421
422                         return false;
423                 }
424
425                 if(m_alsa_capture_handle!=NULL)
426                 {
427                         snd_pcm_close(m_alsa_capture_handle);
428                         m_alsa_capture_handle = NULL;
429                 }
430         }
431
432         m_status = "OK";
433
434         //      cerr << "CaptureThread: INFO: ALSA seems available" << endl;
435
436         return true;
437 }
438
439 void CaptureThreadImplALSA::startCapture()
440 {
441         if(!running())
442                 start();
443
444         m_loop = true;
445
446         m_wait_for_start = true;
447         while(m_wait_for_start) // some implementations take a long time to start
448                 msleep(10);
449 }
450 void CaptureThreadImplALSA::stopCapture()
451 {
452         m_loop = false;
453
454         while(m_in_run)
455                 msleep(10);
456 }
457
458 void CaptureThreadImplALSA::set_params(bool test)
459 {
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;
464 //      }
465         int err=0;
466
467         if(m_source=="")
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)
470         {
471                 //                                      cerr << "err=" << err << ":" << snd_strerror(err) << endl;
472
473                 if(err==-19)    // TODO risks of changes for the error code
474                         throw QString("ALSA: Invalid Source '")+m_source+"'";
475                 else if(err==-16)
476                         throw QString("ALSA: Device '")+m_source+"' busy";
477                 else
478                         throw QString("ALSA: Cannot open pcm: ")+QString(snd_strerror(err));
479         }
480
481         snd_pcm_hw_params_alloca(&m_alsa_hw_params);
482
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))+")";
485
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))+")";
488
489         if(!test)
490         {
491                 // Formats
492                 if(m_format==-1)
493                 {
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);
497
498                         err = -1;
499                         while(err<0)
500                         {
501                                 if(formats.empty())
502                                         throw QString("ALSA: cannot set any format (")+QString(snd_strerror(err))+")";
503
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);
507
508                                 if(err<0)       cerr << " failed" << endl;
509                                 else            cerr << " success" << endl;
510
511                                 formats.pop_front();
512                         }
513                 }
514                 else
515                 {
516                         if((err=snd_pcm_hw_params_set_format(m_alsa_capture_handle, m_alsa_hw_params, m_format))<0)
517                         {
518                                 QString err_msg = QString("ALSA: cannot set format (")+QString(snd_strerror(err))+")";
519                                 cerr << "CaptureThread: ERROR: " << err_msg << endl;
520                         }
521                 }
522
523                 // Channel count
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)
526                 {
527                         QString err_msg = QString("ALSA: cannot set channel count (")+QString(snd_strerror(err))+")";
528                         cerr << "CaptureThread: WARNING: " << err_msg << endl;
529                 }
530                 if(channel_count>1)
531                 {
532                         QString err_msg = QString("ALSA: cannot set channel count to one (")+QString::number(channel_count)+" instead)";
533                         cerr << "CaptureThread: WARNING: " << err_msg << endl;
534                 }
535
536                 setFormatDescrsAndFns(snd_pcm_format_width(m_format)/8, snd_pcm_format_signed(m_format), false, channel_count);
537         }
538
539         if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
540         {
541                 int old_sampling_rate = m_sampling_rate;
542
543                 cerr << "CaptureThread: INFO: ALSA: sampling rate set to max or undefined, try to determinate it." << endl;
544
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);
549
550                 err = -1;
551                 while(err<0)
552                 {
553                         if(sampling_rates.empty())
554                                 throw QString("ALSA: cannot set any sample rate (")+QString(snd_strerror(err))+")";
555
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);
560
561                         if(err<0)       cerr << " failed" << endl;
562                         else            cerr << " success" << endl;
563
564                         sampling_rates.pop_front();
565                 }
566
567                 if(old_sampling_rate!=m_sampling_rate)
568                         m_capture_thread->emitSamplingRateChanged();
569         }
570         else
571         {
572                 int err;
573                 int dir = 0;
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;
580         }
581
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))+")";
584 }
585
586 void CaptureThreadImplALSA::setSamplingRate(int value)
587 {
588 //      cerr << "CaptureThreadImplALSA::setSamplingRate " << value << endl;
589
590         assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
591
592         if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
593         {
594                 bool was_running = m_capture_thread->isCapturing();
595                 if(was_running) m_capture_thread->stopCapture();
596
597                 m_sampling_rate = value;
598
599                 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
600                 {
601                         try
602                         {
603                                 set_params(true);
604                         }
605                         catch(QString error)
606                         {
607                                 cerr << "CaptureThread: ERROR: " << error << endl;
608                                 m_capture_thread->emitError(error);
609                         }
610
611                         // it was just for testing
612                         capture_finished();
613                 }
614                 else
615                         m_capture_thread->emitSamplingRateChanged();
616
617                 if(was_running) m_capture_thread->startCapture();
618         }
619
620 //      cerr << "~CaptureThreadImplALSA::setSamplingRate" << endl;
621 }
622
623 void CaptureThreadImplALSA::capture_init()
624 {
625         set_params();
626
627         snd_pcm_nonblock(m_alsa_capture_handle, 0);
628
629         m_alsa_buffer = new char[m_channel_count*ALSA_BUFF_SIZE*snd_pcm_format_width(m_format)/8];
630
631         int err=0;
632
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))+")";
635 }
636 void CaptureThreadImplALSA::capture_loop()
637 {
638 //      cerr << "CaptureThreadImplALSA::capture_loop" << endl;
639
640         m_wait_for_start = false;
641         while(m_loop)
642         {
643                 int ret_val = snd_pcm_readi(m_alsa_capture_handle, m_alsa_buffer, ALSA_BUFF_SIZE);
644                 if(ret_val<0)
645                 {
646                         cerr << "CaptureThread: WARNING: ALSA: " << snd_strerror(ret_val) << endl;
647                         while((ret_val = snd_pcm_prepare(m_alsa_capture_handle)) < 0)
648                         {
649                                 msleep(1000);
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))+")";
652                         }
653                 }
654                 else
655                 {
656                         if(!m_capture_thread->m_pause)
657                         {
658                                 m_capture_thread->m_lock.lock();
659
660 //                              cerr << "CaptureThreadImplALSA::capture_loop " << m_capture_thread->m_values.size() << endl;
661
662                                 for(int i=0; i<ret_val*m_channel_count; i++)
663                                         addValue(this, decodeValue(m_alsa_buffer, i), i);
664
665                                 m_capture_thread->m_packet_size = ret_val;
666                                 if(m_capture_thread->m_ext_lock)
667                                 {
668                                         m_capture_thread->m_packet_size_sll = 0;
669                                         m_capture_thread->m_ext_lock = false;
670                                 }
671                                 m_capture_thread->m_packet_size_sll += ret_val;
672
673                                 m_capture_thread->m_lock.unlock();
674                         }
675                 }
676         }
677
678 //      cerr << "~CaptureThreadImplALSA::capture_loop" << endl;
679 }
680 void CaptureThreadImplALSA::capture_finished()
681 {
682         if(m_alsa_buffer!=NULL)
683         {
684                 delete[] m_alsa_buffer;
685                 m_alsa_buffer = NULL;
686         }
687
688         if(m_alsa_capture_handle!=NULL)
689         {
690                 snd_pcm_hw_free(m_alsa_capture_handle);
691                 snd_pcm_close(m_alsa_capture_handle);
692                 m_alsa_capture_handle = NULL;
693         }
694 }
695
696 void CaptureThreadImplALSA::run()
697 {
698 //      cerr << "CaptureThread: INFO: ALSA: capture thread entered" << endl;
699
700 //      while(m_alive)  // TODO need to keep alsa thread alive to let PortAudio working after ALSA !!
701         {
702                 while(m_alive && !m_loop)
703                         msleep(10);
704
705                 m_in_run = true;
706
707                 try
708                 {
709                         //                      cerr << "CaptureThread: INFO: capture thread running" << endl;
710
711                         capture_init();
712
713                         m_capture_thread->m_capturing = true;
714                         m_capture_thread->emitCaptureStarted();
715                         m_capture_thread->emitCaptureToggled(true);
716
717                         capture_loop();
718
719                         m_capture_thread->m_capturing = false;
720                         m_capture_thread->emitCaptureStoped();
721                         m_capture_thread->emitCaptureToggled(false);
722                 }
723                 catch(QString error)
724                 {
725                         m_loop = false;
726                         cerr << "CaptureThread: ERROR: " << error << endl;
727                         m_capture_thread->emitError(error);
728                 }
729                 m_wait_for_start = false;
730
731                 capture_finished();
732
733                 m_in_run = false;
734
735                 //              cerr << "CaptureThread: INFO: capture thread stop running" << endl;
736         }
737
738 //      cerr << "CaptureThread: INFO: ALSA: capture thread exited" << endl;
739 }
740
741 CaptureThreadImplALSA::~CaptureThreadImplALSA()
742 {
743 //      cerr << "CaptureThreadImplALSA::~CaptureThreadImplALSA" << endl;
744
745         m_alive = false;
746
747         stopCapture();
748
749         while(running())
750                 msleep(10);
751
752 //      cerr << "~CaptureThreadImplALSA::~CaptureThreadImplALSA" << endl;
753 }
754
755 #endif
756
757 // ------------------------------ JACK implementation ----------------------------
758 #ifdef CAPTURE_JACK
759 CaptureThreadImplJACK::CaptureThreadImplJACK(CaptureThread* capture_thread)
760 : CaptureThreadImpl(capture_thread, "JACK", "Jack Audio Connection Kit")
761 {
762         m_jack_client = NULL;
763         m_jack_port = NULL;
764 }
765
766 bool CaptureThreadImplJACK::is_available()
767 {
768         if(m_jack_client==NULL)
769         {
770                 try
771                 {
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");
775                 }
776                 catch(QString error)
777                 {
778                         m_jack_client = NULL;
779                         m_status = "N/A";
780                         return false;
781                 }
782                 capture_finished();
783         }
784
785         m_status = "available";
786
787         return true;
788 }
789
790 void CaptureThreadImplJACK::setSamplingRate(int value)
791 {
792         cerr << "CaptureThread: ERROR: JACK: setSamplingRate not available with JACK ! change the JACK server sampling rate instead" << endl;
793 }
794
795 void CaptureThreadImplJACK::startCapture()
796 {
797         try
798         {
799                 capture_init();
800         }
801         catch(QString error)
802         {
803                 capture_finished();
804                 cerr << "CaptureThread: ERROR: " << error << endl;
805                 m_capture_thread->emitError(error);
806         }
807 }
808 void CaptureThreadImplJACK::stopCapture()
809 {
810         try
811         {
812                 capture_finished();
813         }
814         catch(QString error)
815         {
816                 cerr << "CaptureThread: ERROR: " << error << endl;
817                 m_capture_thread->emitError(error);
818         }
819 }
820
821 void CaptureThreadImplJACK::JackShutdown(void* arg){((CaptureThreadImplJACK*)arg)->jackShutdown();}
822 void CaptureThreadImplJACK::jackShutdown()
823 {
824         m_jack_client = NULL;
825
826         m_capture_thread->emitError("JACK: server shutdown !");
827 }
828
829 int CaptureThreadImplJACK::JackSampleRate(jack_nframes_t nframes, void* arg){return ((CaptureThreadImplJACK*)arg)->jackSampleRate(nframes);}
830 int CaptureThreadImplJACK::jackSampleRate(jack_nframes_t nframes)
831 {
832         if(m_sampling_rate!=int(nframes))
833         {
834                 m_sampling_rate = nframes;
835                 m_capture_thread->emitSamplingRateChanged();
836         }
837
838         return 0;
839 }
840
841 int CaptureThreadImplJACK::JackProcess(jack_nframes_t nframes, void* arg){return ((CaptureThreadImplJACK*)arg)->jackProcess(nframes);}
842 int CaptureThreadImplJACK::jackProcess(jack_nframes_t nframes)
843 {
844 //      cerr << "'" << nframes << "'" << endl;
845
846         if(m_capture_thread->m_pause || !m_capture_thread->m_capturing || nframes<=0)   return 0;
847
848         void* pin = jack_port_get_buffer(m_jack_port, nframes);
849
850         if(!pin) return 0;
851
852         jack_default_audio_sample_t* in = (jack_default_audio_sample_t*)pin;
853
854         m_capture_thread->m_lock.lock();
855
856         for(jack_nframes_t i=0; i<nframes; i++)
857                 m_capture_thread->m_values.push_front(in[i]);
858
859         m_capture_thread->m_lock.unlock();
860
861         m_capture_thread->m_packet_size = nframes;
862         if(m_capture_thread->m_ext_lock)
863         {
864                 m_capture_thread->m_packet_size_sll = 0;
865                 m_capture_thread->m_ext_lock = false;
866         }
867         m_capture_thread->m_packet_size_sll += nframes;
868
869         return 0;
870 }
871
872 void CaptureThreadImplJACK::capture_init()
873 {
874         m_jack_client = jack_client_new(m_capture_thread->m_name.latin1());
875         if(!m_jack_client)
876                 throw QString("JACK: cannot create client, JACK deamon is running ?");
877
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);
882
883         int err=0;
884         if((err=jack_activate(m_jack_client))!=0)
885                 throw QString("JACK: cannot activate client");
886
887         setFormatDescrsAndFns(sizeof(jack_default_audio_sample_t), true, true, 1);
888
889         m_jack_port = jack_port_register(m_jack_client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput,0);
890
891         if(m_source!="")
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+"'");
894
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();
899
900         m_capture_thread->m_capturing = true;
901         m_capture_thread->emitCaptureStarted();
902         m_capture_thread->emitCaptureToggled(true);
903 }
904 void CaptureThreadImplJACK::capture_finished()
905 {
906 //      cerr << "CaptureThreadImplJACK::capture_finished" << endl;
907
908         if(m_jack_client!=NULL)
909         {
910                 jack_client_close(m_jack_client);
911                 m_jack_client = NULL;
912
913                 m_capture_thread->m_capturing = false;
914                 m_capture_thread->emitCaptureStoped();
915                 m_capture_thread->emitCaptureToggled(false);
916         }
917 }
918 #endif
919
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())+"])")
924 {
925         m_stream = NULL;
926
927         m_source = "default";
928 }
929
930 bool CaptureThreadImplPortAudio::is_available()
931 {
932         if(!m_stream)
933         {
934                 try
935                 {
936                         m_err = Pa_Initialize();
937                         if(m_err != paNoError)  throw QString("PortAudio: is_available:Pa_Initialize ")+Pa_GetErrorText(m_err);
938
939                         PaError err;
940                         int numDevices;
941
942                         numDevices = Pa_GetDeviceCount();
943                         if(numDevices < 0)
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);
947
948 /*                      const   PaDeviceInfo *deviceInfo;
949
950                         for(int i=0; i<numDevices; i++ )
951                         {
952                                 deviceInfo = Pa_GetDeviceInfo( i );
953                                 cerr << deviceInfo->name << endl;
954                                 cerr << deviceInfo->defaultSampleRate << endl;
955                         }*/
956                 }
957                 catch(QString error)
958                 {
959                         Pa_Terminate();
960                         m_stream = NULL;
961                         m_status = "N/A";
962                         return false;
963                 }
964                 capture_finished();
965         }
966
967         m_status = "OK";
968
969         return true;
970 }
971
972 void CaptureThreadImplPortAudio::setSamplingRate(int value)
973 {
974 //      cerr << "CaptureThreadImplPortAudio::setSamplingRate " << value << endl;
975
976         assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
977
978         if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
979         {
980                 bool was_running = m_capture_thread->isCapturing();
981                 if(was_running) m_capture_thread->stopCapture();
982
983                 m_sampling_rate = value;
984
985                 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
986                 {
987                         try
988                         {
989                                 set_params(true);
990                         }
991                         catch(QString error)
992                         {
993                                 cerr << "CaptureThread: ERROR: " << error << endl;
994                                 m_capture_thread->emitError(error);
995                         }
996
997                         try{
998                                 // it was just for testing
999                                 capture_finished();
1000                         }
1001                         catch(QString error)
1002                         {
1003                                 cerr << "CaptureThread: ERROR: " << error << endl;
1004                                 m_capture_thread->emitError(error);
1005                         }
1006                 }
1007                 else
1008                         m_capture_thread->emitSamplingRateChanged();
1009
1010                 if(was_running) m_capture_thread->startCapture();
1011         }
1012
1013 //      cerr << "~CaptureThreadImplPortAudio::setSamplingRate" << endl;
1014 }
1015
1016 int CaptureThreadImplPortAudio::PortAudioCallback( const void *inputBuffer, void *outputBuffer,
1017                                                                   unsigned long framesPerBuffer,
1018                                                                   const PaStreamCallbackTimeInfo* timeInfo,
1019                                                                   PaStreamCallbackFlags statusFlags,
1020                                                                   void *userData )
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)
1026 {
1027         if(m_capture_thread->m_pause)
1028                 return 0;
1029
1030         m_capture_thread->m_lock.lock();
1031
1032         float *in = (float*)inputBuffer;
1033
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
1037
1038         m_capture_thread->m_packet_size = framesPerBuffer;
1039         if(m_capture_thread->m_ext_lock)
1040         {
1041                 m_capture_thread->m_packet_size_sll = 0;
1042                 m_capture_thread->m_ext_lock = false;
1043         }
1044         m_capture_thread->m_packet_size_sll += framesPerBuffer;
1045
1046         m_capture_thread->m_lock.unlock();
1047
1048         return 0;
1049 }
1050
1051 void CaptureThreadImplPortAudio::set_params(bool test)
1052 {
1053         m_err = Pa_Initialize();
1054         if(m_err != paNoError)  throw QString("PortAudio: set_params:Pa_Initialize ")+Pa_GetErrorText(m_err);
1055
1056         PaStreamParameters params;
1057         params.device = paNoDevice;
1058         params.channelCount = 1;
1059         params.sampleFormat = paFloat32;
1060         params.suggestedLatency = 0;
1061         params.hostApiSpecificStreamInfo = NULL;
1062
1063         if(m_source!="default") // TODO hum hum
1064         {
1065                 int     numDevices = Pa_GetDeviceCount();
1066                 const PaDeviceInfo* deviceInfo;
1067                 int index = -1;
1068                 for(int i=0; params.device==paNoDevice && i<numDevices; i++)
1069                 {
1070                         deviceInfo = Pa_GetDeviceInfo(i);
1071                         if(QString(deviceInfo->name)==m_source)
1072                                 params.device = i;
1073                 }
1074
1075                 if(params.device==paNoDevice)
1076                         cerr << "CaptureThread: INFO: PortAudio: cannot determine selected source \"" << m_source << "\"" << endl;
1077         }
1078
1079         if(!test)
1080         {
1081                 if(params.device==paNoDevice)
1082                         cerr << "CaptureThread: INFO: PortAudio: using default device" << endl;
1083                 else
1084                         cerr << "CaptureThread: INFO: PortAudio: using \"" << m_source << "\"" << endl;
1085
1086                 setFormatDescrsAndFns(4, true, true, 1);
1087         }
1088
1089         if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
1090         {
1091                 int old_sampling_rate = m_sampling_rate;
1092
1093                 cerr << "CaptureThread: INFO: PortAudio: sampling rate set to max or undefined, try to determinate it." << endl;
1094
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);
1099
1100                 m_err = -1;
1101                 while(m_err!=paNoError)
1102                 {
1103                         if(sampling_rates.empty())
1104                                 throw QString("PortAudio: cannot set any sample rate (")+Pa_GetErrorText(m_err)+")";
1105
1106                         m_err = Pa_Initialize();
1107                         if(m_err != paNoError)  throw QString("PortAudio: set_params:Pa_Initialize ")+Pa_GetErrorText(m_err);
1108
1109                         m_sampling_rate = sampling_rates.front();
1110                         cerr << "CaptureThread: INFO: PortAudio: try to set sampling rate to " << m_sampling_rate << flush;
1111
1112 //                      cerr << "nbc1 " << params.channelCount << endl;
1113
1114                         if(params.device==paNoDevice)
1115                                 m_err = Pa_OpenDefaultStream(&m_stream, 1, 0, paFloat32, m_sampling_rate, 0, PortAudioCallback, this);
1116                         else
1117                                 m_err = Pa_OpenStream(&m_stream, &params, NULL, m_sampling_rate, 0, paNoFlag, PortAudioCallback, this);
1118
1119                         if(m_err != paNoError)  cerr << " failed" << endl;
1120                         else                                    cerr << " success" << endl;
1121
1122                         sampling_rates.pop_front();
1123                 }
1124
1125                 if(old_sampling_rate!=m_sampling_rate)
1126                         m_capture_thread->emitSamplingRateChanged();
1127         }
1128         else
1129         {
1130 //              cerr << "nbc2 " << params.channelCount << endl;
1131 //              cerr << "dev2 " << params.device << "/" << paNoDevice << endl;
1132
1133                 if(params.device==paNoDevice)
1134                 {
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);
1138                 }
1139                 else
1140                 {
1141                         m_err = Pa_OpenStream(&m_stream, &params, 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);
1144                 }
1145         }
1146 }
1147
1148 void CaptureThreadImplPortAudio::capture_init()
1149 {
1150         set_params(false);
1151
1152         m_err = Pa_StartStream(m_stream);
1153         if(m_err != paNoError)
1154                 throw QString("PortAudio: capture_init:Pa_StartStream ")+Pa_GetErrorText(m_err);
1155
1156         m_capture_thread->m_capturing = true;
1157         m_capture_thread->emitCaptureStarted();
1158         m_capture_thread->emitCaptureToggled(true);
1159 }
1160 void CaptureThreadImplPortAudio::capture_finished()
1161 {
1162         if(m_stream)
1163         {
1164                 if(!Pa_IsStreamStopped(m_stream))
1165                 {
1166                         m_err = Pa_StopStream(m_stream);
1167                         if(m_err != paNoError)  throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
1168                 }
1169
1170                 if(m_stream)
1171                 {
1172                         m_err = Pa_CloseStream(m_stream);
1173                         if(m_err != paNoError)  throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
1174                 }
1175
1176                 m_stream = NULL;
1177
1178                 m_capture_thread->m_capturing = false;
1179                 m_capture_thread->emitCaptureStoped();
1180                 m_capture_thread->emitCaptureToggled(false);
1181         }
1182
1183         m_err = Pa_Terminate();
1184 //      if(m_err != paNoError)  throw QString("PortAudio: capture_finished: ")+Pa_GetErrorText(m_err);
1185 }
1186 void CaptureThreadImplPortAudio::startCapture()
1187 {
1188         try
1189         {
1190                 capture_init();
1191         }
1192         catch(QString error)
1193         {
1194                 capture_finished();
1195                 cerr << "CaptureThread: ERROR: " << error << endl;
1196                 m_capture_thread->emitError(error);
1197         }
1198 }
1199 void CaptureThreadImplPortAudio::stopCapture()
1200 {
1201         try
1202         {
1203                 capture_finished();
1204         }
1205         catch(QString error)
1206         {
1207                 cerr << "CaptureThread: ERROR: " << error << endl;
1208                 m_capture_thread->emitError(error);
1209         }
1210 }
1211 CaptureThreadImplPortAudio::~CaptureThreadImplPortAudio()
1212 {
1213         stopCapture();
1214 }
1215
1216 #endif
1217
1218 // ------------------------------ OSS implementation ----------------------------
1219 #ifdef CAPTURE_OSS
1220 #include <stdio.h>
1221 #include <stdlib.h>
1222 #include <unistd.h>
1223 #include <fcntl.h>
1224 #include <errno.h>
1225 #include <sys/ioctl.h>
1226 #include <sys/soundcard.h>
1227
1228
1229 #define OSS_BUFF_SIZE 1024
1230
1231 CaptureThreadImplOSS::CaptureThreadImplOSS(CaptureThread* capture_thread)
1232         : CaptureThreadImpl(capture_thread, "OSS", QString("Open Sound System"))
1233 {
1234         m_fd_in = 0;
1235         m_oss_buffer = NULL;
1236         m_format = -1;
1237
1238         m_source = "/dev/dsp";
1239
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+")");
1244 //      close(m_fd_in);
1245 //      m_fd_in = 0;
1246         m_descr = QString("Open Sound System (lib:")+QString::number(SOUND_VERSION, 16)+")";
1247
1248         m_alive = true;
1249         m_in_run = false;
1250         m_loop = false;
1251 }
1252
1253 bool CaptureThreadImplOSS::is_available()
1254 {
1255         if(m_fd_in==0)
1256         {
1257                 try
1258                 {
1259                         if((m_fd_in = open (m_source.latin1(), O_RDONLY, 0)) == -1)
1260                                 throw QString(strerror(errno));
1261                 }
1262                 catch(QString error)
1263                 {
1264                         m_fd_in = 0;
1265
1266                         m_status = "N/A ("+error+")";
1267
1268                         return false;
1269                 }
1270
1271                 capture_finished();
1272         }
1273
1274         m_status = "OK";
1275
1276         //      cerr << "CaptureThread: INFO: OSS seems available" << endl;
1277
1278         return true;
1279 }
1280
1281 void CaptureThreadImplOSS::startCapture()
1282 {
1283         if(!running())
1284                 start();
1285
1286         m_loop = true;
1287
1288         m_wait_for_start = true;
1289         while(m_wait_for_start) // some implementations take a long time to start
1290                 msleep(10);
1291 }
1292 void CaptureThreadImplOSS::stopCapture()
1293 {
1294         m_loop = false;
1295
1296         while(m_in_run)
1297                 msleep(10);
1298 }
1299
1300 void CaptureThreadImplOSS::set_params(bool test)
1301 {
1302         if(m_source=="")
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));
1306
1307         if(!test)
1308         {
1309                 if(m_format==-1)
1310                 {
1311                         // Formats
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)+")";
1315
1316                         if(m_format != AFMT_S16_NE)
1317                                 throw QString("OSS: cannot set format to signed 16bits");
1318                 }
1319                 else
1320                 {
1321                         if(ioctl(m_fd_in, SNDCTL_DSP_SETFMT, &m_format)==-1)
1322                                 throw QString("OSS: cannot set format (")+strerror(errno)+")";
1323                 }
1324
1325                 m_format_size = 2;
1326                 m_format_signed = true;
1327                 m_format_float = false;
1328
1329                 // Channel count
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)+")";
1333
1334                 if(channel_count != 1)
1335                         throw QString("OSS: the device doesn't support mono mode");
1336
1337                 /*              if(m_channel_count>1)   // TODO
1338                 {
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;
1341                 }*/
1342
1343                 setFormatDescrsAndFns(2, true, false, channel_count);
1344         }
1345
1346         if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
1347         {
1348                 int old_sampling_rate = m_sampling_rate;
1349
1350                 cerr << "CaptureThread: INFO: OSS: sampling rate set to max or undefined, try to determinate it." << endl;
1351
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);
1356
1357                 int err = -1;
1358                 while(err<0)
1359                 {
1360                         if(sampling_rates.empty())
1361                                 throw QString("OSS: cannot set any sample rate (")+strerror(errno)+")";
1362
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);
1366
1367                         if(err==-1)     cerr << " failed" << endl;
1368                         else            cerr << " success" << endl;
1369
1370                         sampling_rates.pop_front();
1371                 }
1372
1373                 if(old_sampling_rate!=m_sampling_rate)
1374                         m_capture_thread->emitSamplingRateChanged();
1375         }
1376         else
1377         {
1378                 if(ioctl(m_fd_in, SNDCTL_DSP_SPEED, &m_sampling_rate)==-1)
1379                         throw QString("OSS: cannot set sampling rate (")+QString(strerror(errno))+")";
1380         }
1381 }
1382
1383 void CaptureThreadImplOSS::setSamplingRate(int value)
1384 {
1385 //      cerr << "CaptureThreadImplOSS::setSamplingRate " << value << endl;
1386
1387         assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
1388
1389         if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
1390         {
1391                 bool was_running = m_capture_thread->isCapturing();
1392                 if(was_running) m_capture_thread->stopCapture();
1393
1394                 m_sampling_rate = value;
1395
1396                 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
1397                 {
1398                         try
1399                         {
1400                                 set_params(true);
1401                         }
1402                         catch(QString error)
1403                         {
1404                                 cerr << "CaptureThread: ERROR: " << error << endl;
1405                                 m_capture_thread->emitError(error);
1406                         }
1407
1408                         // it was just for testing
1409                         capture_finished();
1410                 }
1411                 else
1412                         m_capture_thread->emitSamplingRateChanged();
1413
1414                 if(was_running) m_capture_thread->startCapture();
1415         }
1416
1417 //      cerr << "~CaptureThreadImplOSS::setSamplingRate" << endl;
1418 }
1419
1420 void CaptureThreadImplOSS::capture_init()
1421 {
1422         set_params(false);
1423
1424         m_oss_buffer = new char[m_channel_count*OSS_BUFF_SIZE*16/8];
1425 }
1426 void CaptureThreadImplOSS::capture_loop()
1427 {
1428 //      cerr << "CaptureThreadImplOSS::capture_loop" << endl;
1429
1430         bool format_signed = true;
1431         int l=0;
1432
1433         m_wait_for_start = false;
1434         while(m_loop)
1435         {
1436                 int ret_val = read(m_fd_in, m_oss_buffer, sizeof(m_oss_buffer));
1437
1438                 if(ret_val==-1)
1439                 {
1440                         cerr << "CaptureThread: WARNING: OSS: " << strerror(errno) << endl;
1441                         msleep(1000);   // TODO which behavior ?
1442 //                      m_loop = false;// TODO which behavior ?
1443                 }
1444                 else
1445                 {
1446                         ret_val /= m_format_size;
1447
1448                         if(!m_capture_thread->m_pause)
1449                         {
1450                                 m_capture_thread->m_lock.lock();
1451
1452                                 for(int i=0; i<ret_val*m_channel_count; i++)
1453                                         addValue(this, decodeValue(m_oss_buffer, i), i);
1454
1455                                 m_capture_thread->m_packet_size = ret_val;
1456                                 if(m_capture_thread->m_ext_lock)
1457                                 {
1458                                         m_capture_thread->m_packet_size_sll = 0;
1459                                         m_capture_thread->m_ext_lock = false;
1460                                 }
1461                                 m_capture_thread->m_packet_size_sll += ret_val;
1462
1463                                 m_capture_thread->m_lock.unlock();
1464                         }
1465                 }
1466         }
1467
1468 //      cerr << "~CaptureThreadImplOSS::capture_loop" << endl;
1469 }
1470 void CaptureThreadImplOSS::capture_finished()
1471 {
1472         if(m_oss_buffer!=NULL)
1473         {
1474                 delete[] m_oss_buffer;
1475                 m_oss_buffer = NULL;
1476         }
1477
1478         if(m_fd_in!=0)
1479         {
1480                 close(m_fd_in);
1481                 m_fd_in = 0;
1482         }
1483 }
1484
1485 void CaptureThreadImplOSS::run()
1486 {
1487 //      cerr << "CaptureThread: INFO: OSS: capture thread entered" << endl;
1488
1489 //      while(m_alive)  // TODO ?? need to keep oss thread alive to let PortAudio working after ALSA ??
1490         {
1491                 while(m_alive && !m_loop)
1492                         msleep(10);
1493
1494                 m_in_run = true;
1495
1496                 try
1497                 {
1498                         //                      cerr << "CaptureThread: INFO: capture thread running" << endl;
1499
1500                         capture_init();
1501
1502                         m_capture_thread->m_capturing = true;
1503                         m_capture_thread->emitCaptureStarted();
1504                         m_capture_thread->emitCaptureToggled(true);
1505
1506                         capture_loop();
1507
1508                         m_capture_thread->m_capturing = false;
1509                         m_capture_thread->emitCaptureStoped();
1510                         m_capture_thread->emitCaptureToggled(false);
1511                 }
1512                 catch(QString error)
1513                 {
1514                         m_loop = false;
1515                         cerr << "CaptureThread: ERROR: " << error << endl;
1516                         m_capture_thread->emitError(error);
1517                 }
1518                 m_wait_for_start = false;
1519
1520                 capture_finished();
1521
1522                 m_in_run = false;
1523
1524                 //              cerr << "CaptureThread: INFO: capture thread stop running" << endl;
1525         }
1526
1527 //      cerr << "CaptureThread: INFO: OSS: capture thread exited" << endl;
1528 }
1529
1530 CaptureThreadImplOSS::~CaptureThreadImplOSS()
1531 {
1532 //      cerr << "CaptureThreadImplOSS::~CaptureThreadImplOSS" << endl;
1533
1534         m_alive = false;
1535
1536         stopCapture();
1537
1538         while(running())
1539                 msleep(10);
1540
1541 //      cerr << "~CaptureThreadImplOSS::~CaptureThreadImplOSS" << endl;
1542 }
1543
1544 #endif