kwave  18.07.70
Record-ALSA.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  Record-ALSA.cpp - device for audio recording via ALSA
3  -------------------
4  begin : Sun Jul 24 2005
5  copyright : (C) 2005 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 #ifdef HAVE_ALSA_SUPPORT
20 
21 #include <errno.h>
22 #include <math.h>
23 
24 #include <QtGlobal>
25 
26 #include "libkwave/Compression.h"
27 #include "libkwave/String.h"
28 #include "libkwave/Utils.h"
29 
30 #include "Record-ALSA.h"
31 
33 QMap<QString, QString> Kwave::RecordALSA::m_device_list;
34 
36 #define DEFAULT_DEVICE (i18n("DSNOOP plugin") + _("|sound_note"))
37 
39 #define ELEMENTS_OF(__array__) (sizeof(__array__) / sizeof(__array__[0]))
40 
41 //***************************************************************************
42 
43 /* define some endian dependent symbols that are missing in ALSA */
44 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
45 // big endian
46 #define SND_PCM_FORMAT_S18_3 SND_PCM_FORMAT_S18_3BE
47 #define SND_PCM_FORMAT_U18_3 SND_PCM_FORMAT_U18_3BE
48 #define SND_PCM_FORMAT_U20_3 SND_PCM_FORMAT_U20_3BE
49 #define SND_PCM_FORMAT_S20_3 SND_PCM_FORMAT_S20_3BE
50 #define SND_PCM_FORMAT_U24_3 SND_PCM_FORMAT_U24_3BE
51 #define SND_PCM_FORMAT_S24_3 SND_PCM_FORMAT_S24_3BE
52 
53 #else
54 // little endian
55 #define SND_PCM_FORMAT_S18_3 SND_PCM_FORMAT_S18_3LE
56 #define SND_PCM_FORMAT_U18_3 SND_PCM_FORMAT_U18_3LE
57 #define SND_PCM_FORMAT_U20_3 SND_PCM_FORMAT_U20_3LE
58 #define SND_PCM_FORMAT_S20_3 SND_PCM_FORMAT_S20_3LE
59 #define SND_PCM_FORMAT_U24_3 SND_PCM_FORMAT_U24_3LE
60 #define SND_PCM_FORMAT_S24_3 SND_PCM_FORMAT_S24_3LE
61 
62 #endif
63 
77 static const snd_pcm_format_t _known_formats[] =
78 {
79  /* 8 bit */
80  SND_PCM_FORMAT_S8,
81  SND_PCM_FORMAT_U8,
82 
83  /* 16 bit */
84  SND_PCM_FORMAT_S16, SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE,
85  SND_PCM_FORMAT_U16, SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_BE,
86 
87  /* 18 bit / 3 byte */
88  SND_PCM_FORMAT_S18_3, SND_PCM_FORMAT_S18_3LE, SND_PCM_FORMAT_S18_3BE,
89  SND_PCM_FORMAT_U18_3, SND_PCM_FORMAT_U18_3LE, SND_PCM_FORMAT_U18_3BE,
90 
91  /* 20 bit / 3 byte */
92  SND_PCM_FORMAT_S20_3, SND_PCM_FORMAT_S20_3LE, SND_PCM_FORMAT_S20_3BE,
93  SND_PCM_FORMAT_U20_3, SND_PCM_FORMAT_U20_3LE, SND_PCM_FORMAT_U20_3BE,
94 
95  /* 24 bit / 3 byte */
96  SND_PCM_FORMAT_S24_3, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_S24_3BE,
97  SND_PCM_FORMAT_U24_3, SND_PCM_FORMAT_U24_3LE, SND_PCM_FORMAT_U24_3BE,
98 
99  /* 24 bit / 4 byte */
100  SND_PCM_FORMAT_S24, SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE,
101  SND_PCM_FORMAT_U24, SND_PCM_FORMAT_U24_LE, SND_PCM_FORMAT_U24_BE,
102 
103  /* 32 bit */
104  SND_PCM_FORMAT_S32, SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE,
105  SND_PCM_FORMAT_U32, SND_PCM_FORMAT_U32_LE, SND_PCM_FORMAT_U32_BE,
106 
107  /* float, 32 bit */
108  SND_PCM_FORMAT_FLOAT, SND_PCM_FORMAT_FLOAT_LE, SND_PCM_FORMAT_FLOAT_BE,
109 
110  /* float, 64 bit */
111  SND_PCM_FORMAT_FLOAT64,
112  SND_PCM_FORMAT_FLOAT64_LE, SND_PCM_FORMAT_FLOAT64_BE,
113 
114 #if 0
115  /* IEC958 subframes (not supported) */
116  SND_PCM_FORMAT_IEC958_SUBFRAME,
117  SND_PCM_FORMAT_IEC958_SUBFRAME_LE, SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
118 #endif
119 
120  /* G711 ULAW */
121  SND_PCM_FORMAT_MU_LAW,
122 
123  /* G711 ALAW */
124  SND_PCM_FORMAT_A_LAW,
125 
126  /*
127  * some exotic formats, does anyone really use them
128  * for recording ?
129  * -> omit support for them, this makes life easier ;-)
130  */
131 #if 0
132  /* IMA ADPCM, 3 or 4 bytes per sample (not supported) */
133  SND_PCM_FORMAT_IMA_ADPCM,
134 
135  /* MPEG (not supported) */
136  SND_PCM_FORMAT_MPEG,
137 
138  /* GSM */
139  SND_PCM_FORMAT_GSM,
140 
141  /* special (not supported) */
142  SND_PCM_FORMAT_SPECIAL,
143 #endif
144 };
145 
146 //***************************************************************************
148 static Kwave::SampleFormat::Format sample_format_of(snd_pcm_format_t fmt)
149 {
150  if (snd_pcm_format_float(fmt)) {
151  if (snd_pcm_format_width(fmt) == 32)
153  if (snd_pcm_format_width(fmt) == 64)
155  } else if (snd_pcm_format_linear(fmt)) {
156  if (snd_pcm_format_signed(fmt) == 1)
158  else if (snd_pcm_format_unsigned(fmt) == 1)
160  }
161 
163 }
164 
165 //***************************************************************************
167 static Kwave::byte_order_t endian_of(snd_pcm_format_t fmt)
168 {
169  if (snd_pcm_format_little_endian(fmt) == 1)
170  return Kwave::LittleEndian;
171  if (snd_pcm_format_big_endian(fmt) == 1)
172  return Kwave::BigEndian;
173  return Kwave::CpuEndian;
174 }
175 
176 //***************************************************************************
177 static Kwave::Compression::Type compression_of(snd_pcm_format_t fmt)
178 {
180  switch (fmt) {
181  case SND_PCM_FORMAT_MU_LAW:
183  case SND_PCM_FORMAT_A_LAW:
185  case SND_PCM_FORMAT_IMA_ADPCM:
186  c = Kwave::Compression::MS_ADPCM; break;
187  case SND_PCM_FORMAT_MPEG:
189  case SND_PCM_FORMAT_GSM:
190  c = Kwave::Compression::GSM; break;
191  default:
192  break;
193  }
194  return c;
195 }
196 
197 //***************************************************************************
199  :Kwave::RecordDevice(), m_handle(Q_NULLPTR), m_hw_params(Q_NULLPTR),
200  m_sw_params(Q_NULLPTR), m_open_result(0), m_tracks(0),
201  m_rate(0.0), m_compression(Kwave::Compression::NONE),
202  m_bits_per_sample(0), m_bytes_per_sample(0),
203  m_sample_format(Kwave::SampleFormat::Unknown),
204  m_supported_formats(), m_initialized(false), m_buffer_size(0),
205  m_chunk_size(0)
206 {
207  snd_pcm_hw_params_malloc(&m_hw_params);
208  snd_pcm_sw_params_malloc(&m_sw_params);
209  Q_ASSERT(m_hw_params);
210  Q_ASSERT(m_sw_params);
211 }
212 
213 //***************************************************************************
215 {
216  close();
217  snd_pcm_hw_params_free(m_hw_params);
218  snd_pcm_sw_params_free(m_sw_params);
219 }
220 
221 //***************************************************************************
223 {
224  // start with an empty list
225  m_supported_formats.clear();
226 
227  Q_ASSERT(m_handle);
228  if (!m_handle || !m_hw_params) return;
229 
230  if (snd_pcm_hw_params_any(m_handle, m_hw_params) < 0) return;
231 
232  // try all known formats
233 // qDebug("--- list of supported formats --- ");
234  const unsigned int count =
235  sizeof(_known_formats) / sizeof(_known_formats[0]);
236  for (unsigned int i = 0; i < count; i++) {
237  // test the sample format
238  snd_pcm_format_t format = _known_formats[i];
239  int err = snd_pcm_hw_params_test_format(m_handle, m_hw_params, format);
240  if (err < 0) continue;
241 
242  const snd_pcm_format_t *fmt = &(_known_formats[i]);
243 
244  // eliminate duplicate alsa sample formats (e.g. BE/LE)
245  foreach (int it, m_supported_formats) {
246  const snd_pcm_format_t *f = &_known_formats[it];
247  if (*f == *fmt) {
248  fmt = Q_NULLPTR;
249  break;
250  }
251  }
252  if (!fmt) continue;
253 
254 // Kwave::Compression t;
255 // Kwave::SampleFormat::Map sf;
256 // qDebug("#%2u, %2d, %2u bit [%u byte], %s, '%s', '%s'",
257 // i,
258 // *fmt,
259 // snd_pcm_format_width(*fmt),
260 // (snd_pcm_format_physical_width(*fmt)+7) >> 3,
261 // endian_of(*fmt) == Kwave::CpuEndian ? "CPU" :
262 // (endian_of(*fmt) == Kwave::LittleEndian ? "LE " : "BE "),
263 // DBG(sf.description(sf.findFromData(sample_format_of(
264 // DBG(t.description(t.findFromData(compression_of(
265 // *fmt), true))));
266 
267  m_supported_formats.append(i);
268  }
269 // qDebug("--------------------------------- ");
270 
271 }
272 
273 //***************************************************************************
274 QString Kwave::RecordALSA::open(const QString &device)
275 {
276 // qDebug("RecordALSA::open(%s)", DBG(device));
277 
278  // close the previous device
279  if (m_handle) close();
280  m_initialized = false;
281 
282  if (!device.length()) return QString::number(EINVAL); // no device name
283 
284  // translate verbose name to internal ALSA name
285  QString alsa_device = alsaDeviceName(device);
286  qDebug("RecordALSA::open -> '%s'", DBG(alsa_device));
287 
288  if (!alsa_device.length()) return QString::number(EINVAL);
289 
290  // workaround for bug in ALSA
291  // if the device name ends with "," -> invalid name
292  if (alsa_device.endsWith(_(","))) return QString::number(EINVAL);
293 
294  // open the device in case it's not already open
295  m_open_result = snd_pcm_open(&m_handle, alsa_device.toLocal8Bit().data(),
296  SND_PCM_STREAM_CAPTURE,
297  SND_PCM_NONBLOCK);
298  if (m_open_result < 0) {
299  m_handle = Q_NULLPTR;
300  qWarning("RecordALSA::openDevice('%s') - failed, err=%d (%s)",
301  DBG(alsa_device),
302  m_open_result, snd_strerror(m_open_result));
303 
304  QString reason;
305  switch (m_open_result) {
306  case -ENOENT:
307  case -ENODEV:
308  case -ENXIO:
309  case -EIO:
310  reason = QString::number(ENODEV);
311  break;
312  case -EBUSY:
313  reason = QString::number(EBUSY);
314  break;
315  default:
316  reason = QString::fromLocal8Bit(snd_strerror(m_open_result));
317  break;
318  }
319  return reason;
320  }
321 
322  // now we can detect all supported formats
324 
325  return QString();
326 }
327 
328 //***************************************************************************
330 {
331  int err;
332  snd_output_t *output = Q_NULLPTR;
333 
334  snd_pcm_uframes_t buffer_size;
335  unsigned period_time = 0; // period time in us
336  unsigned buffer_time = 0; // ring buffer length in us
337  snd_pcm_uframes_t period_frames = 0;
338  snd_pcm_uframes_t buffer_frames = 0;
339  snd_pcm_uframes_t start_threshold, stop_threshold;
340 
341 // qDebug("RecordALSA::initialize");
342  Q_ASSERT(!m_initialized);
343 
344  m_buffer_size = 0;
345 
346  Q_ASSERT(m_handle);
347  if (!m_handle || !m_hw_params) return -EBADF; // file not opened
348 
349  // close the device if it was previously open
350  snd_pcm_drop(m_handle);
351 
352  err = snd_output_stdio_attach(&output, stderr, 0);
353  if (err < 0) {
354  qWarning("Output failed: %s", snd_strerror(err));
355  }
356 
357  if ((err = snd_pcm_hw_params_any(m_handle, m_hw_params)) < 0) {
358  qWarning("Cannot initialize hardware parameters: %s",
359  snd_strerror(err));
360  snd_output_close(output);
361  return -EIO;
362  }
363 
364  err = snd_pcm_hw_params_set_access(m_handle, m_hw_params,
365  SND_PCM_ACCESS_RW_INTERLEAVED);
366  if (err < 0) {
367  qWarning("Cannot set access type: %s", snd_strerror(err));
368  snd_output_close(output);
369  return -EIO;
370  }
371 
372  int format_index = mode2format(m_compression, m_bits_per_sample,
374  Q_ASSERT(format_index >= 0);
375  if (format_index < 0) {
377 
378  qWarning("RecordkALSA::setFormat(): no matching format for "\
379  "compression '%s', %d bits/sample, format '%s'",
383 
384  snd_output_close(output);
385  return -EINVAL;
386  }
387 
388  Q_ASSERT(format_index >= 0);
389  snd_pcm_format_t alsa_format = _known_formats[format_index];
390  m_bytes_per_sample = ((snd_pcm_format_physical_width(
391  _known_formats[format_index])+7) >> 3) * m_tracks;
392 
393  err = snd_pcm_hw_params_test_format(m_handle, m_hw_params, alsa_format);
394  if (err) {
395  qWarning("RecordkALSA::setFormat(): format %u is not supported",
396  static_cast<int>(alsa_format));
397  snd_output_close(output);
398  return -EINVAL;
399  }
400 
401  // activate the settings
402  err = snd_pcm_hw_params_set_format(m_handle, m_hw_params, alsa_format);
403  if (err < 0) {
404  qWarning("Cannot set sample format: %s", snd_strerror(err));
405  snd_output_close(output);
406  return -EINVAL;
407  }
408 
409  err = snd_pcm_hw_params_set_channels(m_handle, m_hw_params, m_tracks);
410  if (err < 0) {
411  qWarning("Cannot set channel count: %s", snd_strerror(err));
412  snd_output_close(output);
413  return -EINVAL;
414  }
415 
416  unsigned int rrate = (m_rate > 0) ? Kwave::toUint(rint(m_rate)) : 0;
417  err = snd_pcm_hw_params_set_rate_near(m_handle, m_hw_params, &rrate,
418  Q_NULLPTR);
419  if (err < 0) {
420  qWarning("Cannot set sample rate: %s", snd_strerror(err));
421  snd_output_close(output);
422  return -EINVAL;
423  }
424 // qDebug(" real rate = %u", rrate);
425  if (m_rate * 1.05 < rrate || m_rate * 0.95 > rrate) {
426  qWarning("rate is not accurate (requested = %iHz, got = %iHz)",
427  Kwave::toInt(m_rate), Kwave::toInt(rrate));
428  }
429  m_rate = rrate;
430 
431  err = snd_pcm_hw_params_get_buffer_time_max(m_hw_params, &buffer_time,
432  Q_NULLPTR);
433  Q_ASSERT(err >= 0);
434  if (buffer_time > 500000) buffer_time = 500000;
435 
436  if (buffer_time > 0)
437  period_time = buffer_time / 4;
438  else
439  period_frames = buffer_frames / 4;
440 
441  if (period_time > 0) {
442  err = snd_pcm_hw_params_set_period_time_near(m_handle, m_hw_params,
443  &period_time, Q_NULLPTR);
444  } else {
445  err = snd_pcm_hw_params_set_period_size_near(m_handle, m_hw_params,
446  &period_frames, Q_NULLPTR);
447  }
448  Q_ASSERT(err >= 0);
449  if (buffer_time > 0) {
450  err = snd_pcm_hw_params_set_buffer_time_near(m_handle, m_hw_params,
451  &buffer_time, Q_NULLPTR);
452  } else {
453  err = snd_pcm_hw_params_set_buffer_size_near(m_handle, m_hw_params,
454  &buffer_frames);
455  }
456  Q_ASSERT(err >= 0);
457 
458 // qDebug(" setting hw_params");
459  err = snd_pcm_hw_params(m_handle, m_hw_params);
460  if (err < 0) {
461  snd_pcm_dump(m_handle, output);
462  snd_output_close(output);
463  qWarning("Cannot set parameters: %s", snd_strerror(err));
464  return err;
465  }
466 
467  snd_pcm_hw_params_get_period_size(m_hw_params, &m_chunk_size, Q_NULLPTR);
468  snd_pcm_hw_params_get_buffer_size(m_hw_params, &buffer_size);
469  if (m_chunk_size == buffer_size) {
470  qWarning("Can't use period equal to buffer size (%lu == %lu)",
471  m_chunk_size, buffer_size);
472  snd_output_close(output);
473  return -EIO;
474  }
475 
476  /* set software parameters */
477  err = snd_pcm_sw_params_current(m_handle, m_sw_params);
478  if (err < 0) {
479  qWarning("Unable to determine current software parameters: %s",
480  snd_strerror(err));
481  snd_output_close(output);
482  return err;
483  }
484 
485  err = snd_pcm_sw_params_set_avail_min(m_handle, m_sw_params, m_chunk_size);
486 
487  /* round up to closest transfer boundary */
488  start_threshold = qMax<snd_pcm_uframes_t>(1, buffer_size);
489  err = snd_pcm_sw_params_set_start_threshold(m_handle, m_sw_params,
490  start_threshold);
491  Q_ASSERT(err >= 0);
492  stop_threshold = buffer_size;
493 
494  err = snd_pcm_sw_params_set_stop_threshold(m_handle, m_sw_params,
495  stop_threshold);
496  Q_ASSERT(err >= 0);
497 
498  // write the software parameters to the recording device
499  err = snd_pcm_sw_params(m_handle, m_sw_params);
500  if (err < 0) {
501  qDebug(" activating snd_pcm_sw_params FAILED");
502  snd_pcm_dump(m_handle, output);
503  qWarning("Unable to set software parameters: %s", snd_strerror(err));
504  }
505 
506  // prepare the device for recording
507  if ((err = snd_pcm_prepare(m_handle)) < 0) {
508  snd_pcm_dump(m_handle, output);
509  qWarning("cannot prepare interface for use: %s",snd_strerror(err));
510  }
511 
512  if ((err = snd_pcm_start(m_handle)) < 0) {
513  snd_pcm_dump(m_handle, output);
514  qWarning("cannot start interface: %s",snd_strerror(err));
515  }
516 
517  // resize our buffer and reset it
518  Q_ASSERT(m_chunk_size);
519  Q_ASSERT(m_bytes_per_sample);
520 
521 // snd_pcm_dump(m_handle, output);
522  snd_output_close(output);
523 
524  return 0;
525 }
526 
527 //***************************************************************************
528 int Kwave::RecordALSA::read(QByteArray &buffer, unsigned int offset)
529 {
530  unsigned int length = buffer.size();
531 
532  if (!m_handle) return m_open_result; // file not opened / open has failed
533  if (!length) return 0; // no buffer, nothing to do
534 
535  // we configure our device at a late stage, not on the fly like in OSS
536  if (!m_initialized) {
537  int err = initialize();
538  if (err < 0) return err;
539  m_initialized = true;
540  }
541 
542  Q_ASSERT(m_chunk_size);
543  if (!m_chunk_size) return 0;
544 
545  unsigned int chunk_bytes = Kwave::toUint(m_chunk_size) * m_bytes_per_sample;
546  Q_ASSERT(chunk_bytes);
547  if (!chunk_bytes) return 0;
548 
549  // align the buffer size to the chunk size if necessary
550  unsigned int n = (length / chunk_bytes);
551  if (length != (n * chunk_bytes)) {
552  n++;
553  length = n * chunk_bytes;
554 // qDebug("resizing buffer %p from %u to %u bytes",
555 // buffer.data(), buffer.size(), length);
556  buffer.resize(length);
557  }
558 
559  Q_ASSERT(length >= offset);
560  Q_ASSERT(m_rate > 0);
561  unsigned int samples = (length - offset) / m_bytes_per_sample;
562 
563  // do not read more than one chunk at a time
564  if (samples > m_chunk_size)
565  samples = Kwave::toUint(m_chunk_size);
566 
567 #ifdef DEBUG
568  // just for debugging: detect state changes of the device
569  static snd_pcm_state_t last_state = SND_PCM_STATE_DISCONNECTED;
570  snd_pcm_state_t state = snd_pcm_state(m_handle);
571  if (state != last_state) {
572  switch (state) {
573  case SND_PCM_STATE_OPEN:
574  qDebug("SND_PCM_STATE_OPEN");
575  break;
576  case SND_PCM_STATE_SETUP:
577  qDebug("SND_PCM_STATE_SETUP");
578  break;
579  case SND_PCM_STATE_PREPARED:
580  qDebug("ND_PCM_STATE_PREPARED");
581  break;
582  case SND_PCM_STATE_RUNNING:
583  qDebug("SND_PCM_STATE_RUNNING");
584  break;
585  case SND_PCM_STATE_XRUN:
586  qDebug("SND_PCM_STATE_XRUN");
587  break;
588  case SND_PCM_STATE_DRAINING:
589  qDebug("SND_PCM_STATE_DRAINING");
590  break;
591  case SND_PCM_STATE_PAUSED:
592  qDebug("SND_PCM_STATE_PAUSED");
593  break;
594  case SND_PCM_STATE_SUSPENDED:
595  qDebug("SND_PCM_STATE_SUSPENDED");
596  break;
597  case SND_PCM_STATE_DISCONNECTED:
598  qDebug("SND_PCM_STATE_DISCONNECTED");
599  break;
600  }
601  last_state = state;
602  }
603 #endif /* DEBUG */
604 
605  // try to read as much as the device accepts
606  Q_ASSERT(samples);
607  Q_ASSERT(offset + samples <= Kwave::toUint(buffer.size()));
608  int r = Kwave::toInt(
609  snd_pcm_readi(m_handle, buffer.data() + offset, samples)
610  );
611 
612  // handle all negative result codes
613  if (r == -EAGAIN) {
614  unsigned int timeout = (m_rate > 0) ?
615  (((1000 * samples) / 4) / Kwave::toUint(m_rate)) : 10U;
616  snd_pcm_wait(m_handle, timeout);
617  return -EAGAIN;
618  } else if (r == -EPIPE) {
619  // underrun -> start again
620  qWarning("RecordALSA::read(), underrun");
621  r = snd_pcm_prepare(m_handle);
622  if (r >= 0) r = snd_pcm_start(m_handle);
623  if (r < 0) {
624  qWarning("RecordALSA::read(), "
625  "resume after underrun failed: %s",
626  snd_strerror(r));
627  return r;
628  }
629  qWarning("RecordALSA::read(), after underrun: resuming");
630  return -EAGAIN; // try again
631  } else if (r == -ESTRPIPE) {
632  qWarning("RecordALSA::read(), suspended. "\
633  "trying to resume...");
634  while ((r = snd_pcm_resume(m_handle)) == -EAGAIN)
635  return -EAGAIN; /* wait until suspend flag is released */
636  if (r < 0) {
637  qWarning("RecordALSA::read(), resume failed, "
638  "restarting stream.");
639  if ((r = snd_pcm_prepare(m_handle)) < 0) {
640  qWarning("RecordALSA::read(), resume error: %s",
641  snd_strerror(r));
642  return r;
643  }
644  }
645  qWarning("RecordALSA::read(), after suspend: resuming");
646  return -EAGAIN; // try again
647  } else if (r < 0) {
648  qWarning("RecordALSA: read error: %s", snd_strerror(r));
649  return r;
650  }
651 
652  // no error, successfully read something:
653  // advance in the buffer
654 // qDebug("<<< after read, r=%d", r);
655  Q_ASSERT(r <= Kwave::toInt(samples));
656  if (r > Kwave::toInt(samples)) r = samples;
657 
658  return (r * m_bytes_per_sample);
659 }
660 
661 //***************************************************************************
663 {
664  // close the device handle
665 
666  if (m_handle) {
667  snd_pcm_drop(m_handle);
668  snd_pcm_hw_free(m_handle);
669  snd_pcm_close(m_handle);
670  }
671  m_handle = Q_NULLPTR;
672  m_open_result = -EINVAL;
673 
674  // we need to re-initialize the next time
675  m_initialized = false;
676 
677  // clear the list of supported formats, nothing open -> nothing supported
678  m_supported_formats.clear();
679 
680  return 0;
681 }
682 
683 //***************************************************************************
684 int Kwave::RecordALSA::detectTracks(unsigned int &min, unsigned int &max)
685 {
686  min = max = 0;
687 
688  if (!m_handle || !m_hw_params) return -1;
689 
690  if (snd_pcm_hw_params_any(m_handle, m_hw_params) >= 0) {
691  int err;
692  if ((err = snd_pcm_hw_params_get_channels_min(m_hw_params, &min)) < 0)
693  qWarning("RecordALSA::detectTracks: min: %s",
694  snd_strerror(err));
695  if ((err = snd_pcm_hw_params_get_channels_max(m_hw_params, &max)) < 0)
696  qWarning("RecordALSA::detectTracks: max: %s",
697  snd_strerror(err));
698  }
699 
700 // qDebug("RecordALSA::detectTracks, min=%u, max=%u", min, max);
701  return 0;
702 }
703 
704 //***************************************************************************
706 {
707  if (tracks != m_tracks) m_initialized = false;
708  m_tracks = tracks;
709  return 0;
710 }
711 
712 //***************************************************************************
714 {
715  return m_tracks;
716 }
717 
718 //***************************************************************************
720 {
721  QList<double> list;
722 
723  if (!m_handle || !m_hw_params) return list;
724 
725  if (snd_pcm_hw_params_any(m_handle, m_hw_params) < 0) return list;
726 
727  static const unsigned int known_rates[] = {
728  1000, // (just for testing)
729  2000, // (just for testing)
730  4000, // standard OSS
731  5125, // seen in Harmony driver (HP712, 715/new)
732  5510, // seen in AD1848 driver
733  5512, // seen in ES1370 driver
734  6215, // seen in ES188X driver
735  6615, // seen in Harmony driver (HP712, 715/new)
736  6620, // seen in AD1848 driver
737  7350, // seen in AWACS and Burgundy sound driver
738  8000, // standard OSS
739  8820, // seen in AWACS and Burgundy sound driver
740  9600, // seen in AD1848 driver
741  11025, // soundblaster
742  14700, // seen in AWACS and Burgundy sound driver
743  16000, // standard OSS
744  17640, // seen in AWACS and Burgundy sound driver
745  18900, // seen in Harmony driver (HP712, 715/new)
746  22050, // soundblaster
747  24000, // seen in NM256 driver
748  27428, // seen in Harmony driver (HP712, 715/new)
749  29400, // seen in AWACS and Burgundy sound driver
750  32000, // standard OSS
751  32768, // seen in CS4299 driver
752  33075, // seen in Harmony driver (HP712, 715/new)
753  37800, // seen in Harmony driver (HP712, 715/new)
754  44100, // soundblaster
755  48000, // AC97
756  64000, // AC97
757  88200, // seen in RME96XX driver
758  96000, // AC97
759  128000, // (just for testing)
760  192000, // AC97
761  196000, // (just for testing)
762  256000 // (just for testing)
763  };
764 
765  // try all known sample rates
766  for (unsigned int i = 0; i < ELEMENTS_OF(known_rates); i++) {
767  unsigned int rate = known_rates[i];
768 
769  int err = snd_pcm_hw_params_test_rate(m_handle, m_hw_params, rate, 0);
770  if (err < 0) continue;
771 
772  // do not produce duplicates
773  bool is_duplicate = false;
774  foreach (const double &r, list)
775  if (qFuzzyCompare(rate, r)) { is_duplicate = true; break; }
776  if (is_duplicate) continue;
777 
778 // qDebug("found rate %u Hz", rate);
779  list.append(rate);
780  }
781 
782  return list;
783 }
784 
785 //***************************************************************************
786 int Kwave::RecordALSA::setSampleRate(double &new_rate)
787 {
788  if (!qFuzzyCompare(new_rate, m_rate)) m_initialized = false;
789  m_rate = new_rate;
790  return 0;
791 }
792 
793 //***************************************************************************
795 {
796  return m_rate;
797 }
798 
799 //***************************************************************************
801  int bits,
802  Kwave::SampleFormat::Format sample_format)
803 {
804  // loop over all supported formats and keep only those that are
805  // compatible with the given compression, bits and sample format
806  foreach (int index, m_supported_formats)
807  {
808  const snd_pcm_format_t *fmt = &_known_formats[index];
809 
810  if (compression_of(*fmt) != compression) continue;
811  if (snd_pcm_format_width(*fmt) != bits) continue;
812  if (!(sample_format_of(*fmt) == sample_format)) continue;
813 
814  // mode is compatible
815  // As the list of known formats is already sorted so that
816  // the simplest formats come first, we don't have a lot
817  // of work -> just take the first entry ;-)
818 // qDebug("RecordALSA::mode2format -> %d", index);
819  return index;
820  }
821 
822  qWarning("RecordALSA::mode2format -> no match found !?");
823  return -1;
824 }
825 
826 //***************************************************************************
827 QList<Kwave::Compression::Type> Kwave::RecordALSA::detectCompressions()
828 {
829  QList<Kwave::Compression::Type> list;
830 
831  // try all known sample formats
832  foreach(int it, m_supported_formats)
833  {
834  const snd_pcm_format_t *fmt = &(_known_formats[it]);
836 
837  // do not produce duplicates
838  if (list.contains(compression)) continue;
839 
840 // Kwave::Compression t;
841 // qDebug("found compression %d '%s'", compression,
842 // DBG(t.name(t.findFromData(compression))));
843  list.append(compression);
844  }
845 
846  return list;
847 }
848 
849 //***************************************************************************
851 {
852  if (m_compression != new_compression) m_initialized = false;
853  m_compression = new_compression;
854  return 0;
855 }
856 
857 //***************************************************************************
859 {
860  return m_compression;
861 }
862 
863 //***************************************************************************
864 QList<unsigned int> Kwave::RecordALSA::supportedBits()
865 {
866  QList<unsigned int> list;
867 
868  // try all known sample formats
869  foreach(int it, m_supported_formats)
870  {
871  const snd_pcm_format_t *fmt = &(_known_formats[it]);
872  const unsigned int bits = snd_pcm_format_width(*fmt);
873 
874  // 0 bits means invalid/does not apply
875  if (!bits) continue;
876 
877  // only accept bits/sample if compression matches
878  if (compression_of(*fmt) != m_compression) continue;
879 
880  // do not produce duplicates
881  if (list.contains(bits)) continue;
882 
883 // qDebug("found bits/sample %u", bits);
884  list.append(bits);
885  }
886 
887  return list;
888 }
889 
890 //***************************************************************************
891 int Kwave::RecordALSA::setBitsPerSample(unsigned int new_bits)
892 {
893  if (m_bits_per_sample != new_bits) m_initialized = false;
894  m_bits_per_sample = new_bits;
895  return 0;
896 }
897 
898 //***************************************************************************
900 {
901  return m_bits_per_sample;
902 }
903 
904 //***************************************************************************
905 QList<Kwave::SampleFormat::Format> Kwave::RecordALSA::detectSampleFormats()
906 {
907  QList<Kwave::SampleFormat::Format> list;
908 
909  // try all known sample formats
910  foreach(int it, m_supported_formats)
911  {
912  const snd_pcm_format_t *fmt = &(_known_formats[it]);
913  const Kwave::SampleFormat::Format sample_format =
914  sample_format_of(*fmt);
915 
916  // only accept bits/sample if compression types
917  // and bits per sample match
918  if (compression_of(*fmt) != m_compression) continue;
919  if (snd_pcm_format_width(*fmt) != Kwave::toInt(m_bits_per_sample))
920  continue;
921 
922  // do not produce duplicates
923  if (list.contains(sample_format)) continue;
924 
925 // Kwave::SampleFormat::Map sf;
926 // qDebug("found sample format %u ('%s')", (int)sample_format,
927 // DBG(sf.name(sf.findFromData(sample_format))));
928 
929  list.append(sample_format);
930  }
931 
932  return list;
933 }
934 
935 //***************************************************************************
937 {
938  if (m_sample_format != new_format) m_initialized = false;
939  m_sample_format = new_format;
940  return 0;
941 }
942 
943 //***************************************************************************
945 {
946  return m_sample_format;
947 }
948 
949 //***************************************************************************
951 {
953  return (index >= 0) ?
955 }
956 
957 //***************************************************************************
959 {
960  // re-validate the list if necessary
961  scanDevices();
962 
963  QStringList list = m_device_list.keys();
964 
965  // move the default device to the start of the list
966  if (list.contains(DEFAULT_DEVICE))
967  list.move(list.indexOf(DEFAULT_DEVICE), 0);
968 
969  list.append(_("#TREE#"));
970  return list;
971 }
972 
973 //***************************************************************************
975 {
976  snd_ctl_t *handle = Q_NULLPTR;
977  int card, err, dev;
978  int idx;
979  snd_ctl_card_info_t *info = Q_NULLPTR;
980  snd_pcm_info_t *pcminfo = Q_NULLPTR;
981 
982  m_device_list.clear();
983 
984  card = -1;
985  if (snd_card_next(&card) < 0 || card < 0) {
986  qWarning("no soundcards found...");
987  return;
988  }
989 
990  snd_ctl_card_info_malloc(&info);
991  snd_pcm_info_malloc(&pcminfo);
992 
993 // qDebug("**** List of RECORD Hardware Devices ****");
994  while (card >= 0) {
995  QString name;
996  name = _("hw:%1");
997  name = name.arg(card);
998  if ((err = snd_ctl_open(&handle, name.toLocal8Bit().data(), 0)) < 0) {
999  qWarning("control open (%i): %s", card, snd_strerror(err));
1000  goto next_card;
1001  }
1002  if ((err = snd_ctl_card_info(handle, info)) < 0) {
1003  qWarning("control hardware info (%i): %s",
1004  card, snd_strerror(err));
1005  snd_ctl_close(handle);
1006  goto next_card;
1007  }
1008  dev = -1;
1009  while (1) {
1010  unsigned int count;
1011  if (snd_ctl_pcm_next_device(handle, &dev)<0)
1012  qWarning("snd_ctl_pcm_next_device");
1013  if (dev < 0)
1014  break;
1015  snd_pcm_info_set_device(pcminfo, dev);
1016  snd_pcm_info_set_subdevice(pcminfo, 0);
1017  snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
1018  if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
1019  if (err != -ENOENT)
1020  qWarning("control digital audio info (%i): %s", card,
1021  snd_strerror(err));
1022  continue;
1023  }
1024  count = snd_pcm_info_get_subdevices_count(pcminfo);
1025 
1026 // qDebug("card %i: %s [%s], device %i: %s [%s]",
1027 // card,
1028 // snd_ctl_card_info_get_id(info),
1029 // snd_ctl_card_info_get_name(info),
1030 // dev,
1031 // snd_pcm_info_get_id(pcminfo),
1032 // snd_pcm_info_get_name(pcminfo));
1033 
1034  // add the device to the list
1035  QString hw_device;
1036  hw_device = _("hw:%1,%2");
1037  hw_device = hw_device.arg(card).arg(dev);
1038 
1039  QString card_name = _(snd_ctl_card_info_get_name(info));
1040  QString device_name = _(snd_pcm_info_get_name(pcminfo));
1041 
1042 // qDebug(" Subdevices: %i/%i\n",
1043 // snd_pcm_info_get_subdevices_avail(pcminfo), count);
1044  if (count > 1) {
1045  for (idx = 0; idx < Kwave::toInt(count); idx++) {
1046  snd_pcm_info_set_subdevice(pcminfo, idx);
1047  if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
1048  qWarning("ctrl digital audio playback info (%i): %s",
1049  card, snd_strerror(err));
1050  } else {
1051  QString hwdev = hw_device + _(",%1").arg(idx);
1052  QString subdevice_name = _(
1053  snd_pcm_info_get_subdevice_name(pcminfo));
1054  QString full_name =
1055  i18n("Card %1: ", card_name) +
1056  _("|sound_card||") +
1057  i18n("Device %1: ", device_name) +
1058  _("|sound_device||") +
1059  i18n("Subdevice %1: ", subdevice_name) +
1060  _("|sound_subdevice");
1061  qDebug("# '%s' -> '%s'", DBG(hwdev), DBG(full_name));
1062  m_device_list.insert(full_name, hwdev);
1063  }
1064  }
1065  } else {
1066  // no sub-devices
1067  QString full_name = QString(
1068  i18n("Card %1: ", card_name) +
1069  _("|sound_card||") +
1070  i18n("Device %1: ", device_name) +
1071  _("|sound_subdevice")
1072  )/*.arg(card).arg(dev)*/;
1073 // qDebug("# '%s' -> '%s'", hw_device.data(), name.data());
1074  m_device_list.insert(full_name, hw_device);
1075  }
1076  }
1077 
1078  snd_ctl_close(handle);
1079 
1080 next_card:
1081  if (snd_card_next(&card) < 0) {
1082  qWarning("snd_card_next failed");
1083  break;
1084  }
1085  }
1086 
1087  // per default: offer the dsnoop plugin if any slave devices exist
1088  if (!m_device_list.isEmpty()) {
1089  m_device_list.insert(DEFAULT_DEVICE, _("plug:dsnoop"));
1090  }
1091 
1092  snd_ctl_card_info_free(info);
1093  snd_pcm_info_free(pcminfo);
1094 
1095  /*
1096  * BUG: this call is allowed due to ALSA documentation, but causes
1097  * SIGSEGV when closing the record device. Somehow the internal
1098  * structures of the PCM devices get messed up :-(
1099  * (THE, 2009-07-18)
1100  */
1101  /* snd_config_update_free_global(); */
1102 }
1103 
1104 //***************************************************************************
1106 {
1107  if (m_device_list.isEmpty() || (name.length() &&
1108  !m_device_list.contains(name)))
1109  {
1110  scanDevices();
1111  }
1112 
1113  if (!m_device_list.contains(name)) {
1114  // maybe we already have a ALSA compatible name (like in init state)
1115  foreach (QString n, m_device_list.values())
1116  if (n == name) return n;
1117 
1118  qWarning("RecordALSA::alsaDeviceName('%s') - NOT FOUND", DBG(name));
1119  return _("");
1120  }
1121  return m_device_list[name];
1122 }
1123 
1124 #endif /* HAVE_ALSA_SUPPORT */
1125 
1126 //***************************************************************************
1127 //***************************************************************************
unsigned int m_buffer_size
Definition: Record-ALSA.h:274
virtual double sampleRate() Q_DECL_OVERRIDE
#define SND_PCM_FORMAT_S20_3
Definition: Record-ALSA.cpp:49
static const snd_pcm_format_t _known_formats[]
Definition: Record-ALSA.cpp:77
virtual QList< Kwave::SampleFormat::Format > detectSampleFormats() Q_DECL_OVERRIDE
byte_order_t
Definition: ByteOrder.h:25
Definition: App.h:33
virtual int setCompression(Kwave::Compression::Type new_compression) Q_DECL_OVERRIDE
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
Kwave::SampleFormat::Format m_sample_format
Definition: Record-ALSA.h:260
#define SND_PCM_FORMAT_U24_3
Definition: Record-ALSA.cpp:50
virtual int close() Q_DECL_OVERRIDE
virtual Kwave::Compression::Type compression() Q_DECL_OVERRIDE
static Kwave::SampleFormat::Format sample_format_of(snd_pcm_format_t fmt)
static Kwave::Compression::Type compression_of(snd_pcm_format_t fmt)
QString description(IDX type, bool localized) const
Definition: TypesMap.h:128
int mode2format(Kwave::Compression::Type compression, int bits, Kwave::SampleFormat::Format sample_format)
virtual QStringList supportedDevices() Q_DECL_OVERRIDE
virtual QList< double > detectSampleRates() Q_DECL_OVERRIDE
virtual Kwave::SampleFormat::Format sampleFormat() Q_DECL_OVERRIDE
#define SND_PCM_FORMAT_S18_3
Definition: Record-ALSA.cpp:46
snd_pcm_sw_params_t * m_sw_params
Definition: Record-ALSA.h:230
virtual int tracks() Q_DECL_OVERRIDE
Kwave::Compression::Type m_compression
Definition: Record-ALSA.h:248
unsigned int m_bits_per_sample
Definition: Record-ALSA.h:251
unsigned int m_tracks
Definition: Record-ALSA.h:242
virtual int read(QByteArray &buffer, unsigned int offset) Q_DECL_OVERRIDE
void detectSupportedFormats()
virtual QString open(const QString &dev) Q_DECL_OVERRIDE
const char name[16]
Definition: memcpy.c:510
virtual int detectTracks(unsigned int &min, unsigned int &max) Q_DECL_OVERRIDE
virtual ~RecordALSA() Q_DECL_OVERRIDE
int toInt(T x)
Definition: Utils.h:127
unsigned int m_bytes_per_sample
Definition: Record-ALSA.h:257
snd_pcm_hw_params_t * m_hw_params
Definition: Record-ALSA.h:227
virtual Kwave::byte_order_t endianness() Q_DECL_OVERRIDE
#define SND_PCM_FORMAT_S24_3
Definition: Record-ALSA.cpp:51
#define SND_PCM_FORMAT_U18_3
Definition: Record-ALSA.cpp:47
virtual QList< unsigned int > supportedBits() Q_DECL_OVERRIDE
virtual int setSampleRate(double &new_rate) Q_DECL_OVERRIDE
QList< int > m_supported_formats
Definition: Record-ALSA.h:268
#define SND_PCM_FORMAT_U20_3
Definition: Record-ALSA.cpp:48
virtual int setSampleFormat(Kwave::SampleFormat::Format new_format) Q_DECL_OVERRIDE
virtual int bitsPerSample() Q_DECL_OVERRIDE
#define _(m)
Definition: memcpy.c:66
virtual int setTracks(unsigned int &tracks) Q_DECL_OVERRIDE
static QMap< QString, QString > m_device_list
Definition: Record-ALSA.h:239
#define DBG(qs)
Definition: String.h:55
virtual QList< Kwave::Compression::Type > detectCompressions() Q_DECL_OVERRIDE
unsigned int toUint(T x)
Definition: Utils.h:109
virtual int setBitsPerSample(unsigned int new_bits) Q_DECL_OVERRIDE
snd_pcm_uframes_t m_chunk_size
Definition: Record-ALSA.h:277
#define DEFAULT_DEVICE
Definition: Record-ALSA.cpp:36
#define ELEMENTS_OF(__array__)
Definition: Record-ALSA.cpp:39
QString alsaDeviceName(const QString &name)
IDX findFromData(const DATA &data) const
Definition: TypesMap.h:89
static Kwave::byte_order_t endian_of(snd_pcm_format_t fmt)