Update of /cvsroot/audacity/lib-src/portmixer/src
In directory 
23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv14233/lib-src/portmixer/src

Modified Files:
        px_win_common.c px_win_common.h px_win_ds.c px_win_wmme.c 
Added Files:
        px_win_endpoint.c px_win_endpoint.h 
Log Message:
First try at getting volume mixers to work "properly" on Vista and 7.


Index: px_win_ds.c
===================================================================
RCS file: /cvsroot/audacity/lib-src/portmixer/src/px_win_ds.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- px_win_ds.c 12 Apr 2009 11:24:52 -0000      1.3
+++ px_win_ds.c 22 Nov 2009 12:46:11 -0000      1.4
@@ -135,13 +135,7 @@
          if (FAILED(hr)) {
             break;
          }
-
-         hr = mixerGetID((HMIXEROBJ) desc.WaveDeviceId,
-                         &deviceIn,
-                         MIXER_OBJECTF_WAVEIN);
-         if (hr != MMSYSERR_NOERROR) {
-           break;
-         }
+         deviceIn = desc.WaveDeviceId;
       }
    
       if (guidOut) {
@@ -158,13 +152,7 @@
          if (FAILED(hr)) {
             break;
          }
-
-         hr = mixerGetID((HMIXEROBJ) desc.WaveDeviceId,
-                         &deviceOut,
-                         MIXER_OBJECTF_WAVEOUT);
-         if (hr != MMSYSERR_NOERROR) {
-           break;
-         }
+         deviceOut = desc.WaveDeviceId;
       }
 
       if (open_mixers(Px, deviceIn, deviceOut))

Index: px_win_common.h
===================================================================
RCS file: /cvsroot/audacity/lib-src/portmixer/src/px_win_common.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- px_win_common.h     2 Oct 2006 00:27:52 -0000       1.1
+++ px_win_common.h     22 Nov 2009 12:46:11 -0000      1.2
@@ -68,6 +68,7 @@
 } PxInfo;
 
 int open_mixers(px_mixer *Px, UINT deviceIn, UINT deviceOut);
+int open_ep_mixers(px_mixer *Px, UINT deviceIn, UINT deviceOut);
 
 #ifdef __cplusplus
 }

--- NEW FILE: px_win_endpoint.h ---
#ifndef PX_WIN_COMMON_H
#define PX_WIN_COMMON_H
/*
 * PortMixer
 * Windows Common Header for Vista/7
 *
 * Copyright (c) 2002, 2009
 *
 * Written by Dominic Mazzoni
 *        and Leland Lucius
 *
 * PortMixer is intended to work side-by-side with PortAudio,
 * the Portable Real-Time Audio Library by Ross Bencina and
 * Phil Burk.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

typedef struct PxEPInfo
{
   IAudioEndpointVolume *inputEP;
   IAudioEndpointVolume *outputEP;
} PxEPInfo;

#ifdef __cplusplus
}
#endif
#endif

Index: px_win_common.c
===================================================================
RCS file: /cvsroot/audacity/lib-src/portmixer/src/px_win_common.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- px_win_common.c     13 Apr 2009 10:08:34 -0000      1.4
+++ px_win_common.c     22 Nov 2009 12:46:11 -0000      1.5
@@ -37,6 +37,7 @@
  */
 
 #include <windows.h>
+#include <tchar.h>
 
 #include "portaudio.h"
 
@@ -71,8 +72,26 @@
 {
    PxInfo*info;
    MMRESULT res;
+   OSVERSIONINFO verInfo;
 
-   if (deviceIn == UINT_MAX && deviceOut == UINT_MAX) {
+   memset(&verInfo, 0, sizeof(verInfo));
+   verInfo.dwOSVersionInfoSize = sizeof(verInfo);
+   GetVersionEx(&verInfo);
+   if (verInfo.dwMajorVersion >= 6) {
+      return open_ep_mixers(Px, deviceIn, deviceOut);
+   }
+
+   res = mixerGetID((HMIXEROBJ) (deviceIn == WAVE_MAPPER ? 0 : deviceIn),
+                    &deviceIn,
+                    MIXER_OBJECTF_WAVEIN);
+   if (res != MMSYSERR_NOERROR) {
+      return FALSE;
+   }
+
+   res = mixerGetID((HMIXEROBJ) (deviceOut == WAVE_MAPPER ? 0 : deviceOut),
+                    &deviceOut,
+                    MIXER_OBJECTF_WAVEIN);
+   if (res != MMSYSERR_NOERROR) {
       return FALSE;
    }
 

Index: px_win_wmme.c
===================================================================
RCS file: /cvsroot/audacity/lib-src/portmixer/src/px_win_wmme.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- px_win_wmme.c       5 Oct 2006 22:59:44 -0000       1.2
+++ px_win_wmme.c       22 Nov 2009 12:46:11 -0000      1.3
@@ -55,23 +55,22 @@
 
    hWaveIn = PaWinMME_GetStreamInputHandle(Px->pa_stream, 0);
    hWaveOut = PaWinMME_GetStreamOutputHandle(Px->pa_stream, 0);
-
    if (hWaveIn) {
-      res = mixerGetID((HMIXEROBJ) hWaveIn,
-                       &deviceIn,
-                       MIXER_OBJECTF_HWAVEIN);
+      res = waveInGetID(hWaveIn, &deviceIn);
       if (res != MMSYSERR_NOERROR) {
          return FALSE;
       }
    }
 
    if (hWaveOut) {
-      res = mixerGetID((HMIXEROBJ) hWaveOut,
-                       &deviceOut,
-                       MIXER_OBJECTF_HWAVEOUT);
+      res = waveOutGetID(hWaveOut, &deviceOut);
       if (res != MMSYSERR_NOERROR) {
          return FALSE;
       }
+
+      if (deviceOut == WAVE_MAPPER) {
+         deviceOut = 0;
+      }
    }
 
    if (open_mixers(Px, deviceIn, deviceOut)) {

--- NEW FILE: px_win_endpoint.c ---
/*
 * PortMixer
 * Common Windows routines for Vista/7
 *
 * Copyright (c) 2002, 2009
 *
 * Written by Dominic Mazzoni and Augustus Saunders
 *        and Leland Lucius
 *
 * PortMixer is intended to work side-by-side with PortAudio,
 * the Portable Real-Time Audio Library by Ross Bencina and
 * Phil Burk.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */
#define CINTERFACE 1
#define COBJMACROS 1

#include <initguid.h>
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>

#include "portaudio.h"

#include "portmixer.h"
#include "px_mixer.h"
#include "px_win_endpoint.h"

#if defined(_DEBUG)
#include <stdio.h>
#include <stdlib.h>
static void dprintf(const char *format, ...)
{
   char buf[4096];
   va_list args;
   int cnt;

   va_start(args, format);
   cnt = _vsnprintf(buf, sizeof(buf) - 1, format, args);
   va_end(args);

   if (cnt > 0) {
      buf[cnt] = '\0';
      OutputDebugString(buf);
   }
}
#endif

DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C,
            0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
DEFINE_GUID(IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35,
            0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
DEFINE_GUID(IID_IAudioEndpointVolume, 0x5CDF2C82, 0x841E, 0x4546,
            0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A);

#define DRV_RESERVED                      0x0800
#define DRV_QUERYFUNCTIONINSTANCEID       (DRV_RESERVED + 17)
#define DRV_QUERYFUNCTIONINSTANCEIDSIZE   (DRV_RESERVED + 18)

int open_ep_mixers(px_mixer *Px, UINT deviceIn, UINT deviceOut)
{
   PxEPInfo *info;
   IMMDeviceEnumerator *denum = NULL;
   IMMDevice *device = NULL;
   HRESULT hr;
   MMRESULT res;
   LPWSTR idStr;
   size_t idLen;

   if (!initialize(Px)) {
      goto fail;
   }

   info = (PxEPInfo *) Px->info;
   info->inputEP = NULL;
   info->outputEP = NULL;

   // Create an audio endpoint device enumerator.
   hr = CoCreateInstance(&CLSID_MMDeviceEnumerator,
                         NULL,
                         CLSCTX_ALL,
                         &IID_IMMDeviceEnumerator,
                         &denum);
   if (FAILED(hr)) {
      goto fail;
   }

   if (deviceIn == WAVE_MAPPER) {
      hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(denum,
                                                       eCapture,
                                                       eMultimedia,
                                                       &device);
      if (SUCCEEDED(hr)) {
         hr = IMMDevice_Activate(device,
                                 &IID_IAudioEndpointVolume,
                                 CLSCTX_ALL,
                                 NULL,
                                 &info->inputEP);
         IUnknown_Release(device);
      }

      if (FAILED(hr)) {
         goto fail;
      }
   }
   else {
      res = waveInMessage((HWAVEIN)IntToPtr(deviceIn),
                          DRV_QUERYFUNCTIONINSTANCEIDSIZE,
                          (DWORD_PTR)&idLen,
                          (DWORD_PTR)NULL);
      if (res != MMSYSERR_NOERROR) {
         goto fail;
      }

      idStr = (WCHAR *) CoTaskMemAlloc(idLen + sizeof(WCHAR));
      if (idStr == NULL) {
         goto fail;
      }

      res = waveInMessage((HWAVEIN)IntToPtr(deviceIn),
                          DRV_QUERYFUNCTIONINSTANCEID,
                          (DWORD_PTR)idStr,
                          (DWORD_PTR)idLen);
      if (res != MMSYSERR_NOERROR) {
         CoTaskMemFree(idStr);
         goto fail;
      }

      hr = IMMDeviceEnumerator_GetDevice(denum, idStr, &device);
      if (SUCCEEDED(hr)) {
         hr = IMMDevice_Activate(device,
                                 &IID_IAudioEndpointVolume,
                                 CLSCTX_ALL,
                                 NULL,
                                 &info->inputEP);
         IUnknown_Release(device);
      }

      CoTaskMemFree(idStr);

      if (FAILED(hr)) {
         goto fail;
      }
   }

   if (deviceIn == WAVE_MAPPER) {
      hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(denum,
                                                       eRender,
                                                       eMultimedia,
                                                       &device);
      if (SUCCEEDED(hr)) {
         hr = IMMDevice_Activate(device,
                                 &IID_IAudioEndpointVolume,
                                 CLSCTX_ALL,
                                 NULL,
                                 &info->outputEP);
         IUnknown_Release(device);
      }

      if (FAILED(hr)) {
         goto fail;
      }
   }
   else {
      res = waveOutMessage((HWAVEOUT)IntToPtr(deviceOut),
                           DRV_QUERYFUNCTIONINSTANCEIDSIZE,
                           (DWORD_PTR)&idLen,
                           (DWORD_PTR)NULL);
      if (res != MMSYSERR_NOERROR) {
         goto fail;
      }

      idStr = (WCHAR *) CoTaskMemAlloc(idLen + sizeof(WCHAR));
      if (idStr == NULL) {
         goto fail;
      }

      res = waveOutMessage((HWAVEOUT)IntToPtr(deviceOut),
                           DRV_QUERYFUNCTIONINSTANCEID,
                           (DWORD_PTR)idStr,
                           (DWORD_PTR)idLen);
      if (res != MMSYSERR_NOERROR) {
         CoTaskMemFree(idStr);
         goto fail;
      }

      hr = IMMDeviceEnumerator_GetDevice(denum, idStr, &device);
      if (SUCCEEDED(hr)) {
         hr = IMMDevice_Activate(device,
                                 &IID_IAudioEndpointVolume,
                                 CLSCTX_ALL,
                                 NULL,
                                 &info->outputEP);
         IUnknown_Release(device);
      }

      CoTaskMemFree(idStr);

      if (FAILED(hr)) {
         goto fail;
      }
   }

   return TRUE;

fail:
   if (denum) {
      IUnknown_Release(denum);
   }

   return cleanup(Px);
}


static int initialize(px_mixer *Px)
{
   Px->info = calloc(1, sizeof(PxEPInfo));
   if (Px->info == NULL) {
      return FALSE;
   }

   Px->CloseMixer = close_mixer;
//   Px->GetNumMixers = get_num_mixers;
//   Px->GetMixerName = get_mixer_name;
   Px->GetMasterVolume = get_master_volume;
   Px->SetMasterVolume = set_master_volume;
   Px->SupportsPCMOutputVolume = supports_pcm_output_volume;
   Px->GetPCMOutputVolume = get_pcm_output_volume;
   Px->SetPCMOutputVolume = set_pcm_output_volume;
   Px->GetNumOutputVolumes = get_num_output_volumes;
   Px->GetOutputVolumeName = get_output_volume_name;
   Px->GetOutputVolume = get_output_volume;
   Px->SetOutputVolume = set_output_volume;
   Px->GetNumInputSources = get_num_input_sources;
   Px->GetInputSourceName = get_input_source_name;
   Px->GetCurrentInputSource = get_current_input_source;
   Px->SetCurrentInputSource = set_current_input_source;
   Px->GetInputVolume = get_input_volume;
   Px->SetInputVolume = set_input_volume;
   
// Px->SupportsOutputBalance = supports_output_balance;
// Px->GetOutputBalance = get_output_balance;
// Px->SetOutputBalance = set_output_balance;
   
// Px->SupportsPlaythrough = supports_play_through;
// Px->GetPlaythrough = get_play_through;
// Px->SetPlaythrough = set_play_through;
   
   return TRUE;
}

static int cleanup(px_mixer *Px)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   if (info) {
      if (info->outputEP) {
         IUnknown_Release(info->outputEP);
      }

      if (info->inputEP) {
         IUnknown_Release(info->inputEP);
      }

      free(info);
      Px->info = NULL;
   }

   return FALSE;
}

static void close_mixer(px_mixer *Px)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   cleanup(Px);
}

static int get_num_mixers(px_mixer *Px)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   return 0;
}

static const char *get_mixer_name(px_mixer *Px, int i)
{
   return NULL;
}

static PxVolume VolumeFunction(HMIXEROBJ hMixer, DWORD controlID, PxVolume 
volume)
{
   MIXERCONTROLDETAILS details;
   MMRESULT result;
   MIXERCONTROLDETAILS_UNSIGNED value;

   if (hMixer == NULL) {
      return -1.0;
   }
   
   memset(&value, 0, sizeof(MIXERCONTROLDETAILS_UNSIGNED));
   
   details.cbStruct = sizeof(MIXERCONTROLDETAILS);
   details.dwControlID = controlID;
   details.cChannels = 1; /* all channels */
   details.cMultipleItems = 0;
   details.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
   details.paDetails = &value;

   if (volume < 0.0) {
      result = mixerGetControlDetails(hMixer,
                                      &details,
                                      MIXER_GETCONTROLDETAILSF_VALUE);
      if (result != MMSYSERR_NOERROR)
         return -1.0;
      
      return (PxVolume)(value.dwValue / 65535.0);
   }
   
   value.dwValue = (unsigned short)(volume * 65535.0);
   result = mixerSetControlDetails(hMixer,
                                   &details,
                                   MIXER_GETCONTROLDETAILSF_VALUE);
   
   if (result != MMSYSERR_NOERROR)
      return -1.0;
   
   return 0.0;
}

static PxVolume get_master_volume(px_mixer *Px)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;
   float volume = 0.0;

   IAudioEndpointVolume_GetMasterVolumeLevelScalar(info->outputEP,
                                                   &volume);

   return volume;
}

static void set_master_volume(px_mixer *Px, PxVolume volume)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   IAudioEndpointVolume_SetMasterVolumeLevelScalar(info->outputEP,
                                                   volume, 
                                                   NULL);
   
   return;
}

/*
|| Main output volume
*/

static int supports_pcm_output_volume(px_mixer *Px)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;
   
   return TRUE;
}

static PxVolume get_pcm_output_volume(px_mixer *Px)
{
   return get_master_volume(Px);
}

static void set_pcm_output_volume(px_mixer *Px, PxVolume volume)
{
   set_master_volume(Px, volume);

   return;
}

/*
|| Output info
*/

static int get_num_output_volumes(px_mixer *Px)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   return 1;
}

static const char *get_output_volume_name(px_mixer *Px, int i)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   return "PCM";
}

/*
|| Output volume
*/

static PxVolume get_output_volume(px_mixer *Px, int i)
{
   return get_master_volume(Px);
}

static void set_output_volume(px_mixer *Px, int i, PxVolume volume)
{
   set_master_volume(Px, volume);

   return;
}

/*
|| Input source
*/

static int get_num_input_sources(px_mixer *Px)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   return (info->inputEP ? 1 : 0);
}

static const char *get_input_source_name(px_mixer *Px, int i)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   return (info->inputEP ? "Master" : NULL);
}

static int get_current_input_source(px_mixer *Px)
{
   return 0;
}

static void set_current_input_source(px_mixer *Px, int i)
{
   return;
}

/*
|| Input volume
*/

static PxVolume get_input_volume(px_mixer *Px)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;
   float volume = 0.0;

   IAudioEndpointVolume_GetMasterVolumeLevelScalar(info->inputEP,
                                                   &volume);

   return volume;
}

static void set_input_volume(px_mixer *Px, PxVolume volume)
{
   PxEPInfo *info = (PxEPInfo *)Px->info;

   IAudioEndpointVolume_SetMasterVolumeLevelScalar(info->inputEP,
                                                   volume, 
                                                   NULL);
   
   return;
}


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Audacity-cvs mailing list
Audacity-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/audacity-cvs

Reply via email to