QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change
-
I am having an issue with the signal audioInputsChanged() from QMediaDevices not emitting as expected when the default audio input device changes at runtime. For example, when I have used the defaultAudioInput() and this gets unplugged, I'd like to update what I was doing with it.
What I’ve Tried:
I’m using QMediaDevices to listen for changes in the audio input devices. The code connects to the audioInputsChanged() signal of QMediaDevices to trigger the onTest() slot in my class.
However, even when the default audio input changes (which I can verify by accessing defaultAudioInput() with a timer), the connected slot (onTest()) is not being called. This leads me to believe that the signal is not being emitted or connected correctly.The connection to audioInputsChanged is made using the following code inside the constructor:
MyClass(QObject* parent) : QObject{parent}, m_mediaDevices{std::make_shared<QMediaDevices>(this)} { qInfo() << "default " << m_mediaDevices->defaultAudioInput().description(); connect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, this, &MyClass::onTest); } void MyClass::onTest() { qInfo() << "on test"; }
Expected Behavior:
The onTest() method should be called whenever the default audio input device changes, but it is not getting triggered.Things I Have Already Checked:
I have created a QTimer to call a function periodically (onDeviceChanged()), which works as expected getting the QMediaDevices::defaultAudioInput().Has anyone encountered a similar issue, or can anyone point out what might be causing the signal not to trigger when the input device changes?
-
Also doing this is not working:
(connection taken from https://youtu.be/a5_T1vuEa18?si=2NknlBbw6wh2nd5N&t=590)QMediaDevices devices; bool con = connect(&devices, &QMediaDevices::audioInputsChanged, [](){qInfo() << "devices changed";});
By the way, when checking on "con" I can see that the connect statement is true.
-
@papisant said in QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change:
QMediaDevices devices;
bool con = connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});Where is this code located?
devices is a local variable here... -
@jsulm I thought QMediaDevices was a singleton. Well, right now it is located in MyClass, which instantiates MyClass2.
In MyClass2, I use:defaultDevice = QMediaDevices::defaultAudioInput()
I thought I could listen for a change in the defaultAudioInput in MyClass, as I'd like to notify the change for other places too.
Nonetheless, listening for the change in MyClass2 does not seem to work also.
It is like the signal never gets emitted.In MyClass, if I do this, I can see the change when it happens using the Timer. But not by the firing of the audioInputsChanged() signal. This code is illustrative.
MyClass2* m_myClass2Obj = new MyClass2(); QTimer* timer = new QTimer(); timer->start(1000); connect(timer, &QTimer::timeout, this, [this](){m_myClass2Obj->onDeviceChanged();}); QMediaDevices devices; connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});
In MyClass2 I'd have (with the m_currentDevice initialized to the default device in its constructor):
void MyClass2::onDeviceChanged() { qInfo() << "onDeviceChanged"; QAudioDevice currentDefaultDevice = QMediaDevices::defaultAudioInput(); qInfo() << "current default device: " << QMediaDevices::defaultAudioInput().description(); // Check if the device has changed if (currentDefaultDevice != m_currentDevice) { // I see the device changing by checking every second for the defaultAudioInput, but never from audioInputsChanged qDebug() << "Audio input device has changed!"; } }
-
@papisant said in QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change:
QMediaDevices devices; connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});
In both your last two posts you show this. This won't work as shown because of the scope of
QMediaDevices devices
if that is a local variable. Admittedly that is not the case if you actually haveconnect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, ...)
per your original post, so you should verify what you are actually using. -
@JonB I am using connect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, ...) as per the original post with no luck.
The last two posts include the QMediaDevices devices as I tried that after finding the mentioned video because I though the problem could be in the connection as QMediaDevices::instance() does not exist. So both approaches I tried and described here don't work.
-
@JonB thank you for your recommendation. Using QMediaDevices m_devices; as a class member variable and connecting it did the trick. Now I see my slot getting called. Will check that the functional part of it works, but the issue with the signal is now solved. Thanks. Marking this as solved.
-
@papisant
Well, I'm not sure why it did not work with your originalm_mediaDevices{std::make_shared<QMediaDevices>(this)
which would surely be a class member too.Anyway, the important take away from this is: when connecting a signal you must look at the scope/lifetime of the signalling object (same for the slot). If either of these is a "local variable" that means the object will go out of scope and be destroyed at the end of the function they are in. And when Qt sees either the signalling or slot object being destroyed it auto-disconnects any connected signals/slots for that object (for obvious reasons). A connection only persists as long as both signal & slot objects are in existence. That is why class members are often used, or the object must be
new
ed and not deleted. -