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
7
8#include "private/qalsaaudiosource_p.h"
9#include "private/qalsaaudiosink_p.h"
10#include "private/qalsaaudiodevice_p.h"
11
12#include <alsa/asoundlib.h>
13
14QT_BEGIN_NAMESPACE
15
16namespace {
17
19{
20 void operator()(char *c) const { ::free(c); }
21};
22
23using unique_str = std::unique_ptr<char, free_char>;
24
25bool operator==(const unique_str &str, std::string_view sv)
26{
27 return std::string_view{ str.get() } == sv;
28}
29bool operator!=(const unique_str &str, std::string_view sv)
30{
31 return !(str == sv);
32}
33
34} // namespace
35
40
41static QList<QAudioDevice> availableDevices(QAudioDevice::Mode mode)
42{
43 QList<QAudioDevice> devices;
44
45 // Create a list of all current audio devices that support mode
46 void **hints;
47 if (snd_device_name_hint(-1, "pcm", &hints) < 0) {
48 qWarning() << "no alsa devices available";
49 return devices;
50 }
51
52 std::string_view filter = (mode == QAudioDevice::Input) ? "Input" : "Output";
53
54 QAlsaAudioDeviceInfo *sysdefault = nullptr;
55
56 auto makeDeviceInfo = [&filter, mode](void *entry) -> QAlsaAudioDeviceInfo * {
57 unique_str name{ snd_device_name_get_hint(entry, "NAME") };
58 if (name && name != "null") {
59 unique_str descr{ snd_device_name_get_hint(entry, "DESC") };
60 unique_str io{ snd_device_name_get_hint(entry, "IOID") };
61
62 if (descr && (!io || (io == filter))) {
63 auto *infop = new QAlsaAudioDeviceInfo{
64 name.get(),
65 QString::fromUtf8(descr.get()),
66 mode,
67 };
68 return infop;
69 }
70 }
71 return nullptr;
72 };
73
74 bool hasDefault = false;
75 void **n = hints;
76 while (*n != NULL) {
77 QAlsaAudioDeviceInfo *infop = makeDeviceInfo(*n++);
78
79 if (infop) {
80 devices.append(infop->create());
81 if (!hasDefault && infop->id.startsWith("default")) {
82 infop->isDefault = true;
83 hasDefault = true;
84 }
85 if (!sysdefault && infop->id.startsWith("sysdefault"))
86 sysdefault = infop;
87 }
88 }
89
90 if (!hasDefault && sysdefault) {
91 // Make "sysdefault" the default device if there is no "default" device exists
92 sysdefault->isDefault = true;
93 hasDefault = true;
94 }
95 if (!hasDefault && devices.size() > 0) {
96 // forcefully declare the first device as "default"
97 QAlsaAudioDeviceInfo *infop = makeDeviceInfo(hints[0]);
98 if (infop) {
99 infop->isDefault = true;
100 devices.prepend(infop->create());
101 }
102 }
103
104 snd_device_name_free_hint(hints);
105 return devices;
106}
107
109{
110 return availableDevices(QAudioDevice::Input);
111}
112
114{
115 return availableDevices(QAudioDevice::Output);
116}
117
118QPlatformAudioSource *QAlsaAudioDevices::createAudioSource(const QAudioDevice &deviceInfo,
119 const QAudioFormat &fmt,
120 QObject *parent)
121{
122 auto ret = new QAlsaAudioSource(deviceInfo.id(), parent);
123 ret->setFormat(fmt);
124 return ret;
125}
126
127QPlatformAudioSink *QAlsaAudioDevices::createAudioSink(const QAudioDevice &deviceInfo,
128 const QAudioFormat &fmt,
129 QObject *parent)
130{
131 auto ret = new QAlsaAudioSink(deviceInfo.id(), parent);
132 ret->setFormat(fmt);
133 return ret;
134}
135
136QT_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)