You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
NAudio's COM interface declarations are classic [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]. Marshalling those depends on System.StubHelpers.InterfaceMarshaler in CoreLib, which the .NET 10 trimmer feature-switches out and prints IL2026: Built-in COM support is not trim compatible. PR #19 confirmed the runtime then throws TypeLoadException on the first MMDeviceEnumerator constructor call. This blocks the trimming follow-up in #21 alongside the own-code migration in #22.
Pairs with #22: even if our own COM declarations are migrated to [GeneratedComInterface], NAudio's classic-COM declarations would still keep System.StubHelpers.InterfaceMarshaler reachable and the trimmer would still strip it.
The remaining NAudio.Core + NAudio.Wasapi together are ~120 KB on disk, so the direct size payoff of dropping them is negligible. The win comes from unblocking trimming.
Problem
Earmark.AudiousesNAudio.CoreAudioApifor Core Audio device + session enumeration and change events:MMDeviceEnumerator,MMDevice,DataFlow,DeviceState,Role(device introspection / default-device queries) - src/Earmark.Audio/Services/AudioEndpointService.cs.AudioSessionManager,AudioSessionControl,IAudioSessionEventsHandler,AudioSessionState(per-session listing + change events) - src/Earmark.Audio/Services/AudioSessionService.cs.IMMNotificationClient(device add/remove/default-changed events).NAudio's COM interface declarations are classic
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]. Marshalling those depends onSystem.StubHelpers.InterfaceMarshalerin CoreLib, which the .NET 10 trimmer feature-switches out and printsIL2026: Built-in COM support is not trim compatible. PR #19 confirmed the runtime then throwsTypeLoadExceptionon the firstMMDeviceEnumeratorconstructor call. This blocks the trimming follow-up in #21 alongside the own-code migration in #22.Pairs with #22: even if our own COM declarations are migrated to
[GeneratedComInterface], NAudio's classic-COM declarations would still keepSystem.StubHelpers.InterfaceMarshalerreachable and the trimmer would still strip it.Proposed Solution
Two paths, in priority order:
netstandard2.0+UAP10.0.18362, so an upstream migration would have to multi-targetnet8.0+to get[GeneratedComInterface]. Slow path, depends on upstream maintainer bandwidth.[GeneratedComInterface]declarations. Roughly five COM interfaces plus IID/HResult/PROPVARIANT plumbing (the same pattern Migrate own classic-COM interop to ComWrappers (IPolicyConfigVista, IAudioPolicyConfigFactory) #22 establishes for our existing interop). Once Migrate own classic-COM interop to ComWrappers (IPolicyConfigVista, IAudioPolicyConfigFactory) #22 lands,Earmark.Audioalready has the ComWrappers strategy class and the helpers needed to do this in-tree.Recommendation: start path 1 (cost of one upstream issue), but plan on path 2 for actually unblocking #21 since upstream timing is uncertain.
Alternatives Considered
Additional Context
NAudio.Core+NAudio.Wasapitogether are ~120 KB on disk, so the direct size payoff of dropping them is negligible. The win comes from unblocking trimming.Checklist