Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
# Conflicts:
#	Graphics/screenshot.png
#	README.md
  • Loading branch information
GoldenTao committed Apr 13, 2016
2 parents 9cc7a24 + 91dad39 commit d13ff8c
Show file tree
Hide file tree
Showing 44 changed files with 2,568 additions and 1,036 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -194,3 +194,5 @@ FakesAssemblies/

# Visual Studio 6 workspace options file
*.opt
/EarTrumpet.VC.VC.opendb
/EarTrumpet.VC.db
Binary file removed Build/Redists/vcredist_x86.exe
Binary file not shown.
154 changes: 154 additions & 0 deletions EarTrumpet.Interop/AudioDeviceService.cpp
@@ -0,0 +1,154 @@
#include "common.h"
#include "Mmdeviceapi.h"
#include "AudioDeviceService.h"
#include "Functiondiscoverykeys_devpkey.h"
#include "PolicyConfig.h"
#include "Propidl.h"
#include "Endpointvolume.h"

using namespace std;
using namespace std::tr1;
using namespace EarTrumpet::Interop;

AudioDeviceService* AudioDeviceService::__instance = nullptr;

void AudioDeviceService::CleanUpAudioDevices()
{
for (auto device = _devices.begin(); device != _devices.end(); device++)
{
CoTaskMemFree(device->Id);
CoTaskMemFree(device->DisplayName);
}

_devices.clear();
}

HRESULT AudioDeviceService::RefreshAudioDevices()
{
CleanUpAudioDevices();

CComPtr<IMMDeviceEnumerator> deviceEnumerator;
FAST_FAIL(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&deviceEnumerator)));

CComPtr<IMMDeviceCollection> deviceCollection;
FAST_FAIL(deviceEnumerator->EnumAudioEndpoints(EDataFlow::eRender, ERole::eMultimedia, &deviceCollection));

CComPtr<IMMDevice> defaultDevice;
FAST_FAIL(deviceEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eMultimedia, &defaultDevice));

CComHeapPtr<wchar_t> defaultDeviceId;
FAST_FAIL(defaultDevice->GetId(&defaultDeviceId));

UINT numDevices;
FAST_FAIL(deviceCollection->GetCount(&numDevices));

for (UINT i = 0; i < numDevices; i++)
{
CComPtr<IMMDevice> device;
if (FAILED(deviceCollection->Item(i, &device)))
{
continue;
}

CComHeapPtr<wchar_t> deviceId;
FAST_FAIL(device->GetId(&deviceId));

CComPtr<IPropertyStore> propertyStore;
FAST_FAIL(device->OpenPropertyStore(STGM_READ, &propertyStore));

PROPVARIANT friendlyName;
PropVariantInit(&friendlyName);
FAST_FAIL(propertyStore->GetValue(PKEY_Device_FriendlyName, &friendlyName));

CComPtr<IAudioEndpointVolume> audioEndpointVol;
FAST_FAIL(device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC, nullptr, reinterpret_cast<void**>(&audioEndpointVol)));

BOOL isMuted;
FAST_FAIL(audioEndpointVol->GetMute(&isMuted));

EarTrumpetAudioDevice audioDevice = {};
FAST_FAIL(SHStrDup(friendlyName.pwszVal, &audioDevice.DisplayName));
FAST_FAIL(SHStrDup(deviceId, &audioDevice.Id));
audioDevice.IsDefault = (wcscmp(defaultDeviceId, deviceId) == 0);
audioDevice.IsMuted = !!isMuted;
_devices.push_back(audioDevice);

PropVariantClear(&friendlyName);
}

return S_OK;
}

HRESULT AudioDeviceService::SetDefaultAudioDevice(LPWSTR deviceId)
{
CComPtr<IPolicyConfig> policyConfig;
FAST_FAIL(CoCreateInstance(__uuidof(CPolicyConfigClient), nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&policyConfig)));
return policyConfig->SetDefaultEndpoint(deviceId, ERole::eMultimedia);
}

HRESULT AudioDeviceService::GetDeviceByDeviceId(PWSTR deviceId, IMMDevice** device)
{
CComPtr<IMMDeviceEnumerator> deviceEnumerator;
FAST_FAIL(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&deviceEnumerator)));

return deviceEnumerator->GetDevice(deviceId, device);
}

HRESULT AudioDeviceService::GetAudioDeviceVolume(LPWSTR deviceId, float* volume)
{
CComPtr<IMMDevice> device;
FAST_FAIL(this->GetDeviceByDeviceId(deviceId, &device));

CComPtr<IAudioEndpointVolume> audioEndpointVol;
FAST_FAIL(device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC, nullptr, reinterpret_cast<void**>(&audioEndpointVol)));

return audioEndpointVol->GetMasterVolumeLevelScalar(volume);
}

HRESULT AudioDeviceService::SetAudioDeviceVolume(LPWSTR deviceId, float volume)
{
CComPtr<IMMDevice> device;
FAST_FAIL(this->GetDeviceByDeviceId(deviceId, &device));

CComPtr<IAudioEndpointVolume> audioEndpointVol;
FAST_FAIL(device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC, nullptr, reinterpret_cast<void**>(&audioEndpointVol)));

return audioEndpointVol->SetMasterVolumeLevelScalar(volume, nullptr);
}

HRESULT AudioDeviceService::GetAudioDevices(void** audioDevices)
{
if (_devices.size() == 0)
{
return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
}

*audioDevices = &_devices[0];
return S_OK;
}

HRESULT AudioDeviceService::SetMuteBoolForDevice(LPWSTR deviceId, BOOL value)
{
CComPtr<IMMDevice> device;
FAST_FAIL(this->GetDeviceByDeviceId(deviceId, &device));

CComPtr<IAudioEndpointVolume> audioEndpointVol;
FAST_FAIL(device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC, nullptr, reinterpret_cast<void**>(&audioEndpointVol)));

return audioEndpointVol->SetMute(value, nullptr);
}

HRESULT AudioDeviceService::MuteAudioDevice(LPWSTR deviceId)
{
return SetMuteBoolForDevice(deviceId, TRUE);
}

HRESULT AudioDeviceService::UnmuteAudioDevice(LPWSTR deviceId)
{
return SetMuteBoolForDevice(deviceId, FALSE);
}

int AudioDeviceService::GetAudioDeviceCount()
{
return _devices.size();
}
45 changes: 45 additions & 0 deletions EarTrumpet.Interop/AudioDeviceService.h
@@ -0,0 +1,45 @@
#pragma once

namespace EarTrumpet
{
namespace Interop
{
struct EarTrumpetAudioDevice
{
LPWSTR Id;
LPWSTR DisplayName;
bool IsDefault;
bool IsMuted;
};

class AudioDeviceService
{
private:
static AudioDeviceService* __instance;
std::vector<EarTrumpetAudioDevice> _devices;

void CleanUpAudioDevices();
HRESULT GetDeviceByDeviceId(PWSTR deviceId, IMMDevice** device);
HRESULT SetMuteBoolForDevice(LPWSTR deviceId, BOOL value);

public:
static AudioDeviceService* instance()
{
if (!__instance)
{
__instance = new AudioDeviceService;
}
return __instance;
}

HRESULT GetAudioDevices(void** audioDevices);
HRESULT GetAudioDeviceVolume(LPWSTR deviceId, float* volume);
HRESULT SetAudioDeviceVolume(LPWSTR deviceId, float volume);
HRESULT SetDefaultAudioDevice(LPWSTR deviceId);
HRESULT MuteAudioDevice(LPWSTR deviceId);
HRESULT UnmuteAudioDevice(LPWSTR deviceId);
HRESULT RefreshAudioDevices();
int GetAudioDeviceCount();
};
}
}

0 comments on commit d13ff8c

Please sign in to comment.