Alsa: fix crash when detecting devices.

Some old versions of Alsa crash when snd_device_name_hint(-1, ...) is
called. This patch works around the problem by iterating manually over all
the available sound cards.

Change-Id: Ic380a371acc15013d137553ff30d68bed5af664e
Reviewed-by: Christian Stromme <christian.stromme@digia.com>
This commit is contained in:
Yoann Lopes
2014-01-30 16:32:53 +01:00
committed by The Qt Project
parent 67b86a9fbd
commit 0ab81ef59f
2 changed files with 80 additions and 72 deletions

View File

@@ -119,33 +119,36 @@ void QGstreamerAudioInputSelector::updateAlsaDevices()
{ {
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
void **hints, **n; void **hints, **n;
if (snd_device_name_hint(-1, "pcm", &hints) < 0) { int card = -1;
qWarning()<<"no alsa devices available";
return;
}
n = hints;
while (*n != NULL) { while (snd_card_next(&card) == 0 && card >= 0) {
char *name = snd_device_name_get_hint(*n, "NAME"); if (snd_device_name_hint(card, "pcm", &hints) < 0)
char *descr = snd_device_name_get_hint(*n, "DESC"); continue;
char *io = snd_device_name_get_hint(*n, "IOID");
if ((name != NULL) && (descr != NULL)) { n = hints;
if ( io == NULL || qstrcmp(io,"Input") == 0 ) { while (*n != NULL) {
m_names.append(QLatin1String("alsa:")+QString::fromUtf8(name)); char *name = snd_device_name_get_hint(*n, "NAME");
m_descriptions.append(QString::fromUtf8(descr)); char *descr = snd_device_name_get_hint(*n, "DESC");
char *io = snd_device_name_get_hint(*n, "IOID");
if ((name != NULL) && (descr != NULL)) {
if ( io == NULL || qstrcmp(io,"Input") == 0 ) {
m_names.append(QLatin1String("alsa:")+QString::fromUtf8(name));
m_descriptions.append(QString::fromUtf8(descr));
}
} }
if (name != NULL)
free(name);
if (descr != NULL)
free(descr);
if (io != NULL)
free(io);
++n;
} }
if (name != NULL) snd_device_name_free_hint(hints);
free(name);
if (descr != NULL)
free(descr);
if (io != NULL)
free(io);
n++;
} }
snd_device_name_free_hint(hints);
#endif #endif
} }

View File

@@ -345,14 +345,9 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
// Create a list of all current audio devices that support mode // Create a list of all current audio devices that support mode
void **hints, **n; void **hints;
char *name, *descr, *io; char *name, *descr, *io;
int card = -1;
if(snd_device_name_hint(-1, "pcm", &hints) < 0) {
qWarning() << "no alsa devices available";
return devices;
}
n = hints;
if(mode == QAudio::AudioInput) { if(mode == QAudio::AudioInput) {
filter = "Input"; filter = "Input";
@@ -360,28 +355,35 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
filter = "Output"; filter = "Output";
} }
while (*n != NULL) { while (snd_card_next(&card) == 0 && card >= 0) {
name = snd_device_name_get_hint(*n, "NAME"); if (snd_device_name_hint(card, "pcm", &hints) < 0)
if (name != 0 && qstrcmp(name, "null") != 0) { continue;
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if ((descr != NULL) && ((io == NULL) || (io == filter))) { void **n = hints;
QString deviceName = QLatin1String(name); while (*n != NULL) {
QString deviceDescription = QLatin1String(descr); name = snd_device_name_get_hint(*n, "NAME");
if (deviceDescription.contains(QLatin1String("Default Audio Device"))) if (name != 0 && qstrcmp(name, "null") != 0) {
devices.prepend(deviceName.toLocal8Bit().constData()); descr = snd_device_name_get_hint(*n, "DESC");
else io = snd_device_name_get_hint(*n, "IOID");
devices.append(deviceName.toLocal8Bit().constData());
if ((descr != NULL) && ((io == NULL) || (io == filter))) {
QString deviceName = QLatin1String(name);
QString deviceDescription = QLatin1String(descr);
if (deviceDescription.contains(QLatin1String("Default Audio Device")))
devices.prepend(deviceName.toLocal8Bit().constData());
else
devices.append(deviceName.toLocal8Bit().constData());
}
free(descr);
free(io);
} }
free(name);
free(descr); ++n;
free(io);
} }
free(name);
++n; snd_device_name_free_hint(hints);
} }
snd_device_name_free_hint(hints);
#else #else
int idx = 0; int idx = 0;
char* name; char* name;
@@ -422,38 +424,41 @@ void QAudioDeviceInfoInternal::checkSurround()
surround51 = false; surround51 = false;
surround71 = false; surround71 = false;
void **hints, **n; void **hints;
char *name, *descr, *io; char *name, *descr, *io;
int card = -1;
if(snd_device_name_hint(-1, "pcm", &hints) < 0) while (snd_card_next(&card) == 0 && card >= 0) {
return; if (snd_device_name_hint(card, "pcm", &hints) < 0)
continue;
n = hints; void **n = hints;
while (*n != NULL) {
while (*n != NULL) { name = snd_device_name_get_hint(*n, "NAME");
name = snd_device_name_get_hint(*n, "NAME"); descr = snd_device_name_get_hint(*n, "DESC");
descr = snd_device_name_get_hint(*n, "DESC"); io = snd_device_name_get_hint(*n, "IOID");
io = snd_device_name_get_hint(*n, "IOID"); if((name != NULL) && (descr != NULL)) {
if((name != NULL) && (descr != NULL)) { QString deviceName = QLatin1String(name);
QString deviceName = QLatin1String(name); if (mode == QAudio::AudioOutput) {
if (mode == QAudio::AudioOutput) { if(deviceName.contains(QLatin1String("surround40")))
if(deviceName.contains(QLatin1String("surround40"))) surround40 = true;
surround40 = true; if(deviceName.contains(QLatin1String("surround51")))
if(deviceName.contains(QLatin1String("surround51"))) surround51 = true;
surround51 = true; if(deviceName.contains(QLatin1String("surround71")))
if(deviceName.contains(QLatin1String("surround71"))) surround71 = true;
surround71 = true; }
} }
if(name != NULL)
free(name);
if(descr != NULL)
free(descr);
if(io != NULL)
free(io);
++n;
} }
if(name != NULL)
free(name); snd_device_name_free_hint(hints);
if(descr != NULL)
free(descr);
if(io != NULL)
free(io);
++n;
} }
snd_device_name_free_hint(hints);
} }
QT_END_NAMESPACE QT_END_NAMESPACE