Alsa: fix crash when detecting devices.
authorYoann Lopes <yoann.lopes@digia.com>
Thu, 30 Jan 2014 15:32:53 +0000 (16:32 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 30 Jan 2014 17:12:44 +0000 (18:12 +0100)
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>
src/gsttools/qgstreameraudioinputselector.cpp
src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp

index dcab762..02d3e56 100644 (file)
@@ -119,33 +119,36 @@ void QGstreamerAudioInputSelector::updateAlsaDevices()
 {
 #ifdef HAVE_ALSA
     void **hints, **n;
-    if (snd_device_name_hint(-1, "pcm", &hints) < 0) {
-        qWarning()<<"no alsa devices available";
-        return;
-    }
-    n = hints;
-
-    while (*n != NULL) {
-        char *name = snd_device_name_get_hint(*n, "NAME");
-        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));
+    int card = -1;
+
+    while (snd_card_next(&card) == 0 && card >= 0) {
+        if (snd_device_name_hint(card, "pcm", &hints) < 0)
+            continue;
+
+        n = hints;
+        while (*n != NULL) {
+            char *name = snd_device_name_get_hint(*n, "NAME");
+            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)
-            free(name);
-        if (descr != NULL)
-            free(descr);
-        if (io != NULL)
-            free(io);
-        n++;
+        snd_device_name_free_hint(hints);
     }
-    snd_device_name_free_hint(hints);
 #endif
 }
 
index bc99202..bd8fa89 100644 (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)
     // Create a list of all current audio devices that support mode
-    void **hints, **n;
+    void **hints;
     char *name, *descr, *io;
-
-    if(snd_device_name_hint(-1, "pcm", &hints) < 0) {
-        qWarning() << "no alsa devices available";
-        return devices;
-    }
-    n = hints;
+    int card = -1;
 
     if(mode == QAudio::AudioInput) {
         filter = "Input";
@@ -360,28 +355,35 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
         filter = "Output";
     }
 
-    while (*n != NULL) {
-        name = snd_device_name_get_hint(*n, "NAME");
-        if (name != 0 && qstrcmp(name, "null") != 0) {
-            descr = snd_device_name_get_hint(*n, "DESC");
-            io = snd_device_name_get_hint(*n, "IOID");
-
-            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());
+    while (snd_card_next(&card) == 0 && card >= 0) {
+        if (snd_device_name_hint(card, "pcm", &hints) < 0)
+            continue;
+
+        void **n = hints;
+        while (*n != NULL) {
+            name = snd_device_name_get_hint(*n, "NAME");
+            if (name != 0 && qstrcmp(name, "null") != 0) {
+                descr = snd_device_name_get_hint(*n, "DESC");
+                io = snd_device_name_get_hint(*n, "IOID");
+
+                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(descr);
-            free(io);
+            free(name);
+            ++n;
         }
-        free(name);
-        ++n;
+
+        snd_device_name_free_hint(hints);
     }
-    snd_device_name_free_hint(hints);
 #else
     int idx = 0;
     char* name;
@@ -422,38 +424,41 @@ void QAudioDeviceInfoInternal::checkSurround()
     surround51 = false;
     surround71 = false;
 
-    void **hints, **n;
+    void **hints;
     char *name, *descr, *io;
+    int card = -1;
 
-    if(snd_device_name_hint(-1, "pcm", &hints) < 0)
-        return;
+    while (snd_card_next(&card) == 0 && card >= 0) {
+        if (snd_device_name_hint(card, "pcm", &hints) < 0)
+            continue;
 
-    n = hints;
-
-    while (*n != NULL) {
-        name = snd_device_name_get_hint(*n, "NAME");
-        descr = snd_device_name_get_hint(*n, "DESC");
-        io = snd_device_name_get_hint(*n, "IOID");
-        if((name != NULL) && (descr != NULL)) {
-            QString deviceName = QLatin1String(name);
-            if (mode == QAudio::AudioOutput) {
-                if(deviceName.contains(QLatin1String("surround40")))
-                    surround40 = true;
-                if(deviceName.contains(QLatin1String("surround51")))
-                    surround51 = true;
-                if(deviceName.contains(QLatin1String("surround71")))
-                    surround71 = true;
+        void **n = hints;
+        while (*n != NULL) {
+            name = snd_device_name_get_hint(*n, "NAME");
+            descr = snd_device_name_get_hint(*n, "DESC");
+            io = snd_device_name_get_hint(*n, "IOID");
+            if((name != NULL) && (descr != NULL)) {
+                QString deviceName = QLatin1String(name);
+                if (mode == QAudio::AudioOutput) {
+                    if(deviceName.contains(QLatin1String("surround40")))
+                        surround40 = true;
+                    if(deviceName.contains(QLatin1String("surround51")))
+                        surround51 = true;
+                    if(deviceName.contains(QLatin1String("surround71")))
+                        surround71 = true;
+                }
             }
+            if(name != NULL)
+                free(name);
+            if(descr != NULL)
+                free(descr);
+            if(io != NULL)
+                free(io);
+            ++n;
         }
-        if(name != NULL)
-            free(name);
-        if(descr != NULL)
-            free(descr);
-        if(io != NULL)
-            free(io);
-        ++n;
+
+        snd_device_name_free_hint(hints);
     }
-    snd_device_name_free_hint(hints);
 }
 
 QT_END_NAMESPACE