1616_platform_audio_error : Optional [str ] = None
1717
1818
19+ def _dispose_track (track : rtc .Track ) -> None :
20+ """Release track handles created only for local PlatformAudio tests.
21+
22+ Note: Track doesn't have a public close() method yet, so we use the internal API.
23+ """
24+ track ._ffi_handle .dispose ()
25+
26+
1927def _check_platform_audio_available () -> tuple [bool , Optional [str ]]:
2028 """Check if PlatformAudio can be initialized on this system."""
2129 global _platform_audio_available , _platform_audio_error
@@ -27,8 +35,7 @@ def _check_platform_audio_available() -> tuple[bool, Optional[str]]:
2735 pa = rtc .PlatformAudio ()
2836 _platform_audio_available = True
2937 _platform_audio_error = None
30- # Keep reference to avoid cleanup issues
31- del pa
38+ pa .close ()
3239 except rtc .PlatformAudioError as e :
3340 _platform_audio_available = False
3441 _platform_audio_error = str (e )
@@ -60,8 +67,10 @@ def platform_audio():
6067 pytest .skip (f"PlatformAudio not available: { error } " )
6168
6269 pa = rtc .PlatformAudio ()
63- yield pa
64- # Cleanup handled by garbage collection
70+ try :
71+ yield pa
72+ finally :
73+ pa .close ()
6574
6675
6776class TestPlatformAudioCreation :
@@ -79,9 +88,12 @@ def test_platform_audio_multiple_instances(self, platform_audio):
7988 pytest .skip (f"PlatformAudio not available: { error } " )
8089
8190 pa2 = rtc .PlatformAudio ()
82- assert pa2 is not None
83- # Both should work
84- assert platform_audio is not None
91+ try :
92+ assert pa2 is not None
93+ # Both should work
94+ assert platform_audio is not None
95+ finally :
96+ pa2 .close ()
8597
8698
8799class TestDeviceEnumeration :
@@ -197,8 +209,11 @@ class TestAudioSourceCreation:
197209 def test_create_audio_source_default_options (self , platform_audio ):
198210 """Test creating an audio source with default options."""
199211 source = platform_audio .create_audio_source ()
200- assert source is not None
201- assert isinstance (source , rtc .PlatformAudioSource )
212+ try :
213+ assert source is not None
214+ assert isinstance (source , rtc .PlatformAudioSource )
215+ finally :
216+ source .close ()
202217
203218 def test_create_audio_source_custom_options (self , platform_audio ):
204219 """Test creating an audio source with custom options."""
@@ -209,8 +224,11 @@ def test_create_audio_source_custom_options(self, platform_audio):
209224 prefer_hardware = False ,
210225 )
211226 source = platform_audio .create_audio_source (options )
212- assert source is not None
213- assert isinstance (source , rtc .PlatformAudioSource )
227+ try :
228+ assert source is not None
229+ assert isinstance (source , rtc .PlatformAudioSource )
230+ finally :
231+ source .close ()
214232
215233 def test_create_audio_source_all_processing_disabled (self , platform_audio ):
216234 """Test creating an audio source with all processing disabled."""
@@ -220,24 +238,35 @@ def test_create_audio_source_all_processing_disabled(self, platform_audio):
220238 auto_gain_control = False ,
221239 )
222240 source = platform_audio .create_audio_source (options )
223- assert source is not None
241+ try :
242+ assert source is not None
243+ finally :
244+ source .close ()
224245
225246 def test_audio_source_has_handle (self , platform_audio ):
226247 """Test that created audio source has a valid internal handle."""
227248 source = platform_audio .create_audio_source ()
228- # The _handle property is used internally for track creation
229- assert hasattr (source , "_handle" )
230- assert source ._handle > 0
249+ try :
250+ # The _handle property is used internally for track creation
251+ assert hasattr (source , "_handle" )
252+ assert source ._handle > 0
253+ finally :
254+ source .close ()
231255
232256 def test_create_multiple_audio_sources (self , platform_audio ):
233257 """Test creating multiple audio sources from the same PlatformAudio."""
234258 source1 = platform_audio .create_audio_source ()
235- source2 = platform_audio .create_audio_source ()
236-
237- assert source1 is not None
238- assert source2 is not None
239- # Each source should have a unique handle
240- assert source1 ._handle != source2 ._handle
259+ source2 = None
260+ try :
261+ source2 = platform_audio .create_audio_source ()
262+ assert source1 is not None
263+ assert source2 is not None
264+ # Each source should have a unique handle
265+ assert source1 ._handle != source2 ._handle
266+ finally :
267+ source1 .close ()
268+ if source2 is not None :
269+ source2 .close ()
241270
242271
243272class TestPlatformAudioOptions :
@@ -291,8 +320,13 @@ class TestIntegrationWithTrack:
291320 def test_create_track_from_platform_audio_source (self , platform_audio ):
292321 """Test creating a LocalAudioTrack from PlatformAudioSource."""
293322 source = platform_audio .create_audio_source ()
294- track = rtc .LocalAudioTrack .create_audio_track ("test-mic" , source )
295-
296- assert track is not None
297- assert track .name == "test-mic"
298- assert track .kind == rtc .TrackKind .KIND_AUDIO
323+ track = None
324+ try :
325+ track = rtc .LocalAudioTrack .create_audio_track ("test-mic" , source )
326+ assert track is not None
327+ assert track .name == "test-mic"
328+ assert track .kind == rtc .TrackKind .KIND_AUDIO
329+ finally :
330+ if track is not None :
331+ _dispose_track (track )
332+ source .close ()
0 commit comments