qtaudioembedded-linuxpulseaudioqtmultimedia

PulseAudioService pa_context_connect() failed in all Qt GUI applications


I have an embedded linux device that is running linux kernel 4.4 and QT5.9.1 with busybox. I have two applications written in QT, one with a GUI and another backend service also written in QT but has no GUI or widgets whatsoever, console only. I've recently been trying to pair and connect bluetooth audio devices to record and playback audio using pulseaudio and bluez. I also have a camera that records live video displayed on the GUI while recording audio from the bluetooth headset. This is done using gstreamer in the wirelesscontroller service.

This all works fine, but when going to play back saved videos with the audio I use the Video widget in the GUI to simplify things. Unfortunately it doesnt recognize the default audio device from pulseaudio as being the bluetooth headset/speaker and instead always forces it out of the 3.5mm audio jack. I tried using this code to print out the list of available audio devices as well as what QT thinks is the default audio device:

    const auto deviceInfos = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
    for (const QAudioDeviceInfo &deviceInfo : deviceInfos)
        qDebug() << "Device name: " << deviceInfo.deviceName();

    qWarning() << "default device: " << QAudioDeviceInfo::defaultOutputDevice().deviceName();

I originally tried this in the backend wirelesscontroller service and it prints this:

[M] qWirelessController WirelessControllerMain::init - Device name:  "default"
[M] qWirelessController WirelessControllerMain::init - Device name:  "default:CARD=rockchipwitorch"
[M] qWirelessController WirelessControllerMain::init - Device name:  "sysdefault:CARD=rockchipwitorch"
[M] qWirelessController WirelessControllerMain::init - Device name:  "bluez_sink.0C_A6_94_E4_22_B9.headset_head_unit"
[M] qWirelessController WirelessControllerMain::init - Device name:  "alsa_output.0.stereo-fallback"
[W] qWirelessController WirelessControllerMain::init - default device:  "bluez_sink.0C_A6_94_E4_22_B9.headset_head_unit"

So the backend service has no problem recognizing the default audio device. I tried adding this same code snippet to my GUI application and I get this error message:

[W] MyGUI  - PulseAudioService: pa_context_connect() failed with return: -1
[M] MyGUI HMIMain::init - Device name:  "default"
[M] MyGUI HMIMain::init - Device name:  "default:CARD=rockchipwitorch"
[M] MyGUI HMIMain::init - Device name:  "sysdefault:CARD=rockchipwitorch"
[M] MyGUI HMIMain::init - Device name:  ""
[W] MyGUI HMIMain::init - default device:  ""

It errors out trying to connect to the pulseaudio service. Ive searched a lot on this error and so far nothing ive found is either relevant to my setup or has fixed my issue. Ive also found that this error occurs on ALL GUI applications. I built a number of QT examples with and without GUIs and put that code snippet in them. All of the GUI applications give me the same pa_context_connect() error whereas all of the console based applications have no problem connecting with the pulse audio service.

From what I can tell, it does not matter how many QT console applications are running, they all are able to connect to the pulseaudio service. I've also made sure that no other user applications are running when trying to get my GUI application to connect with pulseaudio. Currently I'm starting pulseaudio with these parameters:

/usr/bin/pulseaudio -D --exit-idle-time=-1

I have tried launching it with the --system parameter as well as setting the environment variable PULSE_SERVER=localhost and both of those result in me getting the following error:

"PulseAudioService: Connection failure: Connection refused"

If I run pulseaudio in the background (not as a daemon) and --vvvv I see it print out a lot of information when my backend service connects to it but naturally, I see absolutely nothing when my GUI application attempts to connect to it.

I have also tried removing all my pulseaudio cookies in the .config/pulse/ folder as one thread suggested but that also didnt change anything.

As far as the configuration files in /etc/pulse/ I have reverted them all to stock. However, the only change I've had to make was adding "load-module module-stream-restore restore_device=false" to default.pa to get the default sink to maintain.

I really dont want to add more gstreamer code to play back videos so I would really like to figure out what is going on here.

EDIT: i recently found the environment variable "QT_DEBUG_PLUGINS" and launched my application with it set to one and got this output:

[M] MyGUI  - QFactoryLoader::QFactoryLoader() checking directory path "/usr/lib/qt/plugins/audio" ...
[M] MyGUI  - QFactoryLoader::QFactoryLoader() looking at "/usr/lib/qt/plugins/audio/libqtaudio_alsa.so"
[W] MyGUI  - Found metadata in lib /usr/lib/qt/plugins/audio/libqtaudio_alsa.so, metadata=
{
    "IID": "org.qt-project.qt.audiosystemfactory/5.0",
    "MetaData": {
        "Keys": [
            "alsa"
        ]
    },
    "className": "QAlsaPlugin",
    "debug": false,
    "version": 329988
}


[M] MyGUI  - Got keys from plugin meta data ("alsa")
[M] MyGUI  - QFactoryLoader::QFactoryLoader() looking at "/usr/lib/qt/plugins/audio/libqtmedia_pulse.so"
[W] MyGUI  - Found metadata in lib /usr/lib/qt/plugins/audio/libqtmedia_pulse.so, metadata=
{
    "IID": "org.qt-project.qt.audiosystemfactory/5.0",
    "MetaData": {
        "Keys": [
            "default"
        ]
    },
    "className": "QPulseAudioPlugin",
    "debug": false,
    "version": 329988
}


[M] MyGUI  - Got keys from plugin meta data ("default")
[M] MyGUI  - QFactoryLoader::QFactoryLoader() checking directory path "/mnt/app/bin/audio" ...
[M] MyGUI  - loaded library "/usr/lib/qt/plugins/audio/libqtaudio_alsa.so"
[M] MyGUI  - loaded library "/usr/lib/qt/plugins/audio/libqtmedia_pulse.so"
[W] MyGUI  - PulseAudioService: pa_context_connect() failed with return: -1
[M] MyGUI HMIMain::init - Device name:  "default"
[M] MyGUI HMIMain::init - Device name:  "default:CARD=rockchipwitorch"
[M] MyGUI HMIMain::init - Device name:  "sysdefault:CARD=rockchipwitorch"
[M] MyGUI HMIMain::init - Device name:  ""
[W] MyGUI HMIMain::init - default device:  ""

Solution

  • all credit to KH-219Design on the qt forums for his help on this.

    using the environment variable PULSE_LOG=4 I was able to diagnose that the GUI was using the XDG_RUNTIME_DIR to look for the pulse server socket. The XDG environment variable was being used for it to work with wayland which the console application didnt need.

    the pulse server socket was located in /tmp/pulse-/native and the GUI was not able to find it to connect to it because it was looking in /tmp/.xdg/pulse/native