qt6 QMediaDevices::audioInputs() does not return all input devices
-
I used the example programs from .../qt6/examples/multimedia/audiodevices and consistently find that the QMediaDevices method that replaced the qt5 QAudioDeviceInfo method returns just one device.
This is not the case for the audio devices example from ..../qt5/examples/multimemdia/audiodevices .
The problem occurs with both Fedora 42 and Fedora 43. The version in question is
Fedora 42:> qmake6 --version QMake version 3.1 Using Qt version 6.9.3 in /usr/lib64Fedora 43:
$ qmake6 --version QMake version 3.1 Using Qt version 6.10.1 in /usr/lib64So, what am I missing here? (I looked through the forums and was unable to find an earlier report of this issue. If there is one, please point me there.)
matt
-
It was rude of my not to include some code. Here is the relevant snippet from the qt6 example:
void AudioTest::updateAudioDevices() { deviceBox->clear(); const auto devices = m_mode == QAudioDevice::Input ? m_devices->audioInputs() : m_devices->audioOutputs(); for (auto &deviceInfo : devices) { QString description = deviceInfo.description(); description.replace(u"\n"_s, u" - "_s); deviceBox->addItem(description, QVariant::fromValue(deviceInfo)); } } -
Hi and welcome to devnet,
What is your audio software stack ?
Can you show the output your get on each of them ? -
Thanks for the response.
I'm not quite sure how to answer the question - I've always been a bit confused wrt Linux audio. So this might be more information than is needed...
The stack: I believe the answer is "pipewire" though pulse-audio is in there somewhere.
But the qt6 version dumps some disturbing chatter to stdout:
qt.multimedia.ffmpeg: Using Qt multimedia with FFmpeg version 7.1.2 GPL version 3 or later Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory libva info: VA-API version 1.22.0 libva info: Trying to open /usr/lib64/dri-nonfree/iHD_drv_video.so libva info: Trying to open /usr/lib64/dri-freeworld/iHD_drv_video.so libva info: Trying to open /usr/lib64/dri/iHD_drv_video.so libva info: Found init function __vaDriverInit_1_22 libva info: va_openDriver() returns 0 libva info: VA-API version 1.22.0 libva info: Trying to open /usr/lib64/dri-nonfree/iHD_drv_video.so libva info: Trying to open /usr/lib64/dri-freeworld/iHD_drv_video.so libva info: Trying to open /usr/lib64/dri/iHD_drv_video.so libva info: Found init function __vaDriverInit_1_22 libva info: va_openDriver() returns 0I know that pulse is involved as I set up a couple of virtual devices like this:
pactl load-module module-null-sink sink_name=RSink sink_properties=device.description="RadioSink" pactl load-module module-null-sink sink_name=MSink sink_properties=device.description="ModemSink"(These are to provide paths between a modem inside one app (wsjtx) and an SDR running in a separate process.)
I modified both example programs to write directly to the qInfo stream:
qt6 version:const auto devices = m_mode == QAudioDevice::Input ? m_devices->audioInputs() : m_devices->audioOutputs(); for (auto &deviceInfo : devices) { QString description = deviceInfo.description(); description.replace(u"\n"_s, u" - "_s); deviceBox->addItem(description, QVariant::fromValue(deviceInfo)); qInfo() << QString("audio device [%1] from audio%2()") .arg(description) .arg((m_mode == QAudioDevice::Input) ? "Inputs" : "Outputs") ; }which produces this output:
"" "audio device [Built-in Audio Analog Stereo] from audioOutputs()" "audio device [RadioSink] from audioOutputs()" "audio device [ModemSink] from audioOutputs()" "audio device [NoMachine Output] from audioOutputs()" "" "audio device [Remapped nx_voice_out] from audioInputs()" ""The qt5 version looks like this:
const QAudio::Mode mode = idx == 0 ? QAudio::AudioInput : QAudio::AudioOutput; for (auto &deviceInfo: QAudioDeviceInfo::availableDevices(mode)) { deviceBox->addItem(deviceInfo.deviceName(), QVariant::fromValue(deviceInfo)); qInfo() << QString("audio device [%1] from QAudioDeviceInfo::availableDevices(QAudio::Audio%2)") .arg(deviceInfo.deviceName()) .arg((mode == 0) ? "Input" : "Output") ; }and I get this for the output:
QSocketNotifier: Can only be used with threads started with QThread "audio device [pipewire] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" "audio device [default] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" "audio device [sysdefault:CARD=PCH] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" "audio device [front:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" "audio device [nx_remapped_out] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" "audio device [alsa_output.pci-0000_00_1f.3.analog-stereo.monitor] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" "audio device [RSink.monitor] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" "audio device [MSink.monitor] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" "audio device [nx_voice_out.monitor] from QAudioDeviceInfo::availableDevices(QAudio::AudioInput)" qt.qpa.wayland: Wayland does not support QWindow::requestActivate() "audio device [pipewire] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [default] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [sysdefault:CARD=PCH] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [front:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [surround21:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [surround40:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [surround41:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [surround50:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [surround51:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [surround71:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [hdmi:CARD=PCH,DEV=0] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [hdmi:CARD=PCH,DEV=1] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [hdmi:CARD=PCH,DEV=2] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [hdmi:CARD=PCH,DEV=3] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [alsa_output.pci-0000_00_1f.3.analog-stereo] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [RSink] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [MSink] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)" "audio device [nx_voice_out] from QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)"(Sorry for the monster blobs...)
So. The qt5 operations do what I expect.
I don't believe the problem comes from the virtual MSink and RSink devices.
The complaint about the VDPAU backend may be a hint. I've been unable to figure out where it comes from. I don't have any nVidia hardware on this box.I'm building the dev branch from the git sources now. I'll see if a new built-from-source version has the same lib...nvidia problem. That'll take a while, it may take until the weekend.
Thank you for your help.
Is there more information I can provide.? I apologize for the lack of linux audio sophistication.
-
I repeated the experiment with a build-from-git dev branch reporting "3.31.6" as the version. ( git hash e98fab4c4edfa49debfab549a81862922c0b52e8 )
The results were identical to the earlier experiment. I did get this warning, however:
build> ./audiodevices No QtMultimedia backends found. Only QMediaDevices, QAudioDevice, QSoundEffect, QAudioSink, and QAudioSource are available.(I built the Qt library and the test app after installing ffmpeg-free-devel. Though it doesn't appear to be referenced by the app or any of the lib files:
build> ldd ~/exp/qt6/root/lib/lib*.so | grep -i ffmpeg build>)
I built with DEBUG support on. Is there something that you'd like me to try? A particular place to poke around?
-
Qt 5 uses GStreamer as backend on Linux while Qt 6 now uses ffmpeg by default. This is the main difference.
It's strange that QtMultimedia did not build the ffmpeg backend.
What are you getting from the configuration step output ? -
I've tried multiple schemes and configurations.
In answer to no question at all: I've created a GitHub repo with a reproducer (scripts and source and a README) for the problem I'm having.git@github.com:kb1vc/qt_multimedia_audio_problem.git
In answer to your last question:
Building Qt6.10.1 under Fedora43 I see this mention of FFmpeg in the configure log:
CMake Warning at qtmultimedia/src/plugins/multimedia/ffmpeg/cmake/QtAddFFmpegStubs.cmake:38 (message): QT_FEATURE_vaapi is ON but FFmpeg includes VAAPI and dynamic symbols resolve is enabled. Call Stack (most recent call first): qtmultimedia/src/plugins/multimedia/ffmpeg/cmake/QtAddFFmpegStubs.cmake:189 (qt_internal_multimedia_check_ffmpeg_stubs_configuration) qtmultimedia/src/plugins/multimedia/ffmpeg/CMakeLists.txt:107 (qt_internal_multimedia_add_ffmpeg_stubs)I'm not sure what that means, but I'll try another run of the configure command:
Adding -DQT_FEATURE_vaapi=OFF got rid of the warning.The configure completed without warning. And the build completed.
The result of the test program was still not right -- the inputs list was missing almost all the loopback devices, and the one it found (setup by pw-loopback) was named incorrectly.
-
I found the difference. In Qt 6.10.1
eab27c5cbd src/multimedia/pulseaudio/qaudioengine_pulse.cpp (Mikko Hallamaa 2024-03-22 16:47:14 +0100 257) } ^2a34e88c1 src/plugins/pulseaudio/qpulseaudioengine.cpp (Michael Goddard 2011-06-29 13:38:46 +1000 258) 85e2f9712f src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp (Lars Knoll 2021-01-13 15:39:29 +0100 259) // skip monitor channels 85e2f9712f src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp (Lars Knoll 2021-01-13 15:39:29 +0100 260) if (info->monitor_of_sink != PA_INVALID_INDEX) 85e2f9712f src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp (Lars Knoll 2021-01-13 15:39:29 +0100 261) return; 7b75983575 src/multimedia/pulseaudio/qaudioengine_pulse.cpp (Artem Dyomin 2023-06-07 14:46:36 +0200 262)Qt5 lists the monitor devices. Ignoring monitor devices means that devices created like this:
pactl load-module module-null-sink sink_name=RadioOutput sink_properties=device.description="RadioOutput"Used to show up as "RadioOutput.monitor" from QAudioDeviceInfo::availableDevices(Audio::AudioInput).
This created a sink device called "RadioOutput" where the radio would send its output audio stream. The modem would listen on "RadioOutput.monitor."
The workaround is to use the pact remap module
pactl load-module module-remap-source master=RadioOutput.monitor source_name="FromRadio" source_properties=device.description=FromRadioin addition to the module-null-sink step.
This still leaves the question as to why Qt6 wants to ignore monitor devices? This breaks backward compatibility at the user level.
From what I can tell, this was introduced in v6.4.0 in src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp
As a workaround, (or adapting to the new reality) I've changed my loopback creator script to:
pactl load-module module-null-sink sink_name=RadioOutput \ sink_properties=device.description="RadioOutput" pactl load-module module-null-sink sink_name=ModemOutput \ sink_properties=device.description="ModemOutput" pactl load-module module-remap-source master=RadioOutput.monitor \ source_name="FromRadio" source_properties=device.description=FromRadio pactl load-module module-remap-source master=ModemOutput.monitor \ source_name="FromModem" source_properties=device.description="FromModem"What is the Qt6 developer position on breaking backward application user level compatibility?
-
Hi @radiogeek381,
What is the Qt6 developer position on breaking backward application user level compatibility?
Note that this is a user forum. You may ask this question on the development mailing list or create a bugreport about this. You can find links to both in my link collection.
Regards
-
aha_1980 Thank you. That will help.
I started here, rather than with a bug report, because I was pretty sure the problem was on my side. Despite my confidence in the previous note, I still don't have a solution - my experiments were against builds without PipeWire.Thank you for the link collection. When I've got this a little more solid, I'll look at the development mailing list.
-
Hi @radiogeek381,
What is the Qt6 developer position on breaking backward application user level compatibility?
Note that this is a user forum. You may ask this question on the development mailing list or create a bugreport about this. You can find links to both in my link collection.
Regards
@radiogeek381 said in qt6 QMediaDevices::audioInputs() does not return all input devices:
What is the Qt6 developer position on breaking backward application user level compatibility?
The position is they don't care:
https://qt-project.atlassian.net/browse/QTBUG-116015
https://qt-project.atlassian.net/browse/QTBUG-114846
https://qt-project.atlassian.net/browse/QTBUG-118766
https://qt-project.atlassian.net/browse/QTBUG-133298
https://qt-project.atlassian.net/browse/QTBUG-140658?focusedCommentId=2489187Also on Linux , Qt6 no longer works (probably since 6.7) with QT_MEDIA_BACKEND=gstreamer environment-variable set to select the legacy media backend, in case FFMPEG isn't working for you.