]> Repos - portaudio/commitdiff
hotplug dsound: initial cut of properly working connectionIds. it works. it pulls...
authorRoss Bencina <rossb@audiomulch.com>
Fri, 2 Sep 2016 15:57:29 +0000 (01:57 +1000)
committerRoss Bencina <rossb@audiomulch.com>
Fri, 2 Sep 2016 15:57:29 +0000 (01:57 +1000)
src/hostapi/dsound/pa_win_ds.c

index 43e56dcb3f045c775a63b1354eaaf75e6b4e8c57..a87bc666cc8bf19d4d1360eacfd03224439e646f 100644 (file)
@@ -676,7 +676,7 @@ static GUID pawin_IID_IKsPropertySet =
     property, and the other is using DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE.
     I tried both methods and only the second worked. I found two postings on the
     net from people who had the same problem with the first method, so I think the method used here is 
-    more common/likely to work. The probem is that IKsPropertySet_Get returns S_OK
+    more common/likely to work. The problem is that IKsPropertySet_Get returns S_OK
     but the fields of the device description are not filled in.
 
     The mechanism we use works by registering an enumeration callback which is called for 
@@ -993,7 +993,7 @@ static PaError AddOutputDeviceInfoFromDirectSound(
     }
 
     deviceInfo->name = name;
-    deviceInfo->connectionId = PaUtil_MakeDeviceConnectionId();
+    deviceInfo->connectionId = -1; /* initialized by caller */
 
     return result;
 
@@ -1163,7 +1163,7 @@ http://www.winehq.com/hypermail/wine-patches/2003/01/0290.html
     }
 
     deviceInfo->name = name;
-    deviceInfo->connectionId = PaUtil_MakeDeviceConnectionId();
+    deviceInfo->connectionId = -1; /* initialized by caller */
 
     return result;
 
@@ -1390,6 +1390,38 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
 }
 
 /***********************************************************************************/
+
+/* used for looking up existing devices to reuse their connectionId */
+static const PaDeviceInfo* FindDeviceInfo(
+        const PaDeviceInfo **deviceInfos, int deviceCount,
+        LPGUID lpGUID, int isInput )
+{
+    int i;
+
+#ifndef NDEBUG
+    if( deviceCount )
+    {
+        assert( deviceInfos != NULL );
+        assert( deviceInfos[0] != NULL );
+    }
+#endif
+
+    for( i = 0; i < deviceCount; ++i )
+    {
+        const PaDeviceInfo *deviceInfo = deviceInfos[i];
+        const PaWinDsDeviceInfo *dsDeviceInfo = (const PaWinDsDeviceInfo*)deviceInfo;
+        if( ((isInput && deviceInfo->maxInputChannels > 0)
+                || (!isInput && deviceInfo->maxOutputChannels > 0))
+            && ((lpGUID == NULL && dsDeviceInfo->lpGUID == NULL)
+                || (lpGUID != NULL && dsDeviceInfo->lpGUID != NULL && (memcmp(lpGUID, dsDeviceInfo->lpGUID, sizeof(GUID)) == 0))))
+        {
+            return deviceInfo;
+        }
+    }
+
+    return NULL;
+}
+
 static void FreeDeviceInfos( PaUtilAllocationGroup *allocations, PaDeviceInfo **deviceInfos )
 {
     if( deviceInfos )
@@ -1507,6 +1539,18 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
         for( i = 0 ; i < deviceNamesAndGUIDs.inputNamesAndGUIDs.count ; ++i )
         {
             PaWinDsDeviceInfo *winDsDeviceInfo = (PaWinDsDeviceInfo*)outArgument->deviceInfos[*newDeviceCount];
+            const PaDeviceInfo *currentDeviceInfo = FindDeviceInfo(
+                    hostApi->deviceInfos, hostApi->info.deviceCount,
+                    deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].lpGUID, /*isInput=*/1 );
+
+            /*
+            FIXME REVIEW
+                - we could also use deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].pnpInterface as parameter to FindDeviceInfo. I'm not sure whether that adds anything
+                - if currentDeviceInfo is non-NULL we could just copy the device info over instead of calling AddInputDeviceInfoFromDirectSoundCapture
+                    => make an assesment about whether any device info is likely to change
+                        - Channel count could change if speaker configuration changes
+                - if we're going to leave it the current way, then move call to FindDeviceInfo to only if AddInputDeviceInfoFromDirectSoundCapture succeeds
+            */
 
             result = AddInputDeviceInfoFromDirectSoundCapture( winDsDeviceInfo,
                     deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].name,
@@ -1514,6 +1558,11 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
                     deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].pnpInterface );
             if( result == paNoError )
             {
+                if (currentDeviceInfo)
+                    winDsDeviceInfo->inheritedDeviceInfo.connectionId = currentDeviceInfo->connectionId;
+                else
+                    winDsDeviceInfo->inheritedDeviceInfo.connectionId = PaUtil_MakeDeviceConnectionId();
+
                 if( deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].lpGUID == NULL )
                     outArgument->defaultInputDevice = *newDeviceCount;
                 (*newDeviceCount)++;
@@ -1524,6 +1573,9 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
         for( i = 0 ; i < deviceNamesAndGUIDs.outputNamesAndGUIDs.count ; ++i )
         {
             PaWinDsDeviceInfo *winDsDeviceInfo = (PaWinDsDeviceInfo*)outArgument->deviceInfos[*newDeviceCount];
+            const PaDeviceInfo *currentDeviceInfo = FindDeviceInfo(
+                    hostApi->deviceInfos, hostApi->info.deviceCount,
+                    deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].lpGUID, /*isInput=*/0 );
 
             result = AddOutputDeviceInfoFromDirectSound( winDsDeviceInfo,
                     deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].name,
@@ -1531,6 +1583,11 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
                     deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].pnpInterface );
             if( result == paNoError )
             {
+                if (currentDeviceInfo)
+                    winDsDeviceInfo->inheritedDeviceInfo.connectionId = currentDeviceInfo->connectionId;
+                else
+                    winDsDeviceInfo->inheritedDeviceInfo.connectionId = PaUtil_MakeDeviceConnectionId();
+
                 if( deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].lpGUID == NULL )
                     outArgument->defaultOutputDevice = *newDeviceCount;
                 (*newDeviceCount)++;