SoundCard icon indicating copy to clipboard operation
SoundCard copied to clipboard

No error on bluetooth device disconnect using Linux

Open shawnc722 opened this issue 4 years ago • 4 comments

With audio playing out of the default speaker and a non-default bluetooth speaker connected, I recorded loopback from the default speaker and played it out of the bluetooth one. If I turn off the bluetooth speaker, no errors are thrown like they would be on Windows. Instead, soundcard starts playing the audio out of the default speaker, causing constantly increasing feedback. Using the opposite scenario, recording loopback from a bluetooth speaker and playing out of another one, works as you'd expect until the bluetooth speaker is disconnected. Then the _Microphone object switches to the default microphone, making the speaker play whatever the mic hears. This seems like unintended behaviour if not a bug. In windows, two errors will be thrown in the same situation: Error 0x88890004 and Error 0x100000001. Thanks for all your work on this project!

shawnc722 avatar Feb 15 '21 00:02 shawnc722

I think pulseaudio has a way of registering a callback for when devices change. But soundcard is currently not set up to handle such events, as you have noticed.

I'd be grateful for a pull request, if you'd like to look into this in more detail.

bastibe avatar Feb 17 '21 09:02 bastibe

Sorry in advance, I think this is probably a stupid question with a simple answer. I've made a branch with some changes that enable the callback you mentioned, and it can get the type of device (source/sink) and the type of event (add/remove/change), as well as the index of the device. I also added the ability to get a device by its index, and those parts both work with no issues. My problem is when I try to get a device from that callback function; any interaction with _pulse just crashes the program without any errors. I'm fairly certain it's something to do with threading, but I'm lost as to exactly what or how to get around that and I have a feeling it's a simple fix you've probably dealt with while creating the rest of the library. The relevant code starts at line 76 on https://github.com/shawnc722/SoundCard/blob/master/sc/pulseaudio.py. To get that crash, I try to access _pulse.sink_list from within the _context_subscription_callback() function and run testing.py to test. Also, I promise I'll clean up the code (and learn how to use git without changing a bunch of file names) before submitting any pull requests lol.

shawnc722 avatar Feb 27 '21 06:02 shawnc722

You probably have to lock the mainloop first.

Instead of calling your_function(...) directly, try calling _lock_and_block(your_function)(...).

bastibe avatar Mar 02 '21 14:03 bastibe

That was one of the first things I tried, but I got the same crash without an error. I narrowed down the cause of the error to the with self._lock_mainloop: part, so it seems to be the same issue of accessing any of _pulse’s functions that crashes it. In the meantime I’ve built a workaround that allows calling arbitrary functions by using a queue and an extra thread, but it seems to defeat the purpose of using a callback when the response is no longer immediate. Another solution I considered is to just throw a RuntimeError as soon as the current device changes, to match the windows behaviour, but I’ve found that raising an exception from within the callback can’t be captured by a client’s except because they’re on different threads.

I’ll try to figure out some more options once I have time to work on this again. Thanks for your suggestion!

shawnc722 avatar Mar 02 '21 16:03 shawnc722