1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | /*! |
41 | \class QAudioProbe |
42 | \inmodule QtMultimedia |
43 | |
44 | \ingroup multimedia |
45 | \ingroup multimedia_audio |
46 | |
47 | \brief The QAudioProbe class allows you to monitor audio being played or recorded. |
48 | |
49 | \snippet multimedia-snippets/qaudioprobe.cpp desc |
50 | |
51 | \sa QVideoProbe, QMediaPlayer, QCamera |
52 | */ |
53 | |
54 | #include "qaudioprobe.h" |
55 | #include "qmediaaudioprobecontrol.h" |
56 | #include "qmediaservice.h" |
57 | #include "qmediarecorder.h" |
58 | #include "qsharedpointer.h" |
59 | #include "qpointer.h" |
60 | |
61 | QT_BEGIN_NAMESPACE |
62 | |
63 | class QAudioProbePrivate { |
64 | public: |
65 | QPointer<QMediaObject> source; |
66 | QPointer<QMediaAudioProbeControl> probee; |
67 | }; |
68 | |
69 | /*! |
70 | Creates a new QAudioProbe class with a \a parent. After setting the |
71 | source to monitor with \l setSource(), the \l audioBufferProbed() |
72 | signal will be emitted when audio buffers are flowing in the |
73 | source media object. |
74 | */ |
75 | QAudioProbe::QAudioProbe(QObject *parent) |
76 | : QObject(parent) |
77 | , d(new QAudioProbePrivate) |
78 | { |
79 | } |
80 | |
81 | /*! |
82 | Destroys this probe and disconnects from any |
83 | media object. |
84 | */ |
85 | QAudioProbe::~QAudioProbe() |
86 | { |
87 | if (d->source) { |
88 | // Disconnect |
89 | if (d->probee) { |
90 | disconnect(sender: d->probee.data(), SIGNAL(audioBufferProbed(QAudioBuffer)), receiver: this, SIGNAL(audioBufferProbed(QAudioBuffer))); |
91 | disconnect(sender: d->probee.data(), SIGNAL(flush()), receiver: this, SIGNAL(flush())); |
92 | } |
93 | d->source.data()->service()->releaseControl(control: d->probee.data()); |
94 | } |
95 | } |
96 | |
97 | /*! |
98 | Sets the media object to monitor to \a source. |
99 | |
100 | If \a source is zero, this probe will be deactivated |
101 | and this function wil return true. |
102 | |
103 | If the media object does not support monitoring |
104 | audio, this function will return false. |
105 | |
106 | The previous object will no longer be monitored. |
107 | Passing in the same object will be ignored, but |
108 | monitoring will continue. |
109 | */ |
110 | bool QAudioProbe::setSource(QMediaObject *source) |
111 | { |
112 | // Need to: |
113 | // 1) disconnect from current source if necessary |
114 | // 2) see if new one has the probe control |
115 | // 3) connect if so |
116 | |
117 | // in case source was destroyed but probe control is still valid |
118 | if (!d->source && d->probee) { |
119 | disconnect(sender: d->probee.data(), SIGNAL(audioBufferProbed(QAudioBuffer)), receiver: this, SIGNAL(audioBufferProbed(QAudioBuffer))); |
120 | disconnect(sender: d->probee.data(), SIGNAL(flush()), receiver: this, SIGNAL(flush())); |
121 | d->probee.clear(); |
122 | } |
123 | |
124 | if (source != d->source.data()) { |
125 | if (d->source) { |
126 | Q_ASSERT(d->probee); |
127 | disconnect(sender: d->probee.data(), SIGNAL(audioBufferProbed(QAudioBuffer)), receiver: this, SIGNAL(audioBufferProbed(QAudioBuffer))); |
128 | disconnect(sender: d->probee.data(), SIGNAL(flush()), receiver: this, SIGNAL(flush())); |
129 | d->source.data()->service()->releaseControl(control: d->probee.data()); |
130 | d->source.clear(); |
131 | d->probee.clear(); |
132 | } |
133 | |
134 | if (source) { |
135 | QMediaService *service = source->service(); |
136 | if (service) { |
137 | d->probee = service->requestControl<QMediaAudioProbeControl*>(); |
138 | } |
139 | |
140 | if (d->probee) { |
141 | connect(sender: d->probee.data(), SIGNAL(audioBufferProbed(QAudioBuffer)), receiver: this, SIGNAL(audioBufferProbed(QAudioBuffer))); |
142 | connect(sender: d->probee.data(), SIGNAL(flush()), receiver: this, SIGNAL(flush())); |
143 | d->source = source; |
144 | } |
145 | } |
146 | } |
147 | |
148 | return (!source || d->probee != nullptr); |
149 | } |
150 | |
151 | /*! |
152 | Starts monitoring the given \a mediaRecorder. |
153 | |
154 | Returns true on success. |
155 | |
156 | If there is no mediaObject associated with \a mediaRecorder, or if it is |
157 | zero, this probe will be deactivated and this function wil return true. |
158 | |
159 | If the media recorder instance does not support monitoring |
160 | audio, this function will return false. |
161 | |
162 | Any previously monitored objects will no longer be monitored. |
163 | Passing in the same (valid) object will be ignored, but |
164 | monitoring will continue. |
165 | */ |
166 | bool QAudioProbe::setSource(QMediaRecorder *mediaRecorder) |
167 | { |
168 | QMediaObject *source = mediaRecorder ? mediaRecorder->mediaObject() : nullptr; |
169 | bool result = setSource(source); |
170 | |
171 | if (!mediaRecorder) |
172 | return true; |
173 | |
174 | if (mediaRecorder && !source) |
175 | return false; |
176 | |
177 | return result; |
178 | } |
179 | |
180 | /*! |
181 | Returns true if this probe is monitoring something, or false otherwise. |
182 | |
183 | The source being monitored does not need to be active. |
184 | */ |
185 | bool QAudioProbe::isActive() const |
186 | { |
187 | return d->probee != nullptr; |
188 | } |
189 | |
190 | /*! |
191 | \fn QAudioProbe::audioBufferProbed(const QAudioBuffer &buffer) |
192 | |
193 | This signal should be emitted when an audio \a buffer is processed in the |
194 | media service. |
195 | */ |
196 | |
197 | |
198 | /*! |
199 | \fn QAudioProbe::flush() |
200 | |
201 | This signal should be emitted when it is required to release all buffers. |
202 | Application must release all outstanding references to audio buffers. |
203 | */ |
204 | |
205 | QT_END_NAMESPACE |
206 | |