Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more WASAPI functions, interfaces and constants #800

Merged
merged 16 commits into from
Dec 20, 2023
Merged

Add more WASAPI functions, interfaces and constants #800

merged 16 commits into from
Dec 20, 2023

Conversation

SirusDoma
Copy link
Contributor

Add more WASAPI functions, interfaces, and constants.
Fix: #513

example/wasapi.dart Outdated Show resolved Hide resolved
@halildurmus halildurmus self-requested a review December 12, 2023 19:00
@SirusDoma
Copy link
Contributor Author

A bit side-tracked but after testing these API in some of my small projects, I ran into an issue when using IAudioCaptureClient.
Quoting from MSDN docs:

When releasing an IAudioCaptureClient interface instance, the client must call the Release method of the instance from the same thread as the call to IAudioClient::GetService that created the object.

I couldn't find a way to do this in Flutter. Every time the code executes from a button click, the 2 different methods of the same object seem to run under a different native thread leading to segfault / silent crash. My temporary solution is to let this capture client pointer leaking to avoid the crash.. Which is far more than ideal.

Any ideas on how to do this? I reckon I could use a native thread via CreateThread and call the GetService and Release under the same thread, but that would be complicated to do.

@halildurmus
Copy link
Member

halildurmus commented Dec 16, 2023

A bit side-tracked but after testing these API in some of my small projects, I ran into an issue when using IAudioCaptureClient. Quoting from MSDN docs:

When releasing an IAudioCaptureClient interface instance, the client must call the Release method of the instance from the same thread as the call to IAudioClient::GetService that created the object.

I couldn't find a way to do this in Flutter. Every time the code executes from a button click, the 2 different methods of the same object seem to run under a different native thread leading to segfault / silent crash. My temporary solution is to let this capture client pointer leaking to avoid the crash.. Which is far more than ideal.

Any ideas on how to do this? I reckon I could use a native thread via CreateThread and call the GetService and Release under the same thread, but that would be complicated to do.

Finalizers are attached to the COM objects in this package, which decrement the reference count of the object and then free its pointer (see here) when the objects go out of scope (as mentioned in the docs). Therefore, you should not free the pointers of these objects unless you're opting out of this behavior by calling the .detach() method of the object.

Edit: I'll review this PR in a few days, I'm a little busy at the moment.

@SirusDoma
Copy link
Contributor Author

SirusDoma commented Dec 16, 2023

Finalizers are attached to the COM objects in this package, which decrement the reference count of the object and then free its pointer (see here) when the objects go out of scope (as mentioned in the docs). Therefore, you should not free the pointers of these objects unless you're opting out of this behavior by calling the .detach() method of the object.

Yes, I'm completely aware of what you wrote here. However, it doesn't matter if I let the finalizer run (e.g class that contains the IAudioCaptureClient / COM object went out of scope) or detach the pointer from the flutter object and freeing the object by myself: It always leads to segfault/crash because I think internally runs in a different native thread than the one it used to instantiate the object.

The problem isn't likely to be reproducible by example code where everything happens in a single method (eg. init -> render/capture -> object being freed due to out-of-scope at the same method), but it happens to me in a flutter project where init, capture and free/dispose happen within different methods (e.g initState() for init, capture after user-click and/or dispose when widget that contains the COM object no longer active / being rendered / out-of-scope).

Edit: I'll review this PR in a few days, I'm a little busy at the moment.

Please take your time, I'm using my local build for my project for now :)

@halildurmus
Copy link
Member

The problem isn't likely to be reproducible by example code where everything happens in a single method (eg. init -> render/capture -> object being freed due to out-of-scope at the same method), but it happens to me in a flutter project where init, capture and free/dispose happen within different methods (e.g initState() for init, capture after user-click and/or dispose when widget that contains the COM object no longer active / being rendered / out-of-scope).

If you can share an example of this, I'd be happy to look into it.

@SirusDoma
Copy link
Contributor Author

If you can share an example of this, I'd be happy to look into it.

Noted! I'll post a small reproducible flutter code/project later.

@SirusDoma
Copy link
Contributor Author

Hi, I'm so sorry that I haven't updated much yet. I've been busy lately.
Anyway, about the issue about releasing the COM Object, I think the issue lies in my capture codes and not in the flutter or thread stuff. I'm not absolutely certain and have yet to confirm this. I'll post the update once I find something.

P.S I liked your commit Add static methods to PROPERTYKEY struct, not sure why you revert it.

@halildurmus
Copy link
Member

P.S I liked your commit Add static methods to PROPERTYKEY struct, not sure why you revert it.

The commit caused some failures that I haven't been able to diagnose. I'll make another attempt tomorrow to identify and address the issues.

@halildurmus halildurmus added the enhancement New feature or request label Dec 20, 2023
Copy link
Member

@halildurmus halildurmus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you for your contribution!

I removed the ActivateAudioInterfaceAsync function and related COM interfaces as supporting asynchronous Win32 APIs requires some extra work and I don't have any plans to tackle this at the moment.

@halildurmus halildurmus merged commit 3b8fc97 into dart-windows:main Dec 20, 2023
4 checks passed
@SirusDoma
Copy link
Contributor Author

Sorry to bring this up again. There's no problem with releasing the COM object. It appears I'm using Isolate incorrectly.
Anyway, when is this going to be released?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missing property : PROPVARIANT.pwszVal
3 participants