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
4#include <common/qgstreameraudioinput_p.h>
5
6#include <QtCore/qloggingcategory.h>
7#include <QtMultimedia/qaudiodevice.h>
8#include <QtMultimedia/qaudioinput.h>
9
10#include <audio/qgstreameraudiodevice_p.h>
11#include <common/qgstpipeline_p.h>
12
13
14QT_BEGIN_NAMESPACE
15
16namespace {
17
18Q_LOGGING_CATEGORY(qLcMediaAudioInput, "qt.multimedia.audioinput")
19
20constexpr QLatin1String defaultSrcName = [] {
21 using namespace Qt::Literals;
22
23 if constexpr (QT_CONFIG(pulseaudio))
24 return "pulsesrc"_L1;
25 else if constexpr (QT_CONFIG(alsa))
26 return "alsasrc"_L1;
27 else
28 return "autoaudiosrc"_L1;
29}();
30
31bool srcHasDeviceProperty(const QGstElement &element)
32{
33 using namespace Qt::Literals;
34 QLatin1String elementType = element.typeName();
35
36 if constexpr (QT_CONFIG(pulseaudio))
37 return elementType == "GstPulseSrc"_L1;
38
39 if constexpr (0 && QT_CONFIG(alsa)) // alsasrc has a "device" property, but it cannot be changed
40 // during playback
41 return elementType == "GstAlsaSrc"_L1;
42
43 return false;
44}
45
46} // namespace
47
48QMaybe<QPlatformAudioInput *> QGstreamerAudioInput::create(QAudioInput *parent)
49{
50 static const auto error = qGstErrorMessageIfElementsNotAvailable(arg: "autoaudiosrc", args: "volume");
51 if (error)
52 return *error;
53
54 return new QGstreamerAudioInput(parent);
55}
56
57QGstreamerAudioInput::QGstreamerAudioInput(QAudioInput *parent)
58 : QObject(parent),
59 QPlatformAudioInput(parent),
60 m_audioInputBin(QGstBin::create(name: "audioInput")),
61 m_audioSrc{
62 QGstElement::createFromFactory(factory: defaultSrcName.constData(), name: "autoaudiosrc"),
63 },
64 m_audioVolume{
65 QGstElement::createFromFactory(factory: "volume", name: "volume"),
66 }
67{
68 m_audioInputBin.add(ts: m_audioSrc, ts: m_audioVolume);
69 qLinkGstElements(ts: m_audioSrc, ts: m_audioVolume);
70
71 m_audioInputBin.addGhostPad(child: m_audioVolume, name: "src");
72}
73
74QGstElement QGstreamerAudioInput::createGstElement()
75{
76 const auto *customDeviceInfo =
77 dynamic_cast<const QGStreamerCustomAudioDeviceInfo *>(m_audioDevice.handle());
78
79 if (customDeviceInfo) {
80 qCDebug(qLcMediaAudioInput)
81 << "requesting custom audio src element: " << customDeviceInfo->id;
82
83 QGstElement element = QGstBin::createFromPipelineDescription(pipelineDescription: customDeviceInfo->id,
84 /*name=*/nullptr,
85 /*ghostUnlinkedPads=*/true);
86 if (element)
87 return element;
88
89 qCWarning(qLcMediaAudioInput)
90 << "Cannot create audio source element:" << customDeviceInfo->id;
91 }
92
93 const QByteArray &id = m_audioDevice.id();
94 if constexpr (QT_CONFIG(pulseaudio) || QT_CONFIG(alsa)) {
95 QGstElement newSrc = QGstElement::createFromFactory(factory: defaultSrcName.constData(), name: "audiosrc");
96 if (newSrc) {
97 newSrc.set(property: "device", str: id.constData());
98 return newSrc;
99 }
100
101 qWarning() << "Cannot create" << defaultSrcName;
102
103 } else {
104 auto *deviceInfo = dynamic_cast<const QGStreamerAudioDeviceInfo *>(m_audioDevice.handle());
105 if (deviceInfo && deviceInfo->gstDevice) {
106 QGstElement element = QGstElement::createFromDevice(deviceInfo->gstDevice, name: "audiosrc");
107 if (element)
108 return element;
109 }
110 }
111 qCWarning(qLcMediaAudioInput) << "Invalid audio device";
112 qCWarning(qLcMediaAudioInput)
113 << "Failed to create a gst element for the audio device, using a default audio source";
114 return QGstElement::createFromFactory(factory: "autoaudiosrc", name: "audiosrc");
115}
116
117QGstreamerAudioInput::~QGstreamerAudioInput()
118{
119 m_audioInputBin.setStateSync(state: GST_STATE_NULL);
120}
121
122void QGstreamerAudioInput::setVolume(float volume)
123{
124 m_audioVolume.set(property: "volume", d: volume);
125}
126
127void QGstreamerAudioInput::setMuted(bool muted)
128{
129 m_audioVolume.set(property: "mute", b: muted);
130}
131
132void QGstreamerAudioInput::setAudioDevice(const QAudioDevice &device)
133{
134 if (device == m_audioDevice)
135 return;
136 qCDebug(qLcMediaAudioInput) << "setAudioDevice" << device.description() << device.isNull();
137 m_audioDevice = device;
138
139 if (srcHasDeviceProperty(element: m_audioSrc) && !isCustomAudioDevice(device: m_audioDevice)) {
140 m_audioSrc.set(property: "device", str: m_audioDevice.id().constData());
141 return;
142 }
143
144 QGstElement newSrc = createGstElement();
145
146 m_audioVolume.sink().modifyPipelineInIdleProbe(f: [&] {
147 qUnlinkGstElements(ts: m_audioSrc, ts: m_audioVolume);
148 m_audioInputBin.stopAndRemoveElements(ts&: m_audioSrc);
149 m_audioSrc = std::move(newSrc);
150 m_audioInputBin.add(ts: m_audioSrc);
151 qLinkGstElements(ts: m_audioSrc, ts: m_audioVolume);
152 m_audioSrc.syncStateWithParent();
153 });
154}
155
156QT_END_NAMESPACE
157

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtmultimedia/src/plugins/multimedia/gstreamer/common/qgstreameraudioinput.cpp