@@ -315,27 +315,30 @@ namespace vccli {
315315 EDataFlow defaultDevFlow{ deviceFlowFilter };
316316 if (defaultDevFlow == EDataFlow::eAll)
317317 defaultDevFlow = (defaultDevIsOutput ? EDataFlow::eRender : EDataFlow::eCapture);
318+
318319 deviceEnumerator->GetDefaultAudioEndpoint (defaultDevFlow, ERole::eMultimedia, &dev);
319320 deviceEnumerator->Release ();
320321 IAudioEndpointVolume* endpoint{};
321322 dev->Activate (__uuidof (IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL , (void **)&endpoint);
322- const auto & devName{ getDeviceFriendlyName (dev) };
323+ const auto & devName{ str::trim ( getDeviceFriendlyName (dev) ) };
323324 dev->Release ();
324325
325- return std::make_unique<EndpointVolume>(endpoint, devName, defaultDevFlow);
326- }
326+ return std::make_unique<EndpointVolume>(endpoint, devName, defaultDevFlow, true );
327+ } // Else we have an actual target ID to find
328+
329+ // Check if we have a valid PID
327330 std::optional<DWORD> target_pid;
328331 if (std::all_of (target_id.begin (), target_id.end (), str::stdpred::isdigit))
329332 target_pid = str::stoul (target_id);
330333
334+ // Enumerate all devices of the specified I/O type(s):
331335 IMMDeviceCollection* devices;
332336 deviceEnumerator->EnumAudioEndpoints (deviceFlowFilter, ERole::eMultimedia, &devices);
333337 deviceEnumerator->Release ();
334338
335339 UINT count;
336340 devices->GetCount (&count);
337341
338-
339342 for (UINT i{ 0u }; object == nullptr && i < count; ++i) {
340343 devices->Item (i, &dev);
341344
@@ -345,12 +348,13 @@ namespace vccli {
345348
346349 const auto & deviceName{ str::trim (getDeviceFriendlyName (dev)) };
347350
351+ // Check if this device is a match
348352 if (!target_pid.has_value () && (target_id_lower == str::tolower (deviceID) || target_id_lower == str::tolower (deviceName))) {
349353 IAudioEndpointVolume* endpointVolume{};
350354 dev->Activate (__uuidof (IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL , (void **)&endpointVolume);
351- object = std::make_unique<EndpointVolume>(endpointVolume, deviceName, getDeviceDataFlow (dev));
355+ object = std::make_unique<EndpointVolume>(endpointVolume, deviceName, getDeviceDataFlow (dev), isDefaultDevice (dev) );
352356 }
353- else {
357+ else { // Check for matching sessions on this device:
354358 IAudioSessionManager2* mgr{};
355359 dev->Activate (__uuidof (IAudioSessionManager2), 0 , NULL , (void **)&mgr);
356360
@@ -362,6 +366,7 @@ namespace vccli {
362366 IAudioSessionControl2* sessionControl2;
363367 ISimpleAudioVolume* sessionVolumeControl;
364368
369+ // Enumerate all audio sessions on this device:
365370 int sessionCount;
366371 sessionEnumerator->GetCount (&sessionCount);
367372
@@ -376,26 +381,48 @@ namespace vccli {
376381
377382 const auto & pname{ GetProcessNameFrom (pid) };
378383
384+ // Check if this session is a match:
379385 if ((pname.has_value () && target_id_lower == str::tolower (pname.value ())) || (target_pid.has_value () && target_pid.value () == pid)) {
380386 sessionControl2->QueryInterface <ISimpleAudioVolume>(&sessionVolumeControl);
381387 sessionControl2->Release ();
382388 object = std::make_unique<ApplicationVolume>(sessionVolumeControl, pname.value ());
383389 break ;
384390 }
385391 }
386-
387392 sessionEnumerator->Release ();
388393 }
389-
390394 dev->Release ();
391395 }
392396 devices->Release ();
393397
394- if (object == nullptr )
398+ if (object == nullptr ) // use a NullVolume struct instead of returning nullptr
395399 object = std::make_unique<NullVolume>(target_id);
396400
397401 return object;
398402 }
403+
404+ static bool isDefaultDevice (IMMDevice* dev)
405+ {
406+ const auto & devID{ getDeviceID (dev) };
407+ IMMDeviceEnumerator* deviceEnumerator{ getDeviceEnumerator () };
408+ bool isDefault{ false };
409+ IMMDevice* tmp;
410+ std::string tmpID{};
411+ deviceEnumerator->GetDefaultAudioEndpoint (EDataFlow::eRender, ERole::eMultimedia, &tmp);
412+ tmpID = getDeviceID (tmp);
413+ tmp->Release ();
414+ if (tmpID == devID)
415+ isDefault = true ;
416+ else {
417+ deviceEnumerator->GetDefaultAudioEndpoint (EDataFlow::eCapture, ERole::eMultimedia, &tmp);
418+ tmpID = getDeviceID (tmp);
419+ tmp->Release ();
420+ if (tmpID == devID)
421+ isDefault = true ;
422+ }
423+ deviceEnumerator->Release ();
424+ return isDefault;
425+ }
399426 /* *
400427 * @brief Resolves the given identifier to a process ID by searching for it in a snapshot.
401428 * @param identifier A process name or process ID.
0 commit comments