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 #ifndef _CaptureThread_h_
21 #define _CaptureThread_h_
32 // ----------------------- the implementations ----------------------
34 class CaptureThreadImpl;
36 void AddValue2ChannelFirst(CaptureThreadImpl* impl, double value, int i);
37 void AddValue2ChannelMix(CaptureThreadImpl* impl, double value, int i);
38 void AddValue1Channel(CaptureThreadImpl* impl, double value, int i);
40 class CaptureThreadImpl
42 friend class CaptureThread;
43 friend void AddValue2ChannelFirst(CaptureThreadImpl* impl, double value, int i);
44 friend void AddValue2ChannelMix(CaptureThreadImpl* impl, double value, int i);
45 friend void AddValue1Channel(CaptureThreadImpl* impl, double value, int i);
48 CaptureThread* m_capture_thread;
61 virtual void setSamplingRate(int rate)=0;
62 virtual void startCapture()=0;
63 virtual void stopCapture()=0;
64 virtual bool is_available()=0;
66 double (*decodeValue)(void* buffer, int i);
67 void (*addValue)(CaptureThreadImpl* impl, double value, int i);
68 void setFormatDescrsAndFns(int format_size, bool format_signed, bool format_float, int channel_count);
71 CaptureThreadImpl(CaptureThread* capture_thread, const QString& name, const QString& descr);
73 const QString& getStatus();
75 const QString& getName() const {return m_name;}
76 const QString& getDescription() const {return m_descr;}
77 const QString& getSource() const {return m_source;}
79 virtual ~CaptureThreadImpl(){}
82 // ---------------------- the ALSA implementation ---------------------
85 #include <alsa/asoundlib.h>
86 class CaptureThreadImplALSA : public CaptureThreadImpl, public QThread
88 snd_pcm_t* m_alsa_capture_handle;
89 snd_pcm_hw_params_t* m_alsa_hw_params;
91 snd_pcm_format_t m_format;
94 volatile bool m_alive;
95 volatile bool m_in_run;
99 volatile bool m_wait_for_start;
101 void set_params(bool test=false);
104 void capture_finished();
109 CaptureThreadImplALSA(CaptureThread* capture_thread);
111 virtual void setSamplingRate(int rate);
112 virtual void startCapture();
113 virtual void stopCapture();
114 virtual bool is_available();
116 ~CaptureThreadImplALSA();
120 // ---------------------- the JACK implementation ---------------------
123 #include <jack/jack.h>
124 class CaptureThreadImplJACK : public CaptureThreadImpl
126 static int JackProcess(jack_nframes_t nframes, void* arg);
127 static void JackShutdown(void* arg);
128 static int JackSampleRate(jack_nframes_t nframes, void* arg);
130 jack_client_t* m_jack_client;
131 jack_port_t* m_jack_port;
132 int jackSampleRate(jack_nframes_t nframes);
133 int jackProcess(jack_nframes_t nframes);
137 void capture_finished();
140 CaptureThreadImplJACK(CaptureThread* capture_thread);
142 virtual void setSamplingRate(int rate);
143 virtual void startCapture();
144 virtual void stopCapture();
145 virtual bool is_available();
149 // ---------------------- the PortAudio implementation ---------------------
151 #ifdef CAPTURE_PORTAUDIO
152 #include <portaudio.h>
153 class CaptureThreadImplPortAudio : public CaptureThreadImpl
155 static int PortAudioCallback( const void *inputBuffer, void *outputBuffer,
156 unsigned long framesPerBuffer,
157 const PaStreamCallbackTimeInfo* timeInfo,
158 PaStreamCallbackFlags statusFlags,
161 int portAudioCallback(const void *inputBuffer,
162 unsigned long framesPerBuffer,
163 const PaStreamCallbackTimeInfo* timeInfo,
164 PaStreamCallbackFlags statusFlags);
169 void set_params(bool test=false);
170 virtual void capture_init();
171 virtual void capture_finished();
174 CaptureThreadImplPortAudio(CaptureThread* capture_thread);
176 virtual void setSamplingRate(int rate);
177 virtual void startCapture();
178 virtual void stopCapture();
179 virtual bool is_available();
181 virtual ~CaptureThreadImplPortAudio();
185 // ---------------------- the OSS implementation ---------------------
188 class CaptureThreadImplOSS : public CaptureThreadImpl, public QThread
195 volatile bool m_alive;
196 volatile bool m_in_run;
199 volatile bool m_loop;
200 volatile bool m_wait_for_start;
202 void set_params(bool test=false);
205 void capture_finished();
210 CaptureThreadImplOSS(CaptureThread* capture_thread);
212 virtual void setSamplingRate(int rate);
213 virtual void startCapture();
214 virtual void stopCapture();
215 virtual bool is_available();
217 ~CaptureThreadImplOSS();
221 // --------------------- the real accessible thread -------------------------
223 class CaptureThread : public QObject
227 friend class CaptureThreadImpl;
229 friend class CaptureThreadImplALSA;
232 friend class CaptureThreadImplJACK;
234 #ifdef CAPTURE_PORTAUDIO
235 friend class CaptureThreadImplPortAudio;
238 friend class CaptureThreadImplOSS;
241 vector<CaptureThreadImpl*> m_impls;
242 CaptureThreadImpl* m_current_impl;
244 void emitError(const QString& error);
245 void emitSamplingRateChanged();
246 void emitCaptureStarted();
247 void emitCaptureStoped();
248 void emitCaptureToggled(bool value);
253 int m_packet_size_sll;
257 volatile bool m_pause;
258 bool m_mix_multiple_channel;
265 deque<double> m_values;
267 enum {SAMPLING_RATE_UNKNOWN=-1, SAMPLING_RATE_MAX=0};
269 CaptureThread(const QString& name="bastard_thread");
271 void lock() {m_lock.lock(); m_ext_lock=true;}
272 void unlock() {m_lock.unlock();}
274 bool isCapturing() const {return m_capturing;}
275 int getSamplingRate() const;
276 int getPacketSize() const {return m_packet_size;}
277 int getPacketSizeSinceLastLock() const {return m_packet_size_sll;}
278 int getNbPendingData() const {return m_values.size();}
279 const CaptureThreadImpl* getCurrentTransport() const;
280 int getCurrentTransportIndex() const;
281 QString getCurrentTransportDescr() const;
282 QString getFormatDescr() const;
283 const vector<CaptureThreadImpl*>& getTransports() const;
284 const CaptureThreadImpl* getTransport(const QString& name) const;
285 void listTransports();
287 virtual ~CaptureThread();
290 void samplingRateChanged(int sampling_rate);
291 void portNameChanged(const QString& name);
292 void sourceChanged(const QString& src);
293 void transportChanged(const QString& name);
294 void captureStarted();
295 void captureStoped();
296 void captureToggled(bool run);
297 void errorRaised(const QString& error);
300 //! auto detect a working transport
301 void autoDetectTransport();
302 //! select a specific transport
303 void selectTransport(const QString& name);
304 //! select a specific transport
305 void selectTransport(int index);
306 //! reset capture (stop/start)
312 //! set capture status
313 void toggleCapture(bool run);
315 /*! keep capture system connected, but throw away all incoming data
317 void togglePause(bool pause);
319 //! set the sampling rate
320 /*! not always available, depending on the implementation
321 * (reset the capture system !)
323 void setSamplingRate(int value);
325 /*! 'hw:0' for example for ALSA, something like alsa_pcm:capture_1 for JACK
326 * (reset the capture system !)
328 void setSource(const QString& src);
330 void setMixMultipleChannels(bool mix);
333 #endif // _CaptureThread_h_