1
1
using System ;
2
- using System . Runtime . CompilerServices ;
3
2
using System . Runtime . InteropServices ;
4
3
using System . Threading ;
5
4
using System . Threading . Tasks ;
6
5
using NAudio . CoreAudioApi ;
7
- using NAudio . CoreAudioApi . Interfaces ;
8
6
using Windows . Media . Devices ;
9
- using NAudio . Utils ;
10
7
using NAudio . Wave . SampleProviders ;
11
8
12
9
namespace NAudio . Wave
@@ -99,32 +96,7 @@ public void SetClientProperties(bool useHardwareOffload, AudioStreamCategory cat
99
96
} ;
100
97
}
101
98
102
- private async Task Activate ( )
103
- {
104
- var icbh = new ActivateAudioInterfaceCompletionHandler (
105
- ac2 =>
106
- {
107
-
108
- if ( this . audioClientProperties != null )
109
- {
110
- IntPtr p = Marshal . AllocHGlobal ( Marshal . SizeOf ( this . audioClientProperties . Value ) ) ;
111
- Marshal . StructureToPtr ( this . audioClientProperties . Value , p , false ) ;
112
- ac2 . SetClientProperties ( p ) ;
113
- Marshal . FreeHGlobal ( p ) ;
114
- // TODO: consider whether we can marshal this without the need for AllocHGlobal
115
- }
116
99
117
- /*var wfx = new WaveFormat(44100, 16, 2);
118
- int hr = ac2.Initialize(AudioClientShareMode.Shared,
119
- AudioClientStreamFlags.EventCallback | AudioClientStreamFlags.NoPersist,
120
- 10000000, 0, wfx, IntPtr.Zero);*/
121
- } ) ;
122
- var IID_IAudioClient2 = new Guid ( "726778CD-F60A-4eda-82DE-E47610CD78AA" ) ;
123
- IActivateAudioInterfaceAsyncOperation activationOperation ;
124
- NativeMethods . ActivateAudioInterfaceAsync ( device , IID_IAudioClient2 , IntPtr . Zero , icbh , out activationOperation ) ;
125
- var audioClient2 = await icbh ;
126
- audioClient = new AudioClient ( ( IAudioClient ) audioClient2 ) ;
127
- }
128
100
129
101
private static string GetDefaultAudioEndpoint ( )
130
102
{
@@ -135,7 +107,7 @@ private static string GetDefaultAudioEndpoint()
135
107
136
108
private async void PlayThread ( )
137
109
{
138
- await Activate ( ) ;
110
+ audioClient = await AudioClient . ActivateAsync ( device , audioClientProperties ) ;
139
111
var playbackProvider = Init ( ) ;
140
112
bool isClientRunning = false ;
141
113
try
@@ -479,21 +451,6 @@ internal static extern IntPtr CreateEventExW(IntPtr lpEventAttributes, IntPtr lp
479
451
[ DllImport ( "api-ms-win-core-synch-l1-2-0.dll" , ExactSpelling = true , PreserveSig = true , SetLastError = true ) ]
480
452
public static extern int WaitForSingleObjectEx ( IntPtr hEvent , int milliseconds , bool bAlertable ) ;
481
453
482
- /// <summary>
483
- /// Enables Windows Store apps to access preexisting Component Object Model (COM) interfaces in the WASAPI family.
484
- /// </summary>
485
- /// <param name="deviceInterfacePath">A device interface ID for an audio device. This is normally retrieved from a DeviceInformation object or one of the methods of the MediaDevice class.</param>
486
- /// <param name="riid">The IID of a COM interface in the WASAPI family, such as IAudioClient.</param>
487
- /// <param name="activationParams">Interface-specific activation parameters. For more information, see the pActivationParams parameter in IMMDevice::Activate. </param>
488
- /// <param name="completionHandler"></param>
489
- /// <param name="activationOperation"></param>
490
- [ DllImport ( "Mmdevapi.dll" , ExactSpelling = true , PreserveSig = false ) ]
491
- public static extern void ActivateAudioInterfaceAsync (
492
- [ In , MarshalAs ( UnmanagedType . LPWStr ) ] string deviceInterfacePath ,
493
- [ In , MarshalAs ( UnmanagedType . LPStruct ) ] Guid riid ,
494
- [ In ] IntPtr activationParams , // n.b. is actually a pointer to a PropVariant, but we never need to pass anything but null
495
- [ In ] IActivateAudioInterfaceCompletionHandler completionHandler ,
496
- out IActivateAudioInterfaceAsyncOperation activationOperation ) ;
497
454
}
498
455
499
456
// trying some ideas from Lucian Wischik (ljw1004):
@@ -507,143 +464,7 @@ internal enum EventAccess
507
464
EVENT_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3
508
465
}
509
466
510
- internal class ActivateAudioInterfaceCompletionHandler :
511
- IActivateAudioInterfaceCompletionHandler , IAgileObject
512
- {
513
- private Action < IAudioClient2 > initializeAction ;
514
- private TaskCompletionSource < IAudioClient2 > tcs = new TaskCompletionSource < IAudioClient2 > ( ) ;
515
-
516
- public ActivateAudioInterfaceCompletionHandler (
517
- Action < IAudioClient2 > initializeAction )
518
- {
519
- this . initializeAction = initializeAction ;
520
- }
521
-
522
- public void ActivateCompleted ( IActivateAudioInterfaceAsyncOperation activateOperation )
523
- {
524
- // First get the activation results, and see if anything bad happened then
525
- int hr = 0 ;
526
- object unk = null ;
527
- activateOperation . GetActivateResult ( out hr , out unk ) ;
528
- if ( hr != 0 )
529
- {
530
- tcs . TrySetException ( Marshal . GetExceptionForHR ( hr , new IntPtr ( - 1 ) ) ) ;
531
- return ;
532
- }
533
-
534
- var pAudioClient = ( IAudioClient2 ) unk ;
535
-
536
- // Next try to call the client's (synchronous, blocking) initialization method.
537
- try
538
- {
539
- initializeAction ( pAudioClient ) ;
540
- tcs . SetResult ( pAudioClient ) ;
541
- }
542
- catch ( Exception ex )
543
- {
544
- tcs . TrySetException ( ex ) ;
545
- }
546
-
547
-
548
- }
549
-
550
-
551
- public TaskAwaiter < IAudioClient2 > GetAwaiter ( )
552
- {
553
- return tcs . Task . GetAwaiter ( ) ;
554
- }
555
- }
556
467
557
- [ ComImport , InterfaceType ( ComInterfaceType . InterfaceIsIUnknown ) , Guid ( "41D949AB-9862-444A-80F6-C261334DA5EB" ) ]
558
- interface IActivateAudioInterfaceCompletionHandler
559
- {
560
- //virtual HRESULT STDMETHODCALLTYPE ActivateCompleted(/*[in]*/ _In_
561
- // IActivateAudioInterfaceAsyncOperation *activateOperation) = 0;
562
- void ActivateCompleted ( IActivateAudioInterfaceAsyncOperation activateOperation ) ;
563
- }
564
-
565
-
566
- [ ComImport , InterfaceType ( ComInterfaceType . InterfaceIsIUnknown ) , Guid ( "72A22D78-CDE4-431D-B8CC-843A71199B6D" ) ]
567
- interface IActivateAudioInterfaceAsyncOperation
568
- {
569
- //virtual HRESULT STDMETHODCALLTYPE GetActivateResult(/*[out]*/ _Out_
570
- // HRESULT *activateResult, /*[out]*/ _Outptr_result_maybenull_ IUnknown **activatedInterface) = 0;
571
- void GetActivateResult ( [ Out ] out int activateResult ,
572
- [ Out , MarshalAs ( UnmanagedType . IUnknown ) ] out object activateInterface ) ;
573
- }
574
-
575
-
576
- [ ComImport , InterfaceType ( ComInterfaceType . InterfaceIsIUnknown ) , Guid ( "726778CD-F60A-4eda-82DE-E47610CD78AA" ) ]
577
- interface IAudioClient2
578
- {
579
- [ PreserveSig ]
580
- int Initialize ( AudioClientShareMode shareMode ,
581
- AudioClientStreamFlags streamFlags ,
582
- long hnsBufferDuration , // REFERENCE_TIME
583
- long hnsPeriodicity , // REFERENCE_TIME
584
- [ In ] WaveFormat pFormat ,
585
- [ In ] IntPtr audioSessionGuid ) ;
586
-
587
- // ref Guid AudioSessionGuid
588
-
589
- /// <summary>
590
- /// The GetBufferSize method retrieves the size (maximum capacity) of the endpoint buffer.
591
- /// </summary>
592
- int GetBufferSize ( out uint bufferSize ) ;
593
-
594
- [ return : MarshalAs ( UnmanagedType . I8 ) ]
595
- long GetStreamLatency ( ) ;
596
-
597
- int GetCurrentPadding ( out int currentPadding ) ;
598
-
599
- [ PreserveSig ]
600
- int IsFormatSupported (
601
- AudioClientShareMode shareMode ,
602
- [ In ] WaveFormat pFormat ,
603
- out IntPtr closestMatchFormat ) ;
604
-
605
- int GetMixFormat ( out IntPtr deviceFormatPointer ) ;
606
-
607
- // REFERENCE_TIME is 64 bit int
608
- int GetDevicePeriod ( out long defaultDevicePeriod , out long minimumDevicePeriod ) ;
609
-
610
- int Start ( ) ;
611
-
612
- int Stop ( ) ;
613
-
614
- int Reset ( ) ;
615
-
616
- int SetEventHandle ( IntPtr eventHandle ) ;
617
-
618
- /// <summary>
619
- /// The GetService method accesses additional services from the audio client object.
620
- /// </summary>
621
- /// <param name="interfaceId">The interface ID for the requested service.</param>
622
- /// <param name="interfacePointer">Pointer to a pointer variable into which the method writes the address of an instance of the requested interface. </param>
623
- [ PreserveSig ]
624
- int GetService ( [ In , MarshalAs ( UnmanagedType . LPStruct ) ] Guid interfaceId ,
625
- [ Out , MarshalAs ( UnmanagedType . IUnknown ) ] out object interfacePointer ) ;
626
-
627
- //virtual HRESULT STDMETHODCALLTYPE IsOffloadCapable(/*[in]*/ _In_
628
- // AUDIO_STREAM_CATEGORY Category, /*[in]*/ _Out_ BOOL *pbOffloadCapable) = 0;
629
- void IsOffloadCapable ( int category , out bool pbOffloadCapable ) ;
630
- //virtual HRESULT STDMETHODCALLTYPE SetClientProperties(/*[in]*/ _In_
631
- // const AudioClientProperties *pProperties) = 0;
632
- void SetClientProperties ( [ In ] IntPtr pProperties ) ;
633
- // TODO: try this: void SetClientProperties([In, MarshalAs(UnmanagedType.LPStruct)] AudioClientProperties pProperties);
634
- //virtual HRESULT STDMETHODCALLTYPE GetBufferSizeLimits(/*[in]*/ _In_
635
- // const WAVEFORMATEX *pFormat, /*[in]*/ _In_ BOOL bEventDriven, /*[in]*/
636
- // _Out_ REFERENCE_TIME *phnsMinBufferDuration, /*[in]*/ _Out_
637
- // REFERENCE_TIME *phnsMaxBufferDuration) = 0;
638
- void GetBufferSizeLimits ( IntPtr pFormat , bool bEventDriven ,
639
- out long phnsMinBufferDuration , out long phnsMaxBufferDuration ) ;
640
- }
641
-
642
- [ ComImport , InterfaceType ( ComInterfaceType . InterfaceIsIUnknown ) , Guid ( "94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90" ) ]
643
- interface IAgileObject
644
- {
645
-
646
- }
647
468
648
469
649
470
}
0 commit comments