SoundCard icon indicating copy to clipboard operation
SoundCard copied to clipboard

Runtime error 0x800401F0 when running from standalone .exe

Open Bob-Thomas opened this issue 4 years ago • 11 comments

Currently, using pyinstaller to build a onedir installation for my application that is using soundcard.

It all starts fine after adding the .h files but when I click my start recording button it throws a runtime error.

File "lib\site-packages\soundcard\mediafoundation.py", line 145, in get_microp hone                                                                               
File "lib\site-packages\soundcard\mediafoundation.py", line 127, in all_microp hones                                                                              
File "lib\site-packages\soundcard\mediafoundation.py", line 198, in __init__     File "lib\site-
packages\soundcard\mediafoundation.py", line 89, in check_error RuntimeError: Error 0x800401f0
--

It is something about the coInitialize but it sure looks like it actually gets set when I place a simple print at the line that does

hr = _combase.CoInitializeEx(_ffi.NULL, COINIT_MULTITHREADED) This error doesn't get thrown when running it as a python script it only happens when I run it from my standalone executable.

PS - Really amazing library that you build and a life saver

Bob-Thomas avatar Apr 23 '20 22:04 Bob-Thomas

PS - Really amazing library that you build and a life saver

Thank you!

Are you importing anything else besides SoundCard? CoInitializeEx can cause problems if other libraries are also interacting with ComBase. PyQt or PySide for example. I know that in PySide's case, the issue goes away if you switch the import order between PySide and SoundCard.

It might be that we would have to check if ComBase is already initialized, and only initialize if it isn't... or something like that. SoundCard was my first foray into Windows programming, and I am far from an expert.

bastibe avatar Apr 24 '20 07:04 bastibe

OOOh I am indeed using pyside that could be it.

Let me see if I can change the load order

Just tried it but no success. It is weird that it works when running it as python module but when I tried to run it as a packed executable it occurs

Bob-Thomas avatar Apr 24 '20 07:04 Bob-Thomas

Sorry, I told you the wrong thing.

I meant: import SoundCard only once the PySide application is running. That seemed to do the trick in a colleague's case.

bastibe avatar Apr 24 '20 08:04 bastibe

Hmmm alright let's see how I can do that since I use soundcard on multiple places

Bob-Thomas avatar Apr 24 '20 08:04 Bob-Thomas

Yes, it's not a great solution.

bastibe avatar Apr 24 '20 08:04 bastibe

Hmmm can't seem to get it to work? any way to check if combase is initialized.

I see that qt also gives the message that the rpc mode changed

Do you perhaps have an example from your colleague on how he fixed this?

Bob-Thomas avatar Apr 24 '20 10:04 Bob-Thomas

Alright, so I got it working the issue was that I am running the sound card library in a different thread that actually initialized it. So I needed to initialize the combase again inside the new thread.

I am using pywin32 for it with pythoncom.CoInitialize()

It seems to work flawlessly now

Bob-Thomas avatar Apr 24 '20 13:04 Bob-Thomas

Oh, interesting! Would you like to create a pull request that explains this in a quick note in the README?

bastibe avatar Apr 24 '20 18:04 bastibe

Sure thing but still confused why it does work when running it as a python script though but fails to work when running it as a standalone exe.

Went through a lot of stack overflow and I think a post that looks like https://stackoverflow.com/questions/3246525/why-cant-i-create-a-com-object-in-a-new-thread-in-python

Got me the actual answer but don't know the complete mechanics behind it but I will check if I can write something up with an example maybe fun for a blogpost of myself as well :D

Bob-Thomas avatar Apr 24 '20 18:04 Bob-Thomas

Thanks a lot @Bob-Thomas for the SO link provided, it solved my issue. For anyone stumbling here because of the RuntimeError: Error 0x800401f0, I had the issue because I was trying to use soundcard from a new python thread. I surrounded the soundcard bit of my thread function with CoInitializeEx(0) and CoUninitialize() and now it runs without problem.

from pythoncom import CoInitializeEx, CoUninitialize
import threading

def audio_streaming(_microphone):
    res = CoInitializeEx(0)
    voice_packets = []
    with _microphone.recorder(samplerate=8000) as mic:
        while push_to_talk:
            data = mic.record(numframes=160)
            voice_packets.append(data)
    CoUninitialize()

streaming_thread = threading.Thread(target=audio_streaming, args=(default_mic))  
streaming_thread.start()

Zeftow avatar May 25 '23 09:05 Zeftow

Would you like to create a pull request that explains the workaround in a quick note in the README?

bastibe avatar May 26 '23 12:05 bastibe