To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at https://github.com/sonic-visualiser/sv-dependency-builds .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / src / portaudio_20161030_catalina_patch / src / os / win / pa_win_wdmks_utils.c @ 164:9fa11135915a

History | View | Annotate | Download (11.3 KB)

1
/*
2
 * PortAudio Portable Real-Time Audio Library
3
 * Windows WDM KS utilities
4
 *
5
 * Copyright (c) 1999 - 2007 Andrew Baldwin, Ross Bencina
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining
8
 * a copy of this software and associated documentation files
9
 * (the "Software"), to deal in the Software without restriction,
10
 * including without limitation the rights to use, copy, modify, merge,
11
 * publish, distribute, sublicense, and/or sell copies of the Software,
12
 * and to permit persons to whom the Software is furnished to do so,
13
 * subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be
16
 * included in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26

    
27
/*
28
 * The text above constitutes the entire PortAudio license; however, 
29
 * the PortAudio community also makes the following non-binding requests:
30
 *
31
 * Any person wishing to distribute modifications to the Software is
32
 * requested to send the modifications to the original developer so that
33
 * they can be incorporated into the canonical version. It is also 
34
 * requested that these non-binding requests be included along with the 
35
 * license above.
36
 */
37

    
38
#include <windows.h>
39
#include <mmreg.h>
40
#ifndef WAVE_FORMAT_IEEE_FLOAT
41
    #define WAVE_FORMAT_IEEE_FLOAT 0x0003   // MinGW32 does not define this
42
#endif    
43
#ifndef _WAVEFORMATEXTENSIBLE_
44
    #define _WAVEFORMATEXTENSIBLE_          // MinGW32 does not define this
45
#endif
46
#ifndef _INC_MMREG
47
    #define _INC_MMREG                      // for STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
48
#endif
49
#include <winioctl.h>                                                // MinGW32 does not define this automatically
50

    
51
#if defined(__GNUC__)
52

    
53
#include "../../hostapi/wasapi/mingw-include/ks.h"
54
#include "../../hostapi/wasapi/mingw-include/ksmedia.h"
55

    
56
#else
57

    
58
#include <ks.h>
59
#include <ksmedia.h>
60

    
61
#endif
62

    
63
#include <stdio.h>                          // just for some development printfs
64

    
65
#include "portaudio.h"
66
#include "pa_util.h"
67
#include "pa_win_wdmks_utils.h"
68

    
69

    
70
/* PortAudio-local instances of GUIDs previously sourced from ksguid.lib */
71

    
72
/* GUID KSDATAFORMAT_TYPE_AUDIO */
73
static const GUID pa_KSDATAFORMAT_TYPE_AUDIO = { STATIC_KSDATAFORMAT_TYPE_AUDIO };
74

    
75
/* GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT */
76
static const GUID pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT };
77

    
78
/* GUID KSDATAFORMAT_SUBTYPE_PCM */
79
static const GUID pa_KSDATAFORMAT_SUBTYPE_PCM = { STATIC_KSDATAFORMAT_SUBTYPE_PCM };
80

    
81
/* GUID KSDATAFORMAT_SUBTYPE_WAVEFORMATEX */
82
static const GUID pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX = { STATIC_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX };
83

    
84
/* GUID KSMEDIUMSETID_Standard */
85
static const GUID pa_KSMEDIUMSETID_Standard = { STATIC_KSMEDIUMSETID_Standard };
86

    
87
/* GUID KSINTERFACESETID_Standard */
88
static const GUID pa_KSINTERFACESETID_Standard = { STATIC_KSINTERFACESETID_Standard };
89

    
90
/* GUID KSPROPSETID_Pin */
91
static const GUID pa_KSPROPSETID_Pin = { STATIC_KSPROPSETID_Pin };
92

    
93
#define pa_IS_VALID_WAVEFORMATEX_GUID(Guid)\
94
    (!memcmp(((PUSHORT)&pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX) + 1, ((PUSHORT)(Guid)) + 1, sizeof(GUID) - sizeof(USHORT)))
95

    
96

    
97
static PaError WdmGetPinPropertySimple(
98
    HANDLE  handle,
99
    unsigned long pinId,
100
    unsigned long property,
101
    void* value,
102
    unsigned long valueSize )
103
{
104
    DWORD bytesReturned;
105
    KSP_PIN ksPProp;
106
    ksPProp.Property.Set = pa_KSPROPSETID_Pin;
107
    ksPProp.Property.Id = property;
108
    ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
109
    ksPProp.PinId = pinId;
110
    ksPProp.Reserved = 0;
111

    
112
    if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp, sizeof(KSP_PIN),
113
            value, valueSize, &bytesReturned, NULL ) == 0 || bytesReturned != valueSize )
114
    {
115
        return paUnanticipatedHostError;
116
    }
117
    else
118
    {
119
        return paNoError;
120
    }
121
}
122

    
123

    
124
static PaError WdmGetPinPropertyMulti(
125
    HANDLE handle,
126
    unsigned long pinId,
127
    unsigned long property,
128
    KSMULTIPLE_ITEM** ksMultipleItem)
129
{
130
    unsigned long multipleItemSize = 0;
131
    KSP_PIN ksPProp;
132
    DWORD bytesReturned;
133

    
134
    *ksMultipleItem = 0;
135

    
136
    ksPProp.Property.Set = pa_KSPROPSETID_Pin;
137
    ksPProp.Property.Id = property;
138
    ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
139
    ksPProp.PinId = pinId;
140
    ksPProp.Reserved = 0;
141

    
142
    if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp.Property,
143
            sizeof(KSP_PIN), NULL, 0, &multipleItemSize, NULL ) == 0 && GetLastError() != ERROR_MORE_DATA )
144
    {
145
        return paUnanticipatedHostError;
146
    }
147

    
148
    *ksMultipleItem = (KSMULTIPLE_ITEM*)PaUtil_AllocateMemory( multipleItemSize );
149
    if( !*ksMultipleItem )
150
    {
151
        return paInsufficientMemory;
152
    }
153

    
154
    if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp, sizeof(KSP_PIN),
155
            (void*)*ksMultipleItem,  multipleItemSize, &bytesReturned, NULL ) == 0 || bytesReturned != multipleItemSize )
156
    {
157
        PaUtil_FreeMemory( ksMultipleItem );
158
        return paUnanticipatedHostError;
159
    }
160

    
161
    return paNoError;
162
}
163

    
164

    
165
static int GetKSFilterPinCount( HANDLE deviceHandle )
166
{
167
    DWORD result;
168

    
169
    if( WdmGetPinPropertySimple( deviceHandle, 0, KSPROPERTY_PIN_CTYPES, &result, sizeof(result) ) == paNoError ){
170
        return result;
171
    }else{
172
        return 0;
173
    }
174
}
175

    
176

    
177
static KSPIN_COMMUNICATION GetKSFilterPinPropertyCommunication( HANDLE deviceHandle, int pinId )
178
{
179
    KSPIN_COMMUNICATION result;
180

    
181
    if( WdmGetPinPropertySimple( deviceHandle, pinId, KSPROPERTY_PIN_COMMUNICATION, &result, sizeof(result) ) == paNoError ){
182
        return result;
183
    }else{
184
        return KSPIN_COMMUNICATION_NONE;
185
    }
186
}
187

    
188

    
189
static KSPIN_DATAFLOW GetKSFilterPinPropertyDataflow( HANDLE deviceHandle, int pinId )
190
{
191
    KSPIN_DATAFLOW result;
192

    
193
    if( WdmGetPinPropertySimple( deviceHandle, pinId, KSPROPERTY_PIN_DATAFLOW, &result, sizeof(result) ) == paNoError ){
194
        return result;
195
    }else{
196
        return (KSPIN_DATAFLOW)0;
197
    }
198
}
199

    
200

    
201
static int KSFilterPinPropertyIdentifiersInclude( 
202
        HANDLE deviceHandle, int pinId, unsigned long property, const GUID *identifierSet, unsigned long identifierId  )
203
{
204
    KSMULTIPLE_ITEM* item = NULL;
205
    KSIDENTIFIER* identifier;
206
    int i;
207
    int result = 0;
208

    
209
    if( WdmGetPinPropertyMulti( deviceHandle, pinId, property, &item) != paNoError )
210
        return 0;
211
    
212
    identifier = (KSIDENTIFIER*)(item+1);
213

    
214
    for( i = 0; i < (int)item->Count; i++ )
215
    {
216
        if( !memcmp( (void*)&identifier[i].Set, (void*)identifierSet, sizeof( GUID ) ) &&
217
           ( identifier[i].Id == identifierId ) )
218
        {
219
            result = 1;
220
            break;
221
        }
222
    }
223

    
224
    PaUtil_FreeMemory( item );
225

    
226
    return result;
227
}
228

    
229

    
230
/* return the maximum channel count supported by any pin on the device. 
231
   if isInput is non-zero we query input pins, otherwise output pins.
232
*/
233
int PaWin_WDMKS_QueryFilterMaximumChannelCount( void *wcharDevicePath, int isInput )
234
{
235
    HANDLE deviceHandle;
236
        ULONG i;
237
    int pinCount, pinId;
238
    int result = 0;
239
    KSPIN_DATAFLOW requiredDataflowDirection = (isInput ? KSPIN_DATAFLOW_OUT : KSPIN_DATAFLOW_IN );
240
    
241
    if( !wcharDevicePath )
242
        return 0;
243

    
244
    deviceHandle = CreateFileW( (LPCWSTR)wcharDevicePath, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
245
    if( deviceHandle == INVALID_HANDLE_VALUE )
246
        return 0;
247

    
248
    pinCount = GetKSFilterPinCount( deviceHandle );
249
    for( pinId = 0; pinId < pinCount; ++pinId )
250
    {
251
        KSPIN_COMMUNICATION communication = GetKSFilterPinPropertyCommunication( deviceHandle, pinId );
252
        KSPIN_DATAFLOW dataflow = GetKSFilterPinPropertyDataflow( deviceHandle, pinId );
253
        if( ( dataflow == requiredDataflowDirection ) &&
254
                (( communication == KSPIN_COMMUNICATION_SINK) ||
255
                 ( communication == KSPIN_COMMUNICATION_BOTH)) 
256
             && ( KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, 
257
                    KSPROPERTY_PIN_INTERFACES, &pa_KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_STREAMING )
258
                || KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, 
259
                    KSPROPERTY_PIN_INTERFACES, &pa_KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_LOOPED_STREAMING ) )
260
             && KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, 
261
                    KSPROPERTY_PIN_MEDIUMS, &pa_KSMEDIUMSETID_Standard, KSMEDIUM_STANDARD_DEVIO ) )
262
         {
263
            KSMULTIPLE_ITEM* item = NULL;
264
            if( WdmGetPinPropertyMulti( deviceHandle, pinId, KSPROPERTY_PIN_DATARANGES, &item ) == paNoError )
265
            {
266
                KSDATARANGE *dataRange = (KSDATARANGE*)(item+1);
267

    
268
                for( i=0; i < item->Count; ++i ){
269

    
270
                    if( pa_IS_VALID_WAVEFORMATEX_GUID(&dataRange->SubFormat)
271
                            || memcmp( (void*)&dataRange->SubFormat, (void*)&pa_KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID) ) == 0
272
                            || memcmp( (void*)&dataRange->SubFormat, (void*)&pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID) ) == 0
273
                            || ( ( memcmp( (void*)&dataRange->MajorFormat, (void*)&pa_KSDATAFORMAT_TYPE_AUDIO, sizeof(GUID) ) == 0 )
274
                                && ( memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_WILDCARD, sizeof(GUID) ) == 0 ) ) )
275
                    {
276
                        KSDATARANGE_AUDIO *dataRangeAudio = (KSDATARANGE_AUDIO*)dataRange;
277
                        
278
                        /*
279
                        printf( ">>> %d %d %d %d %S\n", isInput, dataflow, communication, dataRangeAudio->MaximumChannels, devicePath );
280
                       
281
                        if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, sizeof(GUID) ) == 0 )
282
                            printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_WAVEFORMATEX\n" );
283
                        else if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_DSOUND, sizeof(GUID) ) == 0 )
284
                            printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_DSOUND\n" );
285
                        else if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_WILDCARD, sizeof(GUID) ) == 0 )
286
                            printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_WILDCARD\n" );
287
                        else
288
                            printf( "\tspecifier: ?\n" );
289
                        */
290

    
291
                        /*
292
                            We assume that very high values for MaximumChannels are not useful and indicate
293
                            that the driver isn't prepared to tell us the real number of channels which it supports.
294
                        */
295
                        if( dataRangeAudio->MaximumChannels  < 0xFFFFUL && (int)dataRangeAudio->MaximumChannels > result )
296
                            result = (int)dataRangeAudio->MaximumChannels;
297
                    }
298
                    
299
                    dataRange = (KSDATARANGE*)( ((char*)dataRange) + dataRange->FormatSize);
300
                }
301

    
302
                PaUtil_FreeMemory( item );
303
            }
304
        }
305
    }
306
    
307
    CloseHandle( deviceHandle );
308
    return result;
309
}