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 // ------------------------------ OSS implementation ----------------------------
39 #include <sys/ioctl.h>
40 #include <sys/soundcard.h>
42 #define OSS_BUFF_SIZE 1024
44 CaptureThreadImplOSS::CaptureThreadImplOSS(CaptureThread* capture_thread)
45 : CaptureThreadImpl(capture_thread, "OSS", QString("Open Sound System"))
51 m_source = "/dev/dsp";
53 // oss_sysinfo si; // definition ??
54 // ioctl(m_fd_in, OSS_SYSINFO, &si);
55 // m_fd_in = open(m_source, O_RDONLY, 0));
56 // m_descr = QString("Open Sound System (")+QString::number(SOUND_VERSION, 16)+":"+si.version+")");
59 m_descr = QString("Open Sound System (lib:")+QString::number(SOUND_VERSION, 16)+")";
66 bool CaptureThreadImplOSS::is_available()
72 if((m_fd_in = open (m_source.toAscii().constData(), O_RDONLY, 0)) == -1)
73 throw QString(strerror(errno));
79 m_status = "N/A ("+error+")";
89 // cerr << "CaptureThread: INFO: OSS seems available" << endl;
94 void CaptureThreadImplOSS::startCapture()
101 m_wait_for_start = true;
102 while(m_wait_for_start) // some implementations take a long time to start
105 void CaptureThreadImplOSS::stopCapture()
113 void CaptureThreadImplOSS::set_params(bool test)
116 throw QString("OSS: set the source first");
117 if((m_fd_in = open (m_source.toAscii().constData(), O_RDONLY, 0))==-1)
118 throw QString("OSS: ")+QString(strerror(errno));
125 m_format = AFMT_S16_NE; /* Native 16 bits */
126 if(ioctl(m_fd_in, SNDCTL_DSP_SETFMT, &m_format)==-1)
127 throw QString("OSS: cannot set format (%1)").arg(strerror(errno));
129 if(m_format != AFMT_S16_NE)
130 throw QString("OSS: cannot set format to signed 16bits");
134 if(ioctl(m_fd_in, SNDCTL_DSP_SETFMT, &m_format)==-1)
135 throw QString("OSS: cannot set format (%1)").arg(strerror(errno));
139 m_format_signed = true;
140 m_format_float = false;
143 unsigned int channel_count = 1;
144 if(ioctl(m_fd_in, SNDCTL_DSP_CHANNELS, &channel_count)==-1)
145 throw QString("OSS: cannot set channel count to 1 (%1)").arg(strerror(errno));
147 if(channel_count != 1)
148 throw QString("OSS: the device doesn't support mono mode");
150 /* if(m_channel_count>1) // TODO
152 QString err_msg = QString("OSS: cannot set channel count to one (")+QString::number(m_channel_count)+" instead)";
153 cerr << "CaptureThread: WARNING: " << err_msg << endl;
156 setFormatDescrsAndFns(2, true, false, channel_count);
159 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX || m_sampling_rate==CaptureThread::SAMPLING_RATE_UNKNOWN)
161 int old_sampling_rate = m_sampling_rate;
163 cerr << "CaptureThread: INFO: OSS: sampling rate set to max or undefined, try to determinate it." << endl;
165 list<int> sampling_rates;
166 sampling_rates.push_front(8000); sampling_rates.push_front(11025); sampling_rates.push_front(16000);
167 sampling_rates.push_front(22050); sampling_rates.push_front(24000); sampling_rates.push_front(32000);
168 sampling_rates.push_front(44100);
173 if(sampling_rates.empty())
174 throw QString("OSS: cannot set any sample rate (%1)").arg(strerror(errno));
176 m_sampling_rate = sampling_rates.front();
177 cerr << "CaptureThread: INFO: OSS: try sampling rate " << m_sampling_rate << " ..." << flush;
178 err = ioctl(m_fd_in, SNDCTL_DSP_SPEED, &m_sampling_rate);
180 if(err==-1) cerr << " failed" << endl;
181 else cerr << " success" << endl;
183 sampling_rates.pop_front();
186 if(old_sampling_rate!=m_sampling_rate)
187 m_capture_thread->emitSamplingRateChanged();
191 if(ioctl(m_fd_in, SNDCTL_DSP_SPEED, &m_sampling_rate)==-1)
192 throw QString("OSS: cannot set sampling rate (")+QString(strerror(errno))+")";
196 void CaptureThreadImplOSS::setSamplingRate(int value)
198 // cerr << "CaptureThreadImplOSS::setSamplingRate " << value << endl;
200 assert(value>0 || value==CaptureThread::SAMPLING_RATE_MAX);
202 if(m_sampling_rate!=value || value==CaptureThread::SAMPLING_RATE_MAX)
204 bool was_running = m_capture_thread->isCapturing();
205 if(was_running) m_capture_thread->stopCapture();
207 m_sampling_rate = value;
209 if(m_sampling_rate==CaptureThread::SAMPLING_RATE_MAX)
217 cerr << "CaptureThread: ERROR: " << error.toStdString() << endl;
218 m_capture_thread->emitError(error);
221 // it was just for testing
225 m_capture_thread->emitSamplingRateChanged();
227 if(was_running) m_capture_thread->startCapture();
230 // cerr << "~CaptureThreadImplOSS::setSamplingRate" << endl;
233 void CaptureThreadImplOSS::capture_init()
237 m_oss_buffer = new char[m_channel_count*OSS_BUFF_SIZE*16/8];
239 void CaptureThreadImplOSS::capture_loop()
241 // cerr << "CaptureThreadImplOSS::capture_loop" << endl;
243 bool format_signed = true;
246 m_wait_for_start = false;
249 int ret_val = read(m_fd_in, m_oss_buffer, sizeof(m_oss_buffer));
253 cerr << "CaptureThread: WARNING: OSS: " << strerror(errno) << endl;
254 msleep(1000); // TODO which behavior ?
255 // m_loop = false;// TODO which behavior ?
259 ret_val /= m_format_size;
261 if(!m_capture_thread->m_pause)
263 m_capture_thread->m_lock.lock();
265 for(int i=0; i<ret_val*m_channel_count; i++)
266 addValue(this, decodeValue(m_oss_buffer, i), i);
268 m_capture_thread->m_packet_size = ret_val;
269 if(m_capture_thread->m_ext_lock)
271 m_capture_thread->m_packet_size_sll = 0;
272 m_capture_thread->m_ext_lock = false;
274 m_capture_thread->m_packet_size_sll += ret_val;
276 m_capture_thread->m_lock.unlock();
281 // cerr << "~CaptureThreadImplOSS::capture_loop" << endl;
283 void CaptureThreadImplOSS::capture_finished()
285 if(m_oss_buffer!=NULL)
287 delete[] m_oss_buffer;
298 void CaptureThreadImplOSS::run()
300 // cerr << "CaptureThread: INFO: OSS: capture thread entered" << endl;
302 // while(m_alive) // TODO ?? need to keep oss thread alive to let PortAudio working after ALSA ??
304 while(m_alive && !m_loop)
311 // cerr << "CaptureThread: INFO: capture thread running" << endl;
315 m_capture_thread->m_capturing = true;
316 m_capture_thread->emitCaptureStarted();
317 m_capture_thread->emitCaptureToggled(true);
321 m_capture_thread->m_capturing = false;
322 m_capture_thread->emitCaptureStoped();
323 m_capture_thread->emitCaptureToggled(false);
328 cerr << "CaptureThread: ERROR: " << error.toStdString() << endl;
329 m_capture_thread->emitError(error);
331 m_wait_for_start = false;
337 // cerr << "CaptureThread: INFO: capture thread stop running" << endl;
340 // cerr << "CaptureThread: INFO: OSS: capture thread exited" << endl;
343 CaptureThreadImplOSS::~CaptureThreadImplOSS()
345 // cerr << "CaptureThreadImplOSS::~CaptureThreadImplOSS" << endl;
354 // cerr << "~CaptureThreadImplOSS::~CaptureThreadImplOSS" << endl;