kwave  18.07.70
Kwave::RecordALSA Class Reference

#include <Record-ALSA.h>

Inheritance diagram for Kwave::RecordALSA:
Inheritance graph
Collaboration diagram for Kwave::RecordALSA:
Collaboration graph

Public Member Functions

 RecordALSA ()
 
virtual ~RecordALSA () Q_DECL_OVERRIDE
 
virtual QString open (const QString &dev) Q_DECL_OVERRIDE
 
virtual int read (QByteArray &buffer, unsigned int offset) Q_DECL_OVERRIDE
 
virtual int close () Q_DECL_OVERRIDE
 
virtual QStringList supportedDevices () Q_DECL_OVERRIDE
 
virtual int detectTracks (unsigned int &min, unsigned int &max) Q_DECL_OVERRIDE
 
virtual int setTracks (unsigned int &tracks) Q_DECL_OVERRIDE
 
virtual int tracks () Q_DECL_OVERRIDE
 
virtual QList< double > detectSampleRates () Q_DECL_OVERRIDE
 
virtual int setSampleRate (double &new_rate) Q_DECL_OVERRIDE
 
virtual double sampleRate () Q_DECL_OVERRIDE
 
virtual QList< Kwave::Compression::TypedetectCompressions () Q_DECL_OVERRIDE
 
virtual int setCompression (Kwave::Compression::Type new_compression) Q_DECL_OVERRIDE
 
virtual Kwave::Compression::Type compression () Q_DECL_OVERRIDE
 
virtual QList< unsigned int > supportedBits () Q_DECL_OVERRIDE
 
virtual int setBitsPerSample (unsigned int new_bits) Q_DECL_OVERRIDE
 
virtual int bitsPerSample () Q_DECL_OVERRIDE
 
virtual QList< Kwave::SampleFormat::FormatdetectSampleFormats () Q_DECL_OVERRIDE
 
virtual int setSampleFormat (Kwave::SampleFormat::Format new_format) Q_DECL_OVERRIDE
 
virtual Kwave::SampleFormat::Format sampleFormat () Q_DECL_OVERRIDE
 
virtual Kwave::byte_order_t endianness () Q_DECL_OVERRIDE
 
- Public Member Functions inherited from Kwave::RecordDevice
 RecordDevice ()
 
virtual ~RecordDevice ()
 
virtual QString fileFilter ()
 

Private Member Functions

void detectSupportedFormats ()
 
int initialize ()
 
int mode2format (Kwave::Compression::Type compression, int bits, Kwave::SampleFormat::Format sample_format)
 
void scanDevices ()
 
QString alsaDeviceName (const QString &name)
 

Private Attributes

snd_pcm_t * m_handle
 
snd_pcm_hw_params_t * m_hw_params
 
snd_pcm_sw_params_t * m_sw_params
 
int m_open_result
 
unsigned int m_tracks
 
double m_rate
 
Kwave::Compression::Type m_compression
 
unsigned int m_bits_per_sample
 
unsigned int m_bytes_per_sample
 
Kwave::SampleFormat::Format m_sample_format
 
QList< int > m_supported_formats
 
bool m_initialized
 
unsigned int m_buffer_size
 
snd_pcm_uframes_t m_chunk_size
 

Static Private Attributes

static QMap< QString, QString > m_device_list
 

Detailed Description

Definition at line 44 of file Record-ALSA.h.

Constructor & Destructor Documentation

◆ RecordALSA()

Kwave::RecordALSA::RecordALSA ( )

Constructor

Definition at line 198 of file Record-ALSA.cpp.

References m_hw_params, and m_sw_params.

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),
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 }
unsigned int m_buffer_size
Definition: Record-ALSA.h:274
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
Kwave::SampleFormat::Format m_sample_format
Definition: Record-ALSA.h:260
snd_pcm_sw_params_t * m_sw_params
Definition: Record-ALSA.h:230
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
unsigned int m_bytes_per_sample
Definition: Record-ALSA.h:257
snd_pcm_hw_params_t * m_hw_params
Definition: Record-ALSA.h:227
QList< int > m_supported_formats
Definition: Record-ALSA.h:268
snd_pcm_uframes_t m_chunk_size
Definition: Record-ALSA.h:277

◆ ~RecordALSA()

Kwave::RecordALSA::~RecordALSA ( )
virtual

Destructor

Definition at line 214 of file Record-ALSA.cpp.

References close(), m_hw_params, and m_sw_params.

215 {
216  close();
217  snd_pcm_hw_params_free(m_hw_params);
218  snd_pcm_sw_params_free(m_sw_params);
219 }
virtual int close() Q_DECL_OVERRIDE
snd_pcm_sw_params_t * m_sw_params
Definition: Record-ALSA.h:230
snd_pcm_hw_params_t * m_hw_params
Definition: Record-ALSA.h:227
Here is the call graph for this function:

Member Function Documentation

◆ alsaDeviceName()

QString Kwave::RecordALSA::alsaDeviceName ( const QString &  name)
private

Translate a verbose device name into a ALSA hardware device name.

Parameters
nameverbose name of the device
Returns
device name that can be used for snd_pcm_open()

Definition at line 1105 of file Record-ALSA.cpp.

References _, DBG, m_device_list, name, and scanDevices().

Referenced by open().

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 }
const char name[16]
Definition: memcpy.c:510
#define _(m)
Definition: memcpy.c:66
static QMap< QString, QString > m_device_list
Definition: Record-ALSA.h:239
#define DBG(qs)
Definition: String.h:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bitsPerSample()

int Kwave::RecordALSA::bitsPerSample ( )
virtual

Returns the current resolution in bits per sample or a negative error code if failed

Implements Kwave::RecordDevice.

Definition at line 899 of file Record-ALSA.cpp.

References m_bits_per_sample.

900 {
901  return m_bits_per_sample;
902 }
unsigned int m_bits_per_sample
Definition: Record-ALSA.h:251

◆ close()

int Kwave::RecordALSA::close ( )
virtual

Close the device

Implements Kwave::RecordDevice.

Definition at line 662 of file Record-ALSA.cpp.

References m_handle, m_initialized, m_open_result, and m_supported_formats.

Referenced by open(), and ~RecordALSA().

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 }
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
QList< int > m_supported_formats
Definition: Record-ALSA.h:268
Here is the caller graph for this function:

◆ compression()

Kwave::Compression::Type Kwave::RecordALSA::compression ( )
virtual

Returns the current compression type (0==none)

Implements Kwave::RecordDevice.

Definition at line 858 of file Record-ALSA.cpp.

References m_compression.

Referenced by detectCompressions().

859 {
860  return m_compression;
861 }
Kwave::Compression::Type m_compression
Definition: Record-ALSA.h:248
Here is the caller graph for this function:

◆ detectCompressions()

QList< Kwave::Compression::Type > Kwave::RecordALSA::detectCompressions ( )
virtual

Gets a list of supported compression types. If no compression is supported, the list might be empty.

Implements Kwave::RecordDevice.

Definition at line 827 of file Record-ALSA.cpp.

References _known_formats, compression(), compression_of(), and m_supported_formats.

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 }
static const snd_pcm_format_t _known_formats[]
Definition: Record-ALSA.cpp:77
virtual Kwave::Compression::Type compression() Q_DECL_OVERRIDE
static Kwave::Compression::Type compression_of(snd_pcm_format_t fmt)
QList< int > m_supported_formats
Definition: Record-ALSA.h:268
Here is the call graph for this function:

◆ detectSampleFormats()

QList< Kwave::SampleFormat::Format > Kwave::RecordALSA::detectSampleFormats ( )
virtual

Gets a list of supported sample formats.

Note
this depends on the current setting of the compression!

Implements Kwave::RecordDevice.

Definition at line 905 of file Record-ALSA.cpp.

References _known_formats, compression_of(), m_bits_per_sample, m_compression, m_supported_formats, sample_format_of(), and Kwave::toInt().

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 }
static const snd_pcm_format_t _known_formats[]
Definition: Record-ALSA.cpp:77
static Kwave::SampleFormat::Format sample_format_of(snd_pcm_format_t fmt)
static Kwave::Compression::Type compression_of(snd_pcm_format_t fmt)
Kwave::Compression::Type m_compression
Definition: Record-ALSA.h:248
unsigned int m_bits_per_sample
Definition: Record-ALSA.h:251
int toInt(T x)
Definition: Utils.h:127
QList< int > m_supported_formats
Definition: Record-ALSA.h:268
Here is the call graph for this function:

◆ detectSampleRates()

QList< double > Kwave::RecordALSA::detectSampleRates ( )
virtual

get a list of supported sample rates

Implements Kwave::RecordDevice.

Definition at line 719 of file Record-ALSA.cpp.

References ELEMENTS_OF, m_handle, and m_hw_params.

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 }
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
snd_pcm_hw_params_t * m_hw_params
Definition: Record-ALSA.h:227
#define ELEMENTS_OF(__array__)
Definition: Record-ALSA.cpp:39

◆ detectSupportedFormats()

void Kwave::RecordALSA::detectSupportedFormats ( )
private

Walk through the list of all known formats and collect the ones that are supported into "m_supported_formats".

Definition at line 222 of file Record-ALSA.cpp.

References _known_formats, m_handle, m_hw_params, and m_supported_formats.

Referenced by open().

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 }
static const snd_pcm_format_t _known_formats[]
Definition: Record-ALSA.cpp:77
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
snd_pcm_hw_params_t * m_hw_params
Definition: Record-ALSA.h:227
QList< int > m_supported_formats
Definition: Record-ALSA.h:268
Here is the caller graph for this function:

◆ detectTracks()

int Kwave::RecordALSA::detectTracks ( unsigned int &  min,
unsigned int &  max 
)
virtual

Detect the minimum and maximum number of tracks. If the detection fails, minimum and maximum are set to zero.

Parameters
minreceives the lowest supported number of tracks
maxreceives the highest supported number of tracks
Returns
zero or positive number if ok, negative error number if failed

Implements Kwave::RecordDevice.

Definition at line 684 of file Record-ALSA.cpp.

References m_handle, and m_hw_params.

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 }
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
snd_pcm_hw_params_t * m_hw_params
Definition: Record-ALSA.h:227

◆ endianness()

Kwave::byte_order_t Kwave::RecordALSA::endianness ( )
virtual

Returns the current endianness (big/little)

Implements Kwave::RecordDevice.

Definition at line 950 of file Record-ALSA.cpp.

References _known_formats, endian_of(), m_bits_per_sample, m_compression, m_sample_format, mode2format(), and Kwave::UnknownEndian.

951 {
953  return (index >= 0) ?
955 }
static const snd_pcm_format_t _known_formats[]
Definition: Record-ALSA.cpp:77
Definition: App.h:33
Kwave::SampleFormat::Format m_sample_format
Definition: Record-ALSA.h:260
int mode2format(Kwave::Compression::Type compression, int bits, Kwave::SampleFormat::Format sample_format)
Kwave::Compression::Type m_compression
Definition: Record-ALSA.h:248
unsigned int m_bits_per_sample
Definition: Record-ALSA.h:251
static Kwave::byte_order_t endian_of(snd_pcm_format_t fmt)
Here is the call graph for this function:

◆ initialize()

int Kwave::RecordALSA::initialize ( )
private

Initialize the ALSA device with current parameters and prepare it for recording.

Returns
zero on success or negative error code -EINVAL or -EIO

Definition at line 329 of file Record-ALSA.cpp.

References _known_formats, DBG, Kwave::TypesMap< IDX, DATA >::description(), Kwave::TypesMap< IDX, DATA >::findFromData(), m_bits_per_sample, m_buffer_size, m_bytes_per_sample, m_chunk_size, m_compression, m_handle, m_hw_params, m_initialized, m_rate, m_sample_format, m_sw_params, m_tracks, mode2format(), name, Kwave::toInt(), and Kwave::toUint().

Referenced by read().

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 }
unsigned int m_buffer_size
Definition: Record-ALSA.h:274
static const snd_pcm_format_t _known_formats[]
Definition: Record-ALSA.cpp:77
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
Kwave::SampleFormat::Format m_sample_format
Definition: Record-ALSA.h:260
QString description(IDX type, bool localized) const
Definition: TypesMap.h:128
int mode2format(Kwave::Compression::Type compression, int bits, Kwave::SampleFormat::Format sample_format)
snd_pcm_sw_params_t * m_sw_params
Definition: Record-ALSA.h:230
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
const char name[16]
Definition: memcpy.c:510
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
#define DBG(qs)
Definition: String.h:55
unsigned int toUint(T x)
Definition: Utils.h:109
snd_pcm_uframes_t m_chunk_size
Definition: Record-ALSA.h:277
IDX findFromData(const DATA &data) const
Definition: TypesMap.h:89
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mode2format()

int Kwave::RecordALSA::mode2format ( Kwave::Compression::Type  compression,
int  bits,
Kwave::SampleFormat::Format  sample_format 
)
private

create a ALSA device format (enum) from parameters.

Parameters
compressionthe compression type
See also
Compression
Parameters
bitsthe number of bits per sample, related to the decoded stream
sample_formatthe sample format, as defined in libaudiofile (signed or unsigned)
Returns
the index of the best matching format within the list of known formats, or -1 if no match was found

Definition at line 800 of file Record-ALSA.cpp.

References _known_formats, compression_of(), m_supported_formats, and sample_format_of().

Referenced by endianness(), and initialize().

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 }
static const snd_pcm_format_t _known_formats[]
Definition: Record-ALSA.cpp:77
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)
QList< int > m_supported_formats
Definition: Record-ALSA.h:268
Here is the call graph for this function:
Here is the caller graph for this function:

◆ open()

QString Kwave::RecordALSA::open ( const QString &  dev)
virtual

Open the record device.

Parameters
devpath of the record device
Return values
QString()if successful
QString::number(ENODEV)if device not found
QString::number(EBUSY)if device is busy
QString::number(EINVAL)on invalid parameters
QString(...)device specific error message (already translated)

Implements Kwave::RecordDevice.

Definition at line 274 of file Record-ALSA.cpp.

References _, alsaDeviceName(), close(), DBG, detectSupportedFormats(), m_handle, m_initialized, and m_open_result.

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 }
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
virtual int close() Q_DECL_OVERRIDE
void detectSupportedFormats()
#define _(m)
Definition: memcpy.c:66
#define DBG(qs)
Definition: String.h:55
QString alsaDeviceName(const QString &name)
Here is the call graph for this function:

◆ read()

int Kwave::RecordALSA::read ( QByteArray &  buffer,
unsigned int  offset 
)
virtual

Read the raw audio data from the record device.

Parameters
bufferarray of bytes to receive the audio data might be resized for alignment
offsetoffset in bytes within the buffer
Returns
number of bytes read, zero or negative if failed

Implements Kwave::RecordDevice.

Definition at line 528 of file Record-ALSA.cpp.

References initialize(), m_bytes_per_sample, m_chunk_size, m_handle, m_initialized, m_open_result, m_rate, Kwave::toInt(), and Kwave::toUint().

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 }
snd_pcm_t * m_handle
Definition: Record-ALSA.h:224
int toInt(T x)
Definition: Utils.h:127
unsigned int m_bytes_per_sample
Definition: Record-ALSA.h:257
unsigned int toUint(T x)
Definition: Utils.h:109
snd_pcm_uframes_t m_chunk_size
Definition: Record-ALSA.h:277
Here is the call graph for this function:

◆ sampleFormat()

Kwave::SampleFormat::Format Kwave::RecordALSA::sampleFormat ( )
virtual

Returns the current sample format (signed/unsigned)

Implements Kwave::RecordDevice.

Definition at line 944 of file Record-ALSA.cpp.

References m_sample_format.

945 {
946  return m_sample_format;
947 }
Kwave::SampleFormat::Format m_sample_format
Definition: Record-ALSA.h:260

◆ sampleRate()

double Kwave::RecordALSA::sampleRate ( )
virtual

Returns the current sample rate of the device

Implements Kwave::RecordDevice.

Definition at line 794 of file Record-ALSA.cpp.

References m_rate.

795 {
796  return m_rate;
797 }

◆ scanDevices()

void Kwave::RecordALSA::scanDevices ( )
private

scan all ALSA devices, re-creates m_device_list

Definition at line 974 of file Record-ALSA.cpp.

References _, DBG, DEFAULT_DEVICE, m_device_list, name, and Kwave::toInt().

Referenced by alsaDeviceName(), and supportedDevices().

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 }
const char name[16]
Definition: memcpy.c:510
int toInt(T x)
Definition: Utils.h:127
#define _(m)
Definition: memcpy.c:66
static QMap< QString, QString > m_device_list
Definition: Record-ALSA.h:239
#define DBG(qs)
Definition: String.h:55
#define DEFAULT_DEVICE
Definition: Record-ALSA.cpp:36
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setBitsPerSample()

int Kwave::RecordALSA::setBitsPerSample ( unsigned int  new_bits)
virtual

Set the resolution in bits per sample

Parameters
new_bitsresolution [bits/sample]

Implements Kwave::RecordDevice.

Definition at line 891 of file Record-ALSA.cpp.

References m_bits_per_sample, and m_initialized.

892 {
893  if (m_bits_per_sample != new_bits) m_initialized = false;
894  m_bits_per_sample = new_bits;
895  return 0;
896 }
unsigned int m_bits_per_sample
Definition: Record-ALSA.h:251

◆ setCompression()

int Kwave::RecordALSA::setCompression ( Kwave::Compression::Type  new_compression)
virtual

Try to set a new compression type.

Parameters
new_compressionthe identifier of the new compression
Returns
zero on success, negative error code if failed
See also
class Compression

Implements Kwave::RecordDevice.

Definition at line 850 of file Record-ALSA.cpp.

References m_compression, and m_initialized.

851 {
852  if (m_compression != new_compression) m_initialized = false;
853  m_compression = new_compression;
854  return 0;
855 }
Kwave::Compression::Type m_compression
Definition: Record-ALSA.h:248

◆ setSampleFormat()

int Kwave::RecordALSA::setSampleFormat ( Kwave::SampleFormat::Format  new_format)
virtual

Try to set a new sample format (signed/unsigned)

Parameters
new_formatthe identifier for the new format
Returns
zero on success, negative error code if failed
See also
class SampleFormat

Implements Kwave::RecordDevice.

Definition at line 936 of file Record-ALSA.cpp.

References m_initialized, and m_sample_format.

937 {
938  if (m_sample_format != new_format) m_initialized = false;
939  m_sample_format = new_format;
940  return 0;
941 }
Kwave::SampleFormat::Format m_sample_format
Definition: Record-ALSA.h:260

◆ setSampleRate()

int Kwave::RecordALSA::setSampleRate ( double &  new_rate)
virtual

Try to set a new sample rate.

Parameters
new_ratethe sample rate to be set [samples/second], can be modified and rounded up/down to the nearest supported sample rate if the underlying driver supports that.
Returns
zero on success, negative error code if failed

Implements Kwave::RecordDevice.

Definition at line 786 of file Record-ALSA.cpp.

References m_initialized, and m_rate.

787 {
788  if (!qFuzzyCompare(new_rate, m_rate)) m_initialized = false;
789  m_rate = new_rate;
790  return 0;
791 }

◆ setTracks()

int Kwave::RecordALSA::setTracks ( unsigned int &  tracks)
virtual

Try to set a new number of tracks.

Note
the device must be open
Parameters
tracksthe number of tracks to be set, can be modified and decreased to the next supported number of tracks if the underlying driver supports that.
Returns
zero on success, negative error code if failed

Implements Kwave::RecordDevice.

Definition at line 705 of file Record-ALSA.cpp.

References m_initialized, m_tracks, and tracks().

706 {
707  if (tracks != m_tracks) m_initialized = false;
708  m_tracks = tracks;
709  return 0;
710 }
virtual int tracks() Q_DECL_OVERRIDE
unsigned int m_tracks
Definition: Record-ALSA.h:242
Here is the call graph for this function:

◆ supportedBits()

QList< unsigned int > Kwave::RecordALSA::supportedBits ( )
virtual

Detect a list of supported bits per sample.

Note
this depends on the compression type
Returns
a list of bits per sample, empty if failed

Implements Kwave::RecordDevice.

Definition at line 864 of file Record-ALSA.cpp.

References _known_formats, compression_of(), m_compression, and m_supported_formats.

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 }
static const snd_pcm_format_t _known_formats[]
Definition: Record-ALSA.cpp:77
static Kwave::Compression::Type compression_of(snd_pcm_format_t fmt)
Kwave::Compression::Type m_compression
Definition: Record-ALSA.h:248
QList< int > m_supported_formats
Definition: Record-ALSA.h:268
Here is the call graph for this function:

◆ supportedDevices()

QStringList Kwave::RecordALSA::supportedDevices ( )
virtual

return a string list with supported device names

Implements Kwave::RecordDevice.

Definition at line 958 of file Record-ALSA.cpp.

References _, DEFAULT_DEVICE, m_device_list, and scanDevices().

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 }
#define _(m)
Definition: memcpy.c:66
static QMap< QString, QString > m_device_list
Definition: Record-ALSA.h:239
#define DEFAULT_DEVICE
Definition: Record-ALSA.cpp:36
Here is the call graph for this function:

◆ tracks()

int Kwave::RecordALSA::tracks ( )
virtual

Returns the current number of tracks

Implements Kwave::RecordDevice.

Definition at line 713 of file Record-ALSA.cpp.

References m_tracks.

Referenced by setTracks().

714 {
715  return m_tracks;
716 }
unsigned int m_tracks
Definition: Record-ALSA.h:242
Here is the caller graph for this function:

Member Data Documentation

◆ m_bits_per_sample

unsigned int Kwave::RecordALSA::m_bits_per_sample
private

resolution [bits per sample]

Definition at line 251 of file Record-ALSA.h.

Referenced by bitsPerSample(), detectSampleFormats(), endianness(), initialize(), and setBitsPerSample().

◆ m_buffer_size

unsigned int Kwave::RecordALSA::m_buffer_size
private

size of the transfer buffer in bytes

Definition at line 274 of file Record-ALSA.h.

Referenced by initialize().

◆ m_bytes_per_sample

unsigned int Kwave::RecordALSA::m_bytes_per_sample
private

Number of bytes per sample, already multiplied with the number of channels (m_channels)

Definition at line 257 of file Record-ALSA.h.

Referenced by initialize(), and read().

◆ m_chunk_size

snd_pcm_uframes_t Kwave::RecordALSA::m_chunk_size
private

number of samples per period

Definition at line 277 of file Record-ALSA.h.

Referenced by initialize(), and read().

◆ m_compression

Kwave::Compression::Type Kwave::RecordALSA::m_compression
private

compression mode

Definition at line 248 of file Record-ALSA.h.

Referenced by compression(), detectSampleFormats(), endianness(), initialize(), setCompression(), and supportedBits().

◆ m_device_list

QMap< QString, QString > Kwave::RecordALSA::m_device_list
staticprivate

dictionary for translating verbose device names into ALSA hardware device names

initializer for the list of devices

Definition at line 239 of file Record-ALSA.h.

Referenced by alsaDeviceName(), scanDevices(), and supportedDevices().

◆ m_handle

snd_pcm_t* Kwave::RecordALSA::m_handle
private

handle of the source device or null if not open

Definition at line 224 of file Record-ALSA.h.

Referenced by close(), detectSampleRates(), detectSupportedFormats(), detectTracks(), initialize(), open(), and read().

◆ m_hw_params

snd_pcm_hw_params_t* Kwave::RecordALSA::m_hw_params
private

ALSA hardware parameters

Definition at line 227 of file Record-ALSA.h.

Referenced by detectSampleRates(), detectSupportedFormats(), detectTracks(), initialize(), RecordALSA(), and ~RecordALSA().

◆ m_initialized

bool Kwave::RecordALSA::m_initialized
private

true if initialize() has been successfully been run

Definition at line 271 of file Record-ALSA.h.

Referenced by close(), initialize(), open(), read(), setBitsPerSample(), setCompression(), setSampleFormat(), setSampleRate(), and setTracks().

◆ m_open_result

int Kwave::RecordALSA::m_open_result
private

result of the "open" call, of interest when m_handle == 0

Definition at line 233 of file Record-ALSA.h.

Referenced by close(), open(), and read().

◆ m_rate

double Kwave::RecordALSA::m_rate
private

sample rate

Definition at line 245 of file Record-ALSA.h.

Referenced by initialize(), read(), sampleRate(), and setSampleRate().

◆ m_sample_format

Kwave::SampleFormat::Format Kwave::RecordALSA::m_sample_format
private

sample format (signed int, unsigned int, float, ...

Definition at line 260 of file Record-ALSA.h.

Referenced by endianness(), initialize(), sampleFormat(), and setSampleFormat().

◆ m_supported_formats

QList<int> Kwave::RecordALSA::m_supported_formats
private

list of supported formats of the current device, indices in the global list of known formats. Only valid after a successful call to "open()", otherwise empty

Definition at line 268 of file Record-ALSA.h.

Referenced by close(), detectCompressions(), detectSampleFormats(), detectSupportedFormats(), mode2format(), and supportedBits().

◆ m_sw_params

snd_pcm_sw_params_t* Kwave::RecordALSA::m_sw_params
private

ALSA software parameters

Definition at line 230 of file Record-ALSA.h.

Referenced by initialize(), RecordALSA(), and ~RecordALSA().

◆ m_tracks

unsigned int Kwave::RecordALSA::m_tracks
private

number of tracks [0...N-1]

Definition at line 242 of file Record-ALSA.h.

Referenced by initialize(), setTracks(), and tracks().


The documentation for this class was generated from the following files: