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 <qgstreameraudioinput_p.h> |
5 | #include <qgstreameraudiodevice_p.h> |
6 | #include <qaudiodevice.h> |
7 | #include <qaudioinput.h> |
8 | |
9 | #include <QtCore/qloggingcategory.h> |
10 | #include <QtNetwork/qnetworkaccessmanager.h> |
11 | #include <QtNetwork/qnetworkreply.h> |
12 | |
13 | #include <sys/types.h> |
14 | #include <sys/stat.h> |
15 | #include <fcntl.h> |
16 | |
17 | #include <utility> |
18 | |
19 | static Q_LOGGING_CATEGORY(qLcMediaAudioInput, "qt.multimedia.audioInput" ) |
20 | |
21 | QT_BEGIN_NAMESPACE |
22 | |
23 | QMaybe<QPlatformAudioInput *> QGstreamerAudioInput::create(QAudioInput *parent) |
24 | { |
25 | QGstElement autoaudiosrc("autoaudiosrc" , "autoaudiosrc" ); |
26 | if (!autoaudiosrc) |
27 | return errorMessageCannotFindElement(element: "autoaudiosrc" ); |
28 | |
29 | QGstElement volume("volume" , "volume" ); |
30 | if (!volume) |
31 | return errorMessageCannotFindElement(element: "volume" ); |
32 | |
33 | return new QGstreamerAudioInput(autoaudiosrc, volume, parent); |
34 | } |
35 | |
36 | QGstreamerAudioInput::QGstreamerAudioInput(QGstElement autoaudiosrc, QGstElement volume, |
37 | QAudioInput *parent) |
38 | : QObject(parent), |
39 | QPlatformAudioInput(parent), |
40 | gstAudioInput("audioInput" ), |
41 | audioSrc(std::move(autoaudiosrc)), |
42 | audioVolume(std::move(volume)) |
43 | { |
44 | gstAudioInput.add(e1: audioSrc, e2: audioVolume); |
45 | audioSrc.link(next: audioVolume); |
46 | |
47 | gstAudioInput.addGhostPad(child: audioVolume, name: "src" ); |
48 | } |
49 | |
50 | QGstreamerAudioInput::~QGstreamerAudioInput() |
51 | { |
52 | gstAudioInput.setStateSync(GST_STATE_NULL); |
53 | } |
54 | |
55 | int QGstreamerAudioInput::volume() const |
56 | { |
57 | return m_volume; |
58 | } |
59 | |
60 | bool QGstreamerAudioInput::isMuted() const |
61 | { |
62 | return m_muted; |
63 | } |
64 | |
65 | void QGstreamerAudioInput::setVolume(float vol) |
66 | { |
67 | if (vol == m_volume) |
68 | return; |
69 | m_volume = vol; |
70 | audioVolume.set(property: "volume" , d: vol); |
71 | emit volumeChanged(m_volume); |
72 | } |
73 | |
74 | void QGstreamerAudioInput::setMuted(bool muted) |
75 | { |
76 | if (muted == m_muted) |
77 | return; |
78 | m_muted = muted; |
79 | audioVolume.set(property: "mute" , b: muted); |
80 | emit mutedChanged(muted); |
81 | } |
82 | |
83 | void QGstreamerAudioInput::setAudioDevice(const QAudioDevice &device) |
84 | { |
85 | if (device == m_audioDevice) |
86 | return; |
87 | qCDebug(qLcMediaAudioInput) << "setAudioInput" << device.description() << device.isNull(); |
88 | m_audioDevice = device; |
89 | |
90 | QGstElement newSrc; |
91 | #if QT_CONFIG(pulseaudio) |
92 | auto id = m_audioDevice.id(); |
93 | newSrc = QGstElement("pulsesrc" , "audiosrc" ); |
94 | if (!newSrc.isNull()) |
95 | newSrc.set(property: "device" , str: id.constData()); |
96 | else |
97 | qCWarning(qLcMediaAudioInput) << "Invalid audio device" ; |
98 | #else |
99 | auto *deviceInfo = static_cast<const QGStreamerAudioDeviceInfo *>(m_audioDevice.handle()); |
100 | if (deviceInfo && deviceInfo->gstDevice) |
101 | newSrc = gst_device_create_element(deviceInfo->gstDevice, "audiosrc" ); |
102 | else |
103 | qCWarning(qLcMediaAudioInput) << "Invalid audio device" ; |
104 | #endif |
105 | |
106 | if (newSrc.isNull()) { |
107 | qCWarning(qLcMediaAudioInput) << "Failed to create a gst element for the audio device, using a default audio source" ; |
108 | newSrc = QGstElement("autoaudiosrc" , "audiosrc" ); |
109 | } |
110 | |
111 | // FIXME: most probably source can be disconnected outside of idle probe |
112 | audioSrc.staticPad(name: "src" ).doInIdleProbe(work: [&](){ |
113 | audioSrc.unlink(next: audioVolume); |
114 | }); |
115 | audioSrc.setStateSync(GST_STATE_NULL); |
116 | gstAudioInput.remove(element: audioSrc); |
117 | audioSrc = newSrc; |
118 | gstAudioInput.add(element: audioSrc); |
119 | audioSrc.link(next: audioVolume); |
120 | audioSrc.syncStateWithParent(); |
121 | } |
122 | |
123 | QAudioDevice QGstreamerAudioInput::audioInput() const |
124 | { |
125 | return m_audioDevice; |
126 | } |
127 | |
128 | QT_END_NAMESPACE |
129 | |
130 | #include "moc_qgstreameraudioinput_p.cpp" |
131 | |