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"
32 // ------------------------------ JACK implementation ----------------------------
35 #define JACK_BUFF_SIZE 1024
37 const size_t g_jack_sample_size = sizeof(jack_default_audio_sample_t);
39 CaptureThreadImplJACK::CaptureThreadImplJACK(CaptureThread* capture_thread)
40 : CaptureThreadImpl(capture_thread, "JACK", "Jack Audio Connection Kit")
51 bool CaptureThreadImplJACK::is_available()
53 if(m_jack_client==NULL)
57 //m_jack_client = jack_client_new((m_capture_thread->m_name+"_test").latin1());
58 m_jack_client = jack_client_open((m_capture_thread->m_name+"_test").toAscii().constData(), JackNoStartServer, NULL);
59 if(m_jack_client==NULL)
60 throw QString("unknown reason");
71 m_status = "available";
76 void CaptureThreadImplJACK::setSamplingRate(int value)
78 cerr << "CaptureThread: ERROR: JACK: setSamplingRate not available with JACK ! change the JACK server sampling rate instead" << endl;
81 void CaptureThreadImplJACK::startCapture()
88 m_wait_for_start = true;
89 while(m_wait_for_start) // some implementations take a long time to start
92 void CaptureThreadImplJACK::stopCapture()
100 void CaptureThreadImplJACK::JackShutdown(void* arg){((CaptureThreadImplJACK*)arg)->jackShutdown();}
101 void CaptureThreadImplJACK::jackShutdown()
103 // cerr << "CaptureThreadImplJACK::jackShutdown" << endl;
105 m_jack_client = NULL;
109 jack_ringbuffer_free(m_ringbuffer);
113 m_capture_thread->emitError("JACK: server shutdown !");
114 // cerr << "~CaptureThreadImplJACK::jackShutdown" << endl;
117 int CaptureThreadImplJACK::JackSampleRate(jack_nframes_t nframes, void* arg){return ((CaptureThreadImplJACK*)arg)->jackSampleRate(nframes);}
118 int CaptureThreadImplJACK::jackSampleRate(jack_nframes_t nframes)
120 if(m_sampling_rate!=int(nframes))
123 jack_ringbuffer_free(m_ringbuffer);
124 m_ringbuffer = jack_ringbuffer_create(g_jack_sample_size*nframes); // one second buffer
126 m_sampling_rate = nframes;
127 m_capture_thread->emitSamplingRateChanged();
133 int CaptureThreadImplJACK::JackProcess(jack_nframes_t nframes, void* arg){return ((CaptureThreadImplJACK*)arg)->jackProcess(nframes);}
134 int CaptureThreadImplJACK::jackProcess(jack_nframes_t nframes)
136 // cerr << "CaptureThreadImplJACK::jackProcess '" << nframes << "'" << endl;
138 if(!m_jack_client || !m_jack_port || !m_ringbuffer) return 0;
139 if(m_capture_thread->m_pause || !m_capture_thread->m_capturing || nframes<=0) return 0;
141 void* pin = jack_port_get_buffer(m_jack_port, nframes);
145 jack_default_audio_sample_t* in = (jack_default_audio_sample_t*)pin;
147 int characters_written = jack_ringbuffer_write(m_ringbuffer, (const char *) ((void *) (in)), g_jack_sample_size*nframes);
148 if (characters_written < g_jack_sample_size*nframes)
149 cerr << "CaptureThreadImplJACK::jackProcess Can not write all frames: ringbuffer full?" << endl;
151 // int toread = jack_ringbuffer_read_space(m_ringbuffer);
152 // cerr << "CaptureThreadImplJACK::jackProcess " << characters_written/g_jack_sample_size << " values written, " << toread/g_jack_sample_size << " to read" << endl;
154 // cerr << "~CaptureThreadImplJACK::jackProcess" << endl;
159 void CaptureThreadImplJACK::capture_init()
161 m_jack_client = jack_client_open(m_capture_thread->m_name.toAscii().constData(), JackNoStartServer, NULL);
163 throw QString("JACK: cannot create client, JACK deamon is running ?");
165 jack_set_process_callback(m_jack_client, JackProcess, (void*)this);
166 jack_on_shutdown(m_jack_client, JackShutdown, (void*)this);
167 jack_set_sample_rate_callback(m_jack_client, JackSampleRate, (void*)this);
169 cerr << "CaptureThread: INFO: JACK: sampling rate=" << jack_get_sample_rate(m_jack_client) << endl;
170 m_ringbuffer = jack_ringbuffer_create(g_jack_sample_size*jack_get_sample_rate(m_jack_client)); // one second buffer
173 if((err=jack_activate(m_jack_client))!=0)
174 throw QString("JACK: cannot activate client");
176 setFormatDescrsAndFns(g_jack_sample_size, true, true, 1);
178 m_jack_port = jack_port_register(m_jack_client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput,0);
182 QString dest = QString(jack_get_client_name(m_jack_client))+":input";
183 cerr << "CaptureThread: INFO: JACK: auto-connect '" << m_source.toStdString() << "' with '" << dest.toStdString() << "'" << endl;
184 if((err=jack_connect(m_jack_client, m_source.toAscii().constData(), dest.toAscii().constData()))!=0)
185 m_capture_thread->emitError(QString("JACK: Invalid source '")+m_source+"'");
188 int old_sampling_rate = m_sampling_rate;
189 m_sampling_rate = jack_get_sample_rate(m_jack_client);
190 if(m_sampling_rate!=old_sampling_rate)
191 m_capture_thread->emitSamplingRateChanged();
193 m_capture_thread->m_capturing = true;
194 m_capture_thread->emitCaptureStarted();
195 m_capture_thread->emitCaptureToggled(true);
197 void CaptureThreadImplJACK::capture_loop()
199 // cerr << "CaptureThreadImplJACK::capture_loop " << g_jack_sample_size << endl;
201 char dest[JACK_BUFF_SIZE*g_jack_sample_size];
203 m_wait_for_start = false;
204 while(m_loop && m_jack_client && m_jack_port && m_ringbuffer)
206 // cerr << "CaptureThreadImplJACK::capture_loop toread=" << toread/g_jack_sample_size << endl;
207 int read = jack_ringbuffer_read(m_ringbuffer, dest, JACK_BUFF_SIZE*g_jack_sample_size);
210 if(!m_capture_thread->m_pause)
212 // cerr << "CaptureThreadImplJACK::capture_loop locking" << endl;
213 m_capture_thread->m_lock.lock();
215 // int toread = jack_ringbuffer_read_space(m_ringbuffer);
216 // cerr << "CaptureThreadImplJACK::capture_loop in deque='" << m_capture_thread->m_values.size() << "' still toread=" << toread/g_jack_sample_size << endl;
218 if(g_jack_sample_size==4)
219 for(int i=0; i<(read/g_jack_sample_size); i++)
220 addValue(this, (double)(((float*)dest)[i]), i);
221 else if(g_jack_sample_size==8)
222 for(int i=0; i<(read/g_jack_sample_size); i++)
223 addValue(this, (double)(((double*)dest)[i]), i);
225 m_capture_thread->m_packet_size = (read/g_jack_sample_size);
226 if(m_capture_thread->m_ext_lock)
228 m_capture_thread->m_packet_size_sll = 0;
229 m_capture_thread->m_ext_lock = false;
231 m_capture_thread->m_packet_size_sll += (read/g_jack_sample_size);
233 m_capture_thread->m_lock.unlock();
234 // cerr << "CaptureThreadImplJACK::capture_loop unlocked" << endl;
241 // cerr << "~CaptureThreadImplJACK::capture_loop" << endl;
243 void CaptureThreadImplJACK::capture_finished()
245 // cerr << "CaptureThreadImplJACK::capture_finished" << endl;
247 if(m_jack_client!=NULL)
249 jack_client_close(m_jack_client);
250 m_jack_client = NULL;
253 jack_ringbuffer_free(m_ringbuffer);
257 m_capture_thread->m_capturing = false;
258 m_capture_thread->emitCaptureStoped();
259 m_capture_thread->emitCaptureToggled(false);
262 void CaptureThreadImplJACK::run()
264 // cerr << "CaptureThread: INFO: JACK: capture thread entered" << endl;
266 // while(m_alive) // TODO need to keep alsa thread alive to let PortAudio working after ALSA !! TODO same for JACK ???
268 while(m_alive && !m_loop)
275 // cerr << "CaptureThread: INFO: JACK: capture thread running" << endl;
279 m_capture_thread->m_capturing = true;
280 m_capture_thread->emitCaptureStarted();
281 m_capture_thread->emitCaptureToggled(true);
285 m_capture_thread->m_capturing = false;
286 m_capture_thread->emitCaptureStoped();
287 m_capture_thread->emitCaptureToggled(false);
292 cerr << "CaptureThread: ERROR: " << error.toStdString() << endl;
293 m_capture_thread->emitError(error);
295 m_wait_for_start = false;
301 // cerr << "CaptureThread: INFO: JACK: capture thread stop running" << endl;
304 // cerr << "CaptureThread: INFO: JACK: capture thread exited" << endl;
306 CaptureThreadImplJACK::~CaptureThreadImplJACK()
308 // cerr << "CaptureThreadImplJACK::~CaptureThreadImplJACK" << endl;
317 // cerr << "~CaptureThreadImplJACK::~CaptureThreadImplJACK" << endl;