Details
-
Task
-
Resolution: Unresolved
-
P3: Somewhat important
-
None
-
6.8
-
None
Description
This problem exists on both QCameraDevice and QAudioDevice. I will use QAudioDevice as an example.
When working with QAudioInput it's useful to see if the underlying device has been disconnected, so that you can correctly adjust app logic. The intended method for this is to compare the associated QAudioDevice up against QMediaDevices::audioInputs.
If the user uses regular comparison of QAudioDevice in QML, such as the following:
mediaDevices.audioInputs.some((connectedDevice) => connectedDevice === myAudioInput.device)
This will in turn call the equality operator for QAudioDevice. There is one problem that arises here. The implementation for equality here will also compare if the "isDefault" members are equal (see QAudioDevice.cpp#134). If you connect an external microphone, this new device will count as the default. Your existing QAudioInput will not change the device, and therefore the stored copy of QAudioDevice will have the member "isDefault" still set to true, even if that no longer reflects reality. If you try to see if your current audio-device is connected using the code above, it will return false because the "isDefault" members are no longer equal, even though the device is still connected and appears in the list.
One workaround here is to always compare the ID of the audio device instead. This alone is not enough. Although the documentation specifies that the member "id" of a QML AudioDevice should be of type String, it is parsed as an Object type by the QML compiler. So therefore it will start comparing the reference adresses rather than value. You can solve this with the following:
mediaDevices.audioInputs.some((connectedDevice) => String(connectedDevice.id) === String(myAudioInput.device.id))
This ID-based approach relies on the system always reporting different IDs for every device always, I think we can safely continue with this assumption.
The issue is that this approach is not documented anywhere. Currently this seems to be the only reliable approach with our current APIs, and as such it should be clear to our users how to do this.
- I think it would be nice if we documented to the user that comparison should be done based on ID in both QML and C++ for reliable results.
- I think we should solve this situation where the QML interprets the ID as an object instead of a String, making it harder to compare the IDs.
I would also argue it's fairly unintuitive that the default comparison behavior is not reliable in this manner, but that would require some minor behavior changes.