Thursday, July 23, 2015

Audio discoveries and problems

So I thought I would package Sidetone using PyInstaller, the latest version of which works so well with PPQT2. But strange things happen in the bundled version. The call to QAudioDeviceInfo.availableDevices(), which works perfectly running from source, returns an empty list to the bundled app. So both comboboxes are empty. Very appropriately, the empty comboboxes never generate a currentIndexChange signal, so the app never does anything (alos very appropriate).

I added code that, when the available list comes back empty, would get a one-item list of the device returned by QAudioDeviceInfo.defaultInputDevice() or QAudioDeviceInfo.defaultOutputDevice(). Because, the Qt docs assure me, "All platform and audio plugin implementations provide a default audio device to use." Which they do, but the devices being returned to the bundled app are invalid devices. They are QAudioInput or QAudioOutput objects, but they also return True from the .null() method, and when the app tries to start them, it generates a stderr message about trying to use a null device.

The code continues to run from source, but with this glitch. On my laptop—which is running the same levels of Mac OS, Python, Qt, and PyQt—when I unplug the USB headset, the app automatically switched to the built-in mic and speaker, and began an entertaining feedback warble. So I thought, OK, there must be some signal, some indication that a USB audio device has gone away. What is it?

But back on the desktop system, where I am doing the coding, things are different. There, when I pull the USB plug out, the app purrs on as if nothing had happened. I added code to intercept the stateChanged signal from the active devices and print the state. It goes from 3 (idle) to 0 (active) and stays there happily after the plug is pulled. And the system doesn't switch to the built-in devices. It is possible to select the built-in devices in Sidetone, and produce quite remarkable feedback effects, but it doesn't happen automatically on the desktop system.

I thought, OK, I'm plugging the headset into a USB hub. What if I put it directly into the back of the iMac? Something did change: the sound developed that "picket-fence" rattle indicating buffer under-run. I had to put the buffer size back up to 512 to eliminate it. Just speculating; the built-in USB delivers data faster than when the headset is on a hub, connected to the built-in hub? Don't care.

What did not change when I plugged into the built-in hub was the behavior when I pulled the plug out. No state change.

So I'm a kind of baffled on two points. One, how to know when the user yanks the plug on the device being used; and two, what is different about a bundled app than one running from source.

Neither is really important to my intended use (personal and casual). I'm cool running from source and I don't expect to be yanking the plug out in normal use. But I'd like to know. If you have any idea, please jump in with a comment.

No comments: