25 #ifdef HAVE_ALSA_SUPPORT 32 #include <QLatin1Char> 36 #include <KLocalizedString> 50 #define DEFAULT_DEVICE (i18n("Default device") + _("|sound_note")) 53 #define NULL_DEVICE (i18n("Null device") + _("|sound_note")) 58 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 60 #define SND_PCM_FORMAT_S18_3 SND_PCM_FORMAT_S18_3BE 61 #define SND_PCM_FORMAT_U18_3 SND_PCM_FORMAT_U18_3BE 62 #define SND_PCM_FORMAT_U20_3 SND_PCM_FORMAT_U20_3BE 63 #define SND_PCM_FORMAT_S20_3 SND_PCM_FORMAT_S20_3BE 64 #define SND_PCM_FORMAT_U24_3 SND_PCM_FORMAT_U24_3BE 65 #define SND_PCM_FORMAT_S24_3 SND_PCM_FORMAT_S24_3BE 69 #define SND_PCM_FORMAT_S18_3 SND_PCM_FORMAT_S18_3LE 70 #define SND_PCM_FORMAT_U18_3 SND_PCM_FORMAT_U18_3LE 71 #define SND_PCM_FORMAT_U20_3 SND_PCM_FORMAT_U20_3LE 72 #define SND_PCM_FORMAT_S20_3 SND_PCM_FORMAT_S20_3LE 73 #define SND_PCM_FORMAT_U24_3 SND_PCM_FORMAT_U24_3LE 74 #define SND_PCM_FORMAT_S24_3 SND_PCM_FORMAT_S24_3LE 98 SND_PCM_FORMAT_S16, SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE,
99 SND_PCM_FORMAT_U16, SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_BE,
114 SND_PCM_FORMAT_S24, SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE,
115 SND_PCM_FORMAT_U24, SND_PCM_FORMAT_U24_LE, SND_PCM_FORMAT_U24_BE,
118 SND_PCM_FORMAT_S32, SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE,
119 SND_PCM_FORMAT_U32, SND_PCM_FORMAT_U32_LE, SND_PCM_FORMAT_U32_BE,
127 if (snd_pcm_format_float(fmt)) {
128 if (snd_pcm_format_width(fmt) == 32)
130 if (snd_pcm_format_width(fmt) == 64)
132 }
else if (snd_pcm_format_linear(fmt)) {
133 if (snd_pcm_format_signed(fmt) == 1)
135 else if (snd_pcm_format_unsigned(fmt) == 1)
146 if (snd_pcm_format_little_endian(fmt) == 1)
148 if (snd_pcm_format_big_endian(fmt) == 1)
159 template <
class T,
int (allocator)(T**),
void (deleter)(T*)>
178 inline operator T *&() {
return m_data; }
187 #define ALSA_MALLOC_WRAPPER(__t__) \ 188 AlsaMallocWrapper<__t__##_t, __t__##_malloc, __t__##_free> 198 m_bytes_per_sample(0),
205 m_supported_formats(),
220 qDebug(
"PlayBackALSA::setFormat(..., bits=%u)", bits);
229 if (format_index < 0) {
230 qWarning(
"PlayBackALSA::setFormat(): %u bit is not supported", bits);
246 qWarning(
"PlayBackALSA: out of memory");
253 Q_ASSERT(
m_format != SND_PCM_FORMAT_UNKNOWN);
268 if (snd_pcm_format_width(*fmt) != bits)
continue;
278 qWarning(
"PlayBackALSA::mode2format -> no match found !?");
286 QList<int> supported_formats;
290 if (!p)
return supported_formats;
293 if (!pcm)
return supported_formats;
295 if (snd_pcm_hw_params_any(pcm, p) < 0) {
296 if (pcm !=
m_handle) snd_pcm_close(pcm);
297 return supported_formats;
302 const unsigned int count =
304 for (
unsigned int i=0; i < count; i++) {
307 int err = snd_pcm_hw_params_test_format(pcm, p, format);
308 if (err < 0)
continue;
334 supported_formats.append(i);
338 if (pcm !=
m_handle) snd_pcm_close(pcm);
339 return supported_formats;
344 unsigned int channels,
unsigned int bits)
347 snd_output_t *output = Q_NULLPTR;
350 snd_pcm_uframes_t buffer_size;
351 unsigned period_time = 0;
352 unsigned buffer_time = 0;
353 snd_pcm_uframes_t period_frames = 0;
354 snd_pcm_uframes_t buffer_frames = 0;
355 snd_pcm_uframes_t start_threshold, stop_threshold;
363 qDebug(
"PlayBackALSA::openDevice() - opening ALSA device '%s', " 364 "%dHz %d channels, %u bit",
365 DBG(alsa_device.split(
_(
"|")).at(0)), rate, channels, bits);
369 if (alsa_device.endsWith(
_(
",")))
return -ENODEV;
371 if (!rate)
return -EINVAL;
372 if (!channels)
return -EINVAL;
373 if (!bits)
return -EINVAL;
375 err = snd_output_stdio_attach(&output, stderr, 0);
377 qWarning(
"Output failed: %s", snd_strerror(err));
381 err = snd_pcm_open(&
m_handle, alsa_device.toLocal8Bit().data(),
382 SND_PCM_STREAM_PLAYBACK,
384 if (err < 0)
return err;
392 SND_PCM_FORMAT_S16_LE,
393 SND_PCM_SUBFORMAT_STD,
394 SND_SPCM_LATENCY_MEDIUM,
395 SND_PCM_ACCESS_RW_INTERLEAVED,
399 qWarning(
"Cannot initialize '%s': %s",
400 device.local8Bit().data(), snd_strerror(err));
404 if ((err = snd_pcm_hw_params_any(
m_handle, hw_params)) < 0) {
405 qWarning(
"Cannot initialize hardware parameters: %s",
407 snd_output_close(output);
411 err = snd_pcm_hw_params_set_access(
m_handle, hw_params,
412 SND_PCM_ACCESS_RW_INTERLEAVED);
414 qWarning(
"Cannot set access type: %s", snd_strerror(err));
415 snd_output_close(output);
421 qWarning(
"Cannot set sample format: %s", snd_strerror(err));
422 snd_output_close(output);
426 err = snd_pcm_hw_params_set_channels(
m_handle, hw_params, channels);
428 qWarning(
"Cannot set channel count: %s", snd_strerror(err));
429 snd_output_close(output);
433 unsigned int rrate = rate;
434 err = snd_pcm_hw_params_set_rate_near(
m_handle, hw_params, &rrate,
437 qWarning(
"Cannot set sample rate: %s", snd_strerror(err));
438 snd_output_close(output);
441 qDebug(
" real rate = %u", rrate);
442 if (static_cast<float>(rate) * 1.05f < rrate ||
443 static_cast<float>(rate) * 0.95f > rrate)
445 qWarning(
"rate is not accurate (requested = %iHz, got = %iHz)",
447 qWarning(
" please, try the plug plugin (-Dplug:%s)",
451 err = snd_pcm_hw_params_get_buffer_time_max(hw_params, &buffer_time,
454 if (buffer_time > 500000) buffer_time = 500000;
456 period_time = buffer_time / 4;
458 period_frames = buffer_frames / 4;
460 if (period_time > 0) {
461 err = snd_pcm_hw_params_set_period_time_near(
m_handle, hw_params,
462 &period_time, Q_NULLPTR);
464 err = snd_pcm_hw_params_set_period_size_near(
m_handle, hw_params,
465 &period_frames, Q_NULLPTR);
468 if (buffer_time > 0) {
469 err = snd_pcm_hw_params_set_buffer_time_near(
m_handle, hw_params,
470 &buffer_time, Q_NULLPTR);
472 err = snd_pcm_hw_params_set_buffer_size_near(
m_handle, hw_params,
477 qDebug(
" setting hw_params");
478 err = snd_pcm_hw_params(
m_handle, hw_params);
481 snd_output_close(output);
482 qWarning(
"Cannot set parameters: %s", snd_strerror(err));
486 snd_pcm_hw_params_get_period_size(hw_params, &
m_chunk_size, Q_NULLPTR);
487 snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
489 qWarning(
"Can't use period equal to buffer size (%lu == %lu)",
491 snd_output_close(output);
496 err = snd_pcm_sw_params_current(
m_handle, sw_params);
498 qWarning(
"Unable to determine current software parameters: %s",
500 snd_output_close(output);
509 err = snd_pcm_sw_params_set_start_threshold(
m_handle, sw_params,
512 stop_threshold = buffer_size;
514 err = snd_pcm_sw_params_set_stop_threshold(
m_handle, sw_params,
519 err = snd_pcm_sw_params(
m_handle, sw_params);
521 qDebug(
" activating snd_pcm_sw_params FAILED");
523 qWarning(
"Unable to set software parameters: %s", snd_strerror(err));
528 snd_output_close(output);
531 if ((err = snd_pcm_prepare(
m_handle)) < 0) {
533 qWarning(
"cannot prepare interface for use: %s", snd_strerror(err));
541 unsigned int channels,
unsigned int bits,
542 unsigned int bufbase)
544 qDebug(
"PlayBackALSA::open(device=%s, rate=%0.1f, channels=%u, bits=%u, " 545 "bufbase=%u)",
DBG(device), rate, channels, bits, bufbase);
573 reason = i18n(
"I/O error. Maybe the driver\n"\
574 "is not present in your kernel or it is not\n"\
575 "properly configured.");
579 "The device is busy. Maybe some other application is\n"\
580 "currently using it. Please try again later.\n"\
581 "(Hint: you might find out the name and process ID of\n"\
582 "the program by calling: \"fuser -v %1\"\n"\
583 "on the command line.)",
587 reason = i18n(
"Opening the device '%1' failed: %2",
588 device.section(QLatin1Char(
'|'), 0, 0),
589 QString::fromLocal8Bit(snd_strerror(err)));
598 Q_ASSERT(chunk_bytes);
599 if (!chunk_bytes)
return QString();
602 static_cast<double>(chunk_bytes)));
623 qWarning(
"PlayBackALSA::write(): buffer overflow ?! (%u/%u)",
629 QByteArray raw(bytes,
char(0));
651 unsigned int timeout = (
m_rate > 0) ?
652 3 * ((1000 * buffer_samples) /
654 quint8 *p =
reinterpret_cast<quint8 *
>(
m_buffer.data());
658 snd_pcm_format_set_silence(
m_format,
662 qDebug(
"--- added silence ---");
665 while (samples > 0) {
668 if ((r == -EAGAIN) || ((r >= 0) && (r <
Kwave::toInt(samples))))
671 }
else if (r == -EPIPE) {
673 qWarning(
"PlayBackALSA::flush(), underrun");
676 qWarning(
"PlayBackALSA::flush(), "\
677 "resume after underrun failed: %s",
682 qWarning(
"PlayBackALSA::flush(), after underrun: resuming");
684 }
else if (r == -ESTRPIPE) {
685 qWarning(
"PlayBackALSA::flush(), suspended. "\
686 "trying to resume...");
687 while ((r = snd_pcm_resume(
m_handle)) == -EAGAIN)
690 qWarning(
"PlayBackALSA::flush(), resume failed, "\
691 "restarting stream.");
692 if ((r = snd_pcm_prepare(
m_handle)) < 0) {
693 qWarning(
"PlayBackALSA::flush(), resume error: %s",
699 qWarning(
"PlayBackALSA::flush(), after suspend: resuming");
702 qWarning(
"write error: %s", snd_strerror(r));
750 if (snd_card_next(&card) < 0 || card < 0) {
751 qWarning(
"no soundcards found...");
759 name = name.arg(card);
760 if ((err = snd_ctl_open(&handle, name.toLocal8Bit().data(), 0)) < 0) {
761 qWarning(
"control open (%i): %s", card, snd_strerror(err));
764 if ((err = snd_ctl_card_info(handle, info)) < 0) {
765 qWarning(
"control hardware info (%i): %s",
766 card, snd_strerror(err));
767 snd_ctl_close(handle);
773 if (snd_ctl_pcm_next_device(handle, &dev)<0)
774 qWarning(
"snd_ctl_pcm_next_device");
777 snd_pcm_info_set_device(pcminfo, dev);
778 snd_pcm_info_set_subdevice(pcminfo, 0);
779 snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
780 if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
782 qWarning(
"control digital audio info (%i): %s", card,
786 count = snd_pcm_info_get_subdevices_count(pcminfo);
798 hw_device =
_(
"plughw:%1,%2");
799 hw_device = hw_device.arg(card).arg(dev);
801 QString card_name =
_(snd_ctl_card_info_get_name(info));
802 QString device_name =
_(snd_pcm_info_get_name(pcminfo));
808 snd_pcm_info_set_subdevice(pcminfo, idx);
809 if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
810 qWarning(
"ctrl digital audio playback info (%i): %s",
811 card, snd_strerror(err));
813 QString hwdev = hw_device +
_(
",%1").arg(idx);
814 QString subdevice_name =
815 _(snd_pcm_info_get_subdevice_name(pcminfo));
816 QString full_name = QString(
817 i18n(
"Card %1: ", card) + card_name +
819 i18n(
"Device %1: ", dev) + device_name +
820 _(
"|sound_device||") +
821 i18n(
"Subdevice %1: ", idx) + subdevice_name +
822 _(
"|sound_subdevice")
824 qDebug(
"# '%s' -> '%s'",
DBG(hwdev),
DBG(full_name));
830 QString full_name = QString(
831 i18n(
"Card %1: ", card) +
832 card_name +
_(
"|sound_card||") +
833 i18n(
"Device %1: ", dev) +
834 device_name +
_(
"|sound_subdevice")
840 snd_ctl_close(handle);
842 if (snd_card_next(&card) < 0) {
843 qWarning(
"snd_card_next failed");
875 if (n == name)
return n;
877 qWarning(
"PlayBackALSA::alsaDeviceName('%s') - NOT FOUND",
DBG(name));
897 if (!list.isEmpty()) list.append(
_(
"#TREE#"));
918 if (!alsa_device.length())
return Q_NULLPTR;
922 if (alsa_device.endsWith(
_(
",")))
return Q_NULLPTR;
926 int err = snd_pcm_open(&pcm, alsa_device.toLocal8Bit().data(),
927 SND_PCM_STREAM_PLAYBACK,
931 qWarning(
"PlayBackALSA::openDevice('%s') - failed, err=%d (%s)",
932 DBG(alsa_device), err, snd_strerror(err));
942 QList<unsigned int> list;
943 QList<int> supported_formats;
947 foreach (
int index, supported_formats) {
949 const unsigned int bits = snd_pcm_format_width(*fmt);
955 if (list.contains(bits))
continue;
966 unsigned int &min,
unsigned int &max)
976 if (snd_pcm_hw_params_any(pcm, p) >= 0) {
979 if ((err = snd_pcm_hw_params_get_channels_min(p, &min)) < 0)
980 qWarning(
"PlayBackALSA::detectTracks: min: %s",
982 if ((err = snd_pcm_hw_params_get_channels_max(p, &max)) < 0)
983 qWarning(
"PlayBackALSA::detectTracks: max: %s",
988 if (pcm !=
m_handle) snd_pcm_close(pcm);
#define SND_PCM_FORMAT_U24_3
snd_pcm_t * openDevice(const QString &device)
snd_pcm_format_t m_format
virtual QString open(const QString &device, double rate, unsigned int channels, unsigned int bits, unsigned int bufbase) Q_DECL_OVERRIDE
#define SND_PCM_FORMAT_S20_3
static Kwave::SampleFormat::Format sample_format_of(snd_pcm_format_t fmt)
QList< int > detectSupportedFormats(const QString &device)
virtual QString fileFilter() Q_DECL_OVERRIDE
#define SND_PCM_FORMAT_U18_3
#define SND_PCM_FORMAT_S24_3
QString alsaDeviceName(const QString &name)
#define SND_PCM_FORMAT_U20_3
#define ALSA_MALLOC_WRAPPER(__t__)
virtual int write(const Kwave::SampleArray &samples) Q_DECL_OVERRIDE
Kwave::SampleEncoder * m_encoder
virtual ~PlayBackALSA() Q_DECL_OVERRIDE
snd_pcm_uframes_t m_chunk_size
int setFormat(snd_pcm_hw_params_t *hw_params, unsigned int bits)
virtual QList< unsigned int > supportedBits(const QString &device) Q_DECL_OVERRIDE
static QMap< QString, QString > m_device_list
virtual int detectChannels(const QString &device, unsigned int &min, unsigned int &max) Q_DECL_OVERRIDE
static const snd_pcm_format_t _known_formats[]
static Kwave::byte_order_t endian_of(snd_pcm_format_t fmt)
unsigned int m_buffer_size
int mode2format(int bits)
virtual QStringList supportedDevices() Q_DECL_OVERRIDE
#define SND_PCM_FORMAT_S18_3
unsigned int m_bytes_per_sample
unsigned int m_buffer_used
virtual int close() Q_DECL_OVERRIDE
QList< int > m_supported_formats
virtual ~AlsaMallocWrapper()
virtual void encode(const Kwave::SampleArray &samples, unsigned int count, QByteArray &raw_data)=0