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 m_tmp_value; // used when two channels have to be mixed down
67 double (*decodeValue)(void* buffer, int i); // not used for JACK
68 void (*addValue)(CaptureThreadImpl* impl, double value, int i);
69 void setFormatDescrsAndFns(int format_size, bool format_signed, bool format_float, int channel_count);
72 CaptureThreadImpl(CaptureThread* capture_thread, const QString& name, const QString& descr);
74 const QString& getStatus();
76 const QString& getName() const {return m_name;}
77 const QString& getDescription() const {return m_descr;}
78 const QString& getSource() const {return m_source;}
80 virtual ~CaptureThreadImpl(){}
83 // ---------------------- the ALSA implementation ---------------------
86 #include <alsa/asoundlib.h>
87 class CaptureThreadImplALSA : public CaptureThreadImpl, public QThread
89 snd_pcm_t* m_alsa_capture_handle;
90 snd_pcm_hw_params_t* m_alsa_hw_params;
92 snd_pcm_format_t m_format;
95 volatile bool m_alive;
96 volatile bool m_in_run;
100 volatile bool m_wait_for_start;
102 void set_params(bool test=false);
105 void capture_finished();
110 CaptureThreadImplALSA(CaptureThread* capture_thread);
112 virtual void setSamplingRate(int rate);
113 virtual void startCapture();
114 virtual void stopCapture();
115 virtual bool is_available();
117 ~CaptureThreadImplALSA();
121 // ---------------------- the JACK implementation ---------------------
124 #include <jack/jack.h>
125 #include <jack/ringbuffer.h>
126 class CaptureThreadImplJACK : public CaptureThreadImpl, public QThread
128 static int JackProcess(jack_nframes_t nframes, void* arg);
129 static void JackShutdown(void* arg);
130 static int JackSampleRate(jack_nframes_t nframes, void* arg);
132 jack_ringbuffer_t* m_ringbuffer;
133 jack_client_t* m_jack_client;
134 jack_port_t* m_jack_port;
135 int jackSampleRate(jack_nframes_t nframes);
136 int jackProcess(jack_nframes_t nframes);
140 volatile bool m_alive;
141 volatile bool m_in_run;
144 volatile bool m_loop;
145 volatile bool m_wait_for_start;
149 void capture_finished();
154 CaptureThreadImplJACK(CaptureThread* capture_thread);
156 virtual void setSamplingRate(int rate);
157 virtual void startCapture();
158 virtual void stopCapture();
159 virtual bool is_available();
161 ~CaptureThreadImplJACK();
165 // ---------------------- the PortAudio implementation ---------------------
167 #ifdef CAPTURE_PORTAUDIO
168 #include <portaudio.h>
169 class CaptureThreadImplPortAudio : public CaptureThreadImpl
171 static int PortAudioCallback( const void *inputBuffer, void *outputBuffer,
172 unsigned long framesPerBuffer,
173 const PaStreamCallbackTimeInfo* timeInfo,
174 PaStreamCallbackFlags statusFlags,
177 int portAudioCallback(const void *inputBuffer,
178 unsigned long framesPerBuffer,
179 const PaStreamCallbackTimeInfo* timeInfo,
180 PaStreamCallbackFlags statusFlags);
185 void set_params(bool test=false);
186 virtual void capture_init();
187 virtual void capture_finished();
190 CaptureThreadImplPortAudio(CaptureThread* capture_thread);
192 virtual void setSamplingRate(int rate);
193 virtual void startCapture();
194 virtual void stopCapture();
195 virtual bool is_available();
197 virtual ~CaptureThreadImplPortAudio();
201 // ---------------------- the OSS implementation ---------------------
204 class CaptureThreadImplOSS : public CaptureThreadImpl, public QThread
211 volatile bool m_alive;
212 volatile bool m_in_run;
215 volatile bool m_loop;
216 volatile bool m_wait_for_start;
218 void set_params(bool test=false);
221 void capture_finished();
226 CaptureThreadImplOSS(CaptureThread* capture_thread);
228 virtual void setSamplingRate(int rate);
229 virtual void startCapture();
230 virtual void stopCapture();
231 virtual bool is_available();
233 ~CaptureThreadImplOSS();
237 // --------------------- the real accessible thread -------------------------
239 class CaptureThread : public QObject
243 friend class CaptureThreadImpl;
245 friend class CaptureThreadImplALSA;
248 friend class CaptureThreadImplJACK;
250 #ifdef CAPTURE_PORTAUDIO
251 friend class CaptureThreadImplPortAudio;
254 friend class CaptureThreadImplOSS;
257 vector<CaptureThreadImpl*> m_impls;
258 CaptureThreadImpl* m_current_impl;
260 void emitError(const QString& error);
261 void emitSamplingRateChanged();
262 void emitCaptureStarted();
263 void emitCaptureStoped();
264 void emitCaptureToggled(bool value);
269 int m_packet_size_sll;
273 volatile bool m_pause;
274 bool m_mix_multiple_channel;
281 deque<double> m_values;
283 enum {SAMPLING_RATE_UNKNOWN=-1, SAMPLING_RATE_MAX=0};
285 CaptureThread(const QString& name="bastard_thread");
287 void lock() {m_lock.lock(); m_ext_lock=true;}
288 void unlock() {m_lock.unlock();}
290 bool isCapturing() const {return m_capturing;}
291 int getSamplingRate() const;
292 int getPacketSize() const {return m_packet_size;}
293 int getPacketSizeSinceLastLock() const {return m_packet_size_sll;}
294 int getNbPendingData() const {return m_values.size();}
295 const CaptureThreadImpl* getCurrentTransport() const;
296 int getCurrentTransportIndex() const;
297 QString getCurrentTransportDescr() const;
298 QString getFormatDescr() const;
299 const vector<CaptureThreadImpl*>& getTransports() const;
300 const CaptureThreadImpl* getTransport(const QString& name) const;
301 void listTransports();
303 virtual ~CaptureThread();
306 void samplingRateChanged(int sampling_rate);
307 void portNameChanged(const QString& name);
308 void sourceChanged(const QString& src);
309 void transportChanged(const QString& name);
310 void captureStarted();
311 void captureStoped();
312 void captureToggled(bool run);
313 void errorRaised(const QString& error);
316 //! auto detect a working transport
317 void autoDetectTransport();
318 //! select a specific transport
319 void selectTransport(const QString& name);
320 //! select a specific transport
321 void selectTransport(int index);
322 //! reset capture (stop/start)
328 //! set capture status
329 void toggleCapture(bool run);
331 /*! keep capture system connected, but throw away all incoming data
333 void togglePause(bool pause);
335 //! set the sampling rate
336 /*! not always available, depending on the implementation
337 * (reset the capture system !)
339 void setSamplingRate(int value);
341 /*! 'hw:0' for example for ALSA, something like alsa_pcm:capture_1 for JACK
342 * (reset the capture system !)
344 void setSource(const QString& src);
346 void setMixMultipleChannels(bool mix);
349 #endif // _CaptureThread_h_