Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qalsaaudiodevices.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#include "private/qalsaaudiosource_p.h"
8#include "private/qalsaaudiosink_p.h"
9#include "private/qalsaaudiodevice_p.h"
10
11#include <alsa/asoundlib.h>
12
13QT_BEGIN_NAMESPACE
14
15namespace {
16
18{
19 void operator()(char *c) const { ::free(c); }
20};
21
22using unique_str = std::unique_ptr<char, free_char>;
23
24bool operator==(const unique_str &str, std::string_view sv)
25{
26 return std::string_view{ str.get() } == sv;
27}
28bool operator!=(const unique_str &str, std::string_view sv)
29{
30 return !(str == sv);
31}
32
33} // namespace
34
39
40static QList<QAudioDevice> availableDevices(QAudioDevice::Mode mode)
41{
42 QList<QAudioDevice> devices;
43
44 // Create a list of all current audio devices that support mode
45 void **hints;
46 if (snd_device_name_hint(-1, "pcm", &hints) < 0) {
47 qWarning() << "no alsa devices available";
48 return devices;
49 }
50
51 std::string_view filter = (mode == QAudioDevice::Input) ? "Input" : "Output";
52
53 QAlsaAudioDeviceInfo *sysdefault = nullptr;
54
55 auto makeDeviceInfo = [&filter, mode](void *entry) -> std::unique_ptr<QAlsaAudioDeviceInfo> {
56 unique_str name{ snd_device_name_get_hint(entry, "NAME") };
57 if (name && name != "null") {
58 unique_str descr{ snd_device_name_get_hint(entry, "DESC") };
59 unique_str io{ snd_device_name_get_hint(entry, "IOID") };
60
61 if (descr && (!io || (io == filter))) {
62 auto info = std::make_unique<QAlsaAudioDeviceInfo>(
63 name.get(), QString::fromUtf8(descr.get()), mode);
64 return info;
65 }
66 }
67 return nullptr;
68 };
69
70 bool hasDefault = false;
71 void **n = hints;
72 while (*n != NULL) {
73 std::unique_ptr<QAlsaAudioDeviceInfo> info = makeDeviceInfo(*n++);
74
75 if (info) {
76 if (!hasDefault && info->id.startsWith("default")) {
77 info->isDefault = true;
78 hasDefault = true;
79 }
80 if (!sysdefault && info->id.startsWith("sysdefault"))
81 sysdefault = info.get();
82 devices.append(QAudioDevicePrivate::createQAudioDevice(std::move(info)));
83 }
84 }
85
86 if (!hasDefault && sysdefault) {
87 // Make "sysdefault" the default device if there is no "default" device exists
88 sysdefault->isDefault = true;
89 hasDefault = true;
90 }
91 if (!hasDefault && devices.size() > 0) {
92 // forcefully declare the first device as "default"
93 std::unique_ptr<QAlsaAudioDeviceInfo> info = makeDeviceInfo(hints[0]);
94 if (info) {
95 info->isDefault = true;
96 devices.prepend(QAudioDevicePrivate::createQAudioDevice(std::move(info)));
97 }
98 }
99
100 snd_device_name_free_hint(hints);
101 return devices;
102}
103
105{
106 return availableDevices(QAudioDevice::Input);
107}
108
110{
111 return availableDevices(QAudioDevice::Output);
112}
113
114QPlatformAudioSource *QAlsaAudioDevices::createAudioSource(const QAudioDevice &deviceInfo,
115 const QAudioFormat &fmt,
116 QObject *parent)
117{
118 return new QAlsaAudioSource(deviceInfo, fmt, parent);
119}
120
121QPlatformAudioSink *QAlsaAudioDevices::createAudioSink(const QAudioDevice &deviceInfo,
122 const QAudioFormat &fmt,
123 QObject *parent)
124{
125 return new QAlsaAudioSink(deviceInfo, fmt, parent);
126}
127
128QT_END_NAMESPACE
QList< QAudioDevice > findAudioInputs() const override
QList< QAudioDevice > findAudioOutputs() const override
bool operator!=(const unique_str &str, std::string_view sv)
bool operator==(const unique_str &str, std::string_view sv)
static QList< QAudioDevice > availableDevices(QAudioDevice::Mode mode)