19 #ifdef HAVE_ALSA_SUPPORT 36 #define DEFAULT_DEVICE (i18n("DSNOOP plugin") + _("|sound_note")) 39 #define ELEMENTS_OF(__array__) (sizeof(__array__) / sizeof(__array__[0])) 44 #if Q_BYTE_ORDER == Q_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 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 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,
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,
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,
108 SND_PCM_FORMAT_FLOAT, SND_PCM_FORMAT_FLOAT_LE, SND_PCM_FORMAT_FLOAT_BE,
111 SND_PCM_FORMAT_FLOAT64,
112 SND_PCM_FORMAT_FLOAT64_LE, SND_PCM_FORMAT_FLOAT64_BE,
116 SND_PCM_FORMAT_IEC958_SUBFRAME,
117 SND_PCM_FORMAT_IEC958_SUBFRAME_LE, SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
121 SND_PCM_FORMAT_MU_LAW,
124 SND_PCM_FORMAT_A_LAW,
133 SND_PCM_FORMAT_IMA_ADPCM,
142 SND_PCM_FORMAT_SPECIAL,
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)
169 if (snd_pcm_format_little_endian(fmt) == 1)
171 if (snd_pcm_format_big_endian(fmt) == 1)
181 case SND_PCM_FORMAT_MU_LAW:
183 case SND_PCM_FORMAT_A_LAW:
185 case SND_PCM_FORMAT_IMA_ADPCM:
187 case SND_PCM_FORMAT_MPEG:
189 case SND_PCM_FORMAT_GSM:
200 m_sw_params(Q_NULLPTR), m_open_result(0), m_tracks(0),
202 m_bits_per_sample(0), m_bytes_per_sample(0),
204 m_supported_formats(), m_initialized(false), m_buffer_size(0),
234 const unsigned int count =
236 for (
unsigned int i = 0; i < count; i++) {
240 if (err < 0)
continue;
282 if (!device.length())
return QString::number(EINVAL);
286 qDebug(
"RecordALSA::open -> '%s'",
DBG(alsa_device));
288 if (!alsa_device.length())
return QString::number(EINVAL);
292 if (alsa_device.endsWith(
_(
",")))
return QString::number(EINVAL);
296 SND_PCM_STREAM_CAPTURE,
300 qWarning(
"RecordALSA::openDevice('%s') - failed, err=%d (%s)",
310 reason = QString::number(ENODEV);
313 reason = QString::number(EBUSY);
316 reason = QString::fromLocal8Bit(snd_strerror(
m_open_result));
332 snd_output_t *output = Q_NULLPTR;
334 snd_pcm_uframes_t buffer_size;
335 unsigned period_time = 0;
336 unsigned buffer_time = 0;
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;
352 err = snd_output_stdio_attach(&output, stderr, 0);
354 qWarning(
"Output failed: %s", snd_strerror(err));
358 qWarning(
"Cannot initialize hardware parameters: %s",
360 snd_output_close(output);
365 SND_PCM_ACCESS_RW_INTERLEAVED);
367 qWarning(
"Cannot set access type: %s", snd_strerror(err));
368 snd_output_close(output);
374 Q_ASSERT(format_index >= 0);
375 if (format_index < 0) {
378 qWarning(
"RecordkALSA::setFormat(): no matching format for "\
379 "compression '%s', %d bits/sample, format '%s'",
384 snd_output_close(output);
388 Q_ASSERT(format_index >= 0);
395 qWarning(
"RecordkALSA::setFormat(): format %u is not supported",
396 static_cast<int>(alsa_format));
397 snd_output_close(output);
404 qWarning(
"Cannot set sample format: %s", snd_strerror(err));
405 snd_output_close(output);
411 qWarning(
"Cannot set channel count: %s", snd_strerror(err));
412 snd_output_close(output);
420 qWarning(
"Cannot set sample rate: %s", snd_strerror(err));
421 snd_output_close(output);
426 qWarning(
"rate is not accurate (requested = %iHz, got = %iHz)",
431 err = snd_pcm_hw_params_get_buffer_time_max(
m_hw_params, &buffer_time,
434 if (buffer_time > 500000) buffer_time = 500000;
437 period_time = buffer_time / 4;
439 period_frames = buffer_frames / 4;
441 if (period_time > 0) {
443 &period_time, Q_NULLPTR);
446 &period_frames, Q_NULLPTR);
449 if (buffer_time > 0) {
451 &buffer_time, Q_NULLPTR);
462 snd_output_close(output);
463 qWarning(
"Cannot set parameters: %s", snd_strerror(err));
468 snd_pcm_hw_params_get_buffer_size(
m_hw_params, &buffer_size);
470 qWarning(
"Can't use period equal to buffer size (%lu == %lu)",
472 snd_output_close(output);
479 qWarning(
"Unable to determine current software parameters: %s",
481 snd_output_close(output);
488 start_threshold = qMax<snd_pcm_uframes_t>(1, buffer_size);
492 stop_threshold = buffer_size;
501 qDebug(
" activating snd_pcm_sw_params FAILED");
503 qWarning(
"Unable to set software parameters: %s", snd_strerror(err));
507 if ((err = snd_pcm_prepare(
m_handle)) < 0) {
509 qWarning(
"cannot prepare interface for use: %s",snd_strerror(err));
512 if ((err = snd_pcm_start(
m_handle)) < 0) {
514 qWarning(
"cannot start interface: %s",snd_strerror(err));
522 snd_output_close(output);
530 unsigned int length = buffer.size();
533 if (!length)
return 0;
538 if (err < 0)
return err;
546 Q_ASSERT(chunk_bytes);
547 if (!chunk_bytes)
return 0;
550 unsigned int n = (length / chunk_bytes);
551 if (length != (n * chunk_bytes)) {
553 length = n * chunk_bytes;
556 buffer.resize(length);
559 Q_ASSERT(length >= offset);
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) {
573 case SND_PCM_STATE_OPEN:
574 qDebug(
"SND_PCM_STATE_OPEN");
576 case SND_PCM_STATE_SETUP:
577 qDebug(
"SND_PCM_STATE_SETUP");
579 case SND_PCM_STATE_PREPARED:
580 qDebug(
"ND_PCM_STATE_PREPARED");
582 case SND_PCM_STATE_RUNNING:
583 qDebug(
"SND_PCM_STATE_RUNNING");
585 case SND_PCM_STATE_XRUN:
586 qDebug(
"SND_PCM_STATE_XRUN");
588 case SND_PCM_STATE_DRAINING:
589 qDebug(
"SND_PCM_STATE_DRAINING");
591 case SND_PCM_STATE_PAUSED:
592 qDebug(
"SND_PCM_STATE_PAUSED");
594 case SND_PCM_STATE_SUSPENDED:
595 qDebug(
"SND_PCM_STATE_SUSPENDED");
597 case SND_PCM_STATE_DISCONNECTED:
598 qDebug(
"SND_PCM_STATE_DISCONNECTED");
609 snd_pcm_readi(
m_handle, buffer.data() + offset, samples)
614 unsigned int timeout = (
m_rate > 0) ?
618 }
else if (r == -EPIPE) {
620 qWarning(
"RecordALSA::read(), underrun");
622 if (r >= 0) r = snd_pcm_start(
m_handle);
624 qWarning(
"RecordALSA::read(), " 625 "resume after underrun failed: %s",
629 qWarning(
"RecordALSA::read(), after underrun: resuming");
631 }
else if (r == -ESTRPIPE) {
632 qWarning(
"RecordALSA::read(), suspended. "\
633 "trying to resume...");
634 while ((r = snd_pcm_resume(
m_handle)) == -EAGAIN)
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",
645 qWarning(
"RecordALSA::read(), after suspend: resuming");
648 qWarning(
"RecordALSA: read error: %s", snd_strerror(r));
692 if ((err = snd_pcm_hw_params_get_channels_min(
m_hw_params, &min)) < 0)
693 qWarning(
"RecordALSA::detectTracks: min: %s",
695 if ((err = snd_pcm_hw_params_get_channels_max(
m_hw_params, &max)) < 0)
696 qWarning(
"RecordALSA::detectTracks: max: %s",
727 static const unsigned int known_rates[] = {
766 for (
unsigned int i = 0; i <
ELEMENTS_OF(known_rates); i++) {
767 unsigned int rate = known_rates[i];
770 if (err < 0)
continue;
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;
811 if (snd_pcm_format_width(*fmt) != bits)
continue;
822 qWarning(
"RecordALSA::mode2format -> no match found !?");
829 QList<Kwave::Compression::Type> list;
838 if (list.contains(compression))
continue;
843 list.append(compression);
866 QList<unsigned int> list;
872 const unsigned int bits = snd_pcm_format_width(*fmt);
881 if (list.contains(bits))
continue;
907 QList<Kwave::SampleFormat::Format> list;
923 if (list.contains(sample_format))
continue;
929 list.append(sample_format);
953 return (index >= 0) ?
969 list.append(
_(
"#TREE#"));
976 snd_ctl_t *handle = Q_NULLPTR;
979 snd_ctl_card_info_t *info = Q_NULLPTR;
980 snd_pcm_info_t *pcminfo = Q_NULLPTR;
985 if (snd_card_next(&card) < 0 || card < 0) {
986 qWarning(
"no soundcards found...");
990 snd_ctl_card_info_malloc(&info);
991 snd_pcm_info_malloc(&pcminfo);
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));
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);
1011 if (snd_ctl_pcm_next_device(handle, &dev)<0)
1012 qWarning(
"snd_ctl_pcm_next_device");
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) {
1020 qWarning(
"control digital audio info (%i): %s", card,
1024 count = snd_pcm_info_get_subdevices_count(pcminfo);
1036 hw_device =
_(
"hw:%1,%2");
1037 hw_device = hw_device.arg(card).arg(dev);
1039 QString card_name =
_(snd_ctl_card_info_get_name(info));
1040 QString device_name =
_(snd_pcm_info_get_name(pcminfo));
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));
1051 QString hwdev = hw_device +
_(
",%1").arg(idx);
1052 QString subdevice_name =
_(
1053 snd_pcm_info_get_subdevice_name(pcminfo));
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));
1067 QString full_name = QString(
1068 i18n(
"Card %1: ", card_name) +
1069 _(
"|sound_card||") +
1070 i18n(
"Device %1: ", device_name) +
1071 _(
"|sound_subdevice")
1078 snd_ctl_close(handle);
1081 if (snd_card_next(&card) < 0) {
1082 qWarning(
"snd_card_next failed");
1092 snd_ctl_card_info_free(info);
1093 snd_pcm_info_free(pcminfo);
1116 if (n == name)
return n;
1118 qWarning(
"RecordALSA::alsaDeviceName('%s') - NOT FOUND",
DBG(name));
unsigned int m_buffer_size
virtual double sampleRate() Q_DECL_OVERRIDE
#define SND_PCM_FORMAT_S20_3
static const snd_pcm_format_t _known_formats[]
virtual QList< Kwave::SampleFormat::Format > detectSampleFormats() Q_DECL_OVERRIDE
virtual int setCompression(Kwave::Compression::Type new_compression) Q_DECL_OVERRIDE
Kwave::SampleFormat::Format m_sample_format
#define SND_PCM_FORMAT_U24_3
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
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
snd_pcm_sw_params_t * m_sw_params
virtual int tracks() Q_DECL_OVERRIDE
Kwave::Compression::Type m_compression
unsigned int m_bits_per_sample
virtual int read(QByteArray &buffer, unsigned int offset) Q_DECL_OVERRIDE
void detectSupportedFormats()
virtual QString open(const QString &dev) Q_DECL_OVERRIDE
virtual int detectTracks(unsigned int &min, unsigned int &max) Q_DECL_OVERRIDE
virtual ~RecordALSA() Q_DECL_OVERRIDE
unsigned int m_bytes_per_sample
snd_pcm_hw_params_t * m_hw_params
virtual Kwave::byte_order_t endianness() Q_DECL_OVERRIDE
#define SND_PCM_FORMAT_S24_3
#define SND_PCM_FORMAT_U18_3
virtual QList< unsigned int > supportedBits() Q_DECL_OVERRIDE
virtual int setSampleRate(double &new_rate) Q_DECL_OVERRIDE
QList< int > m_supported_formats
#define SND_PCM_FORMAT_U20_3
virtual int setSampleFormat(Kwave::SampleFormat::Format new_format) Q_DECL_OVERRIDE
virtual int bitsPerSample() Q_DECL_OVERRIDE
virtual int setTracks(unsigned int &tracks) Q_DECL_OVERRIDE
static QMap< QString, QString > m_device_list
virtual QList< Kwave::Compression::Type > detectCompressions() Q_DECL_OVERRIDE
virtual int setBitsPerSample(unsigned int new_bits) Q_DECL_OVERRIDE
snd_pcm_uframes_t m_chunk_size
#define ELEMENTS_OF(__array__)
QString alsaDeviceName(const QString &name)
IDX findFromData(const DATA &data) const
static Kwave::byte_order_t endian_of(snd_pcm_format_t fmt)