709 lines
21 KiB
C++
709 lines
21 KiB
C++
#include <backlasses.h>
|
|
#include <backfuncs.h>
|
|
|
|
EndpointNewSessionCallback::EndpointNewSessionCallback(EndpointHandler* eph){
|
|
this->eph = eph;
|
|
}
|
|
|
|
ULONG EndpointNewSessionCallback::AddRef(){
|
|
return InterlockedIncrement(&ref);
|
|
}
|
|
|
|
ULONG EndpointNewSessionCallback::Release(){
|
|
ULONG tempRef = InterlockedDecrement(&ref);
|
|
if (tempRef == 0) {
|
|
delete this;
|
|
}
|
|
return tempRef;
|
|
}
|
|
|
|
HRESULT EndpointNewSessionCallback::QueryInterface(REFIID riid, VOID **ppvInterface) {
|
|
if (IID_IUnknown == riid)
|
|
{
|
|
AddRef();
|
|
*ppvInterface = (IUnknown*)this;
|
|
}
|
|
else if (__uuidof(IAudioSessionNotification) == riid)
|
|
{
|
|
AddRef();
|
|
*ppvInterface = (IMMNotificationClient*)this;
|
|
}
|
|
else
|
|
{
|
|
*ppvInterface = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSession) {
|
|
if (eph->getFlow() == Flows::FLOW_CAPTURE) return S_OK;
|
|
|
|
HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
|
IAudioSessionControl2* sessionControl;
|
|
//ISimmpleAudioVolume* sessionVolume;
|
|
if (FAILED(NewSession->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl))) { log_wdebugcpp(L"no nueva sesion......"); };
|
|
if (sessionControl) {
|
|
sessionControl->AddRef();
|
|
//sessionControl->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&sessionVolume);
|
|
Session* newSession = new Session(this->eph->getEndpoint(), sessionControl);
|
|
eph->addSession(newSession);
|
|
}
|
|
|
|
if (result == S_OK)
|
|
CoUninitialize();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
EndpointVolumeCallback::EndpointVolumeCallback(Endpoint* ep){
|
|
this->ep = ep;
|
|
}
|
|
|
|
ULONG EndpointVolumeCallback::AddRef(){
|
|
return InterlockedIncrement(&ref);
|
|
}
|
|
|
|
ULONG EndpointVolumeCallback::Release(){
|
|
ULONG tempRef = InterlockedDecrement(&ref);
|
|
if (tempRef == 0) {
|
|
delete this;
|
|
}
|
|
return tempRef;
|
|
}
|
|
|
|
HRESULT EndpointVolumeCallback::QueryInterface(REFIID riid, VOID **ppvInterface) {
|
|
if (IID_IUnknown == riid)
|
|
{
|
|
AddRef();
|
|
*ppvInterface = (IUnknown*)this;
|
|
}
|
|
else if (__uuidof(IAudioEndpointVolumeCallback) == riid)
|
|
{
|
|
AddRef();
|
|
*ppvInterface = (IAudioEndpointVolumeCallback*)this;
|
|
}
|
|
else
|
|
{
|
|
*ppvInterface = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) {
|
|
if (pNotify == NULL) return E_INVALIDARG;
|
|
|
|
//delete osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller;
|
|
//osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.freeData4();
|
|
//Could've made a function or = override to hide this within Nguid, but back in cont = bad.
|
|
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data1 \
|
|
= pNotify->guidEventContext.Data1;
|
|
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \
|
|
= pNotify->guidEventContext.Data2;
|
|
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data3 \
|
|
= pNotify->guidEventContext.Data3;
|
|
for(int i = 0; i < 8 /* Data4 size */; i++){
|
|
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data4[i] = pNotify->guidEventContext.Data4[i];
|
|
}
|
|
|
|
//memcpy(&osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller, &pNotify->guidEventContext,sizeof(NGuid) );
|
|
Flows flow = this->ep->getFlow();
|
|
EndpointHandler* eph = nullptr;
|
|
if (flow & Flows::FLOW_PLAYBACK) {
|
|
eph = osh->getPlaybackEndpointHandlers().at(this->ep->getIndex());
|
|
} else {
|
|
eph = osh->getCaptureEndpointHandlers().at(this->ep->getIndex());
|
|
}
|
|
|
|
eph->getCallbackInfo()->muted = pNotify->bMuted;
|
|
eph->getCallbackInfo()->mainVolume = pNotify->fMasterVolume;
|
|
eph->getCallbackInfo()->channels = pNotify->nChannels;
|
|
|
|
|
|
UINT j = 0;
|
|
//todo: do while here caused stack corruption; sus
|
|
while(j < pNotify->nChannels) {
|
|
if (flow & Flows::FLOW_PLAYBACK)
|
|
eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j];
|
|
else
|
|
eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j];
|
|
j++;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* EndpointSituationCallback::EndpointSituationCallback(IMMDeviceEnumerator *deviceEnumerator, std::vector<Endpoint*> playbackDevices){
|
|
* this->deviceEnumerator = deviceEnumerator;
|
|
* this->playbackDevices = playbackDevices;
|
|
* }
|
|
*
|
|
*/
|
|
//todo: not on construct since it expects them to already exist; smells like refactor!
|
|
void EndpointSituationCallback::fill(IMMDeviceEnumerator *deviceEnumerator, std::vector<Endpoint*> playbackDevices, std::vector<Endpoint*> captureDevices){
|
|
this->deviceEnumerator = deviceEnumerator;
|
|
this->playbackDevices = playbackDevices;
|
|
this->captureDevices = captureDevices;
|
|
}
|
|
|
|
ULONG EndpointSituationCallback::AddRef(){
|
|
return InterlockedIncrement(&ref);
|
|
}
|
|
|
|
ULONG EndpointSituationCallback::Release(){
|
|
ULONG tempRef = InterlockedDecrement(&ref);
|
|
if (tempRef == 0) {
|
|
delete this;
|
|
}
|
|
return tempRef;
|
|
}
|
|
|
|
HRESULT EndpointSituationCallback::QueryInterface(REFIID riid, VOID **ppvInterface) {
|
|
if (IID_IUnknown == riid)
|
|
{
|
|
AddRef();
|
|
*ppvInterface = (IUnknown*)this;
|
|
}
|
|
else if (__uuidof(IMMNotificationClient) == riid)
|
|
{
|
|
AddRef();
|
|
*ppvInterface = (IMMNotificationClient*)this;
|
|
}
|
|
else
|
|
{
|
|
*ppvInterface = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT EndpointSituationCallback::OnDefaultDeviceChanged(EDataFlow flow, ERole role,LPCWSTR pwstrDeviceId) {
|
|
if (flow == EDataFlow::eCapture) return E_INVALIDARG;
|
|
|
|
Roles nRole;
|
|
switch (role) {
|
|
case ERole::eConsole:
|
|
nRole = Roles::ROLE_CONSOLE;
|
|
break;
|
|
case ERole::eMultimedia:
|
|
nRole = Roles::ROLE_MULTIMEDIA;
|
|
break;
|
|
case ERole::eCommunications:
|
|
nRole = Roles::ROLE_COMMUNICATIONS;
|
|
break;
|
|
}
|
|
std::wstring wstringEndpointId = pwstrDeviceId;
|
|
log_wdebugcpp(L"we got za defol 4 " + wstringEndpointId);
|
|
osh->changeFrontDefaultsCallback(nRole, wstringEndpointId);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT EndpointSituationCallback::OnDeviceAdded(LPCWSTR pwstrDeviceId) {
|
|
log_wdebugcpp(L"ayo we eventing za adin " + std::wstring(pwstrDeviceId));
|
|
return S_OK;
|
|
};
|
|
|
|
HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
|
|
log_wdebugcpp(L"ayo we eventing za rmovin " + std::wstring(pwstrDeviceId));
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
|
|
std::wstring endpointId = std::wstring(pwstrDeviceId);
|
|
switch (dwNewState){
|
|
case DEVICE_STATE_ACTIVE:
|
|
osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_ACTIVE);
|
|
break;
|
|
case DEVICE_STATE_DISABLED:
|
|
osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_DISABLED);
|
|
break;
|
|
case DEVICE_STATE_NOTPRESENT:
|
|
osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_NOTPRESENT);
|
|
break;
|
|
case DEVICE_STATE_UNPLUGGED:
|
|
osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_UNPLUGGED);
|
|
break;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
|
|
|
|
/*
|
|
* log_debugcpp(" -->Changed device property " +
|
|
* key.fmtid.Data1 + key.fmtid.Data2 + key.fmtid.Data3 + "\n" +
|
|
* key.fmtid.Data4[0]+ key.fmtid.Data4[1]+ "\n"+
|
|
* key.fmtid.Data4[2]+ key.fmtid.Data4[3] + "\n"+
|
|
* key.fmtid.Data4[4]+ key.fmtid.Data4[5] + "\n"+
|
|
* key.fmtid.Data4[6]+ key.fmtid.Data4[7]+ "\n"+
|
|
* " pid " + key.pid);
|
|
*/
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){
|
|
this->endpoint = ep;
|
|
this->idx = idx;
|
|
|
|
/*
|
|
* It can't multiflag, it's that stupid. MS momento.
|
|
* Only shows most relevant flag according to MS, i.e. 0110 sends 0010
|
|
*/
|
|
//todo: preguntitas owindows dword no es uint32_t even tho mingw mingas
|
|
if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-1);};
|
|
|
|
if(this->endpointState == EndpointState::ENDPOINT_ACTIVE) {
|
|
activateEndpointVolume();
|
|
}
|
|
|
|
reloadEndpointChannels();
|
|
|
|
/* todo: check header
|
|
* if(FAILED(endpoint->Activate(__uuidof(IAudioMeterInformation),
|
|
* CLSCTX_ALL, NULL, (void**)&endpointPeakMeter))) { log_debugcpp("peakbros..."); }
|
|
*/
|
|
|
|
//todo:: atexit into exit Gather ID
|
|
LPWSTR tempString = nullptr;
|
|
if (FAILED(endpoint->GetId(&tempString))) {exit(-1);};
|
|
endpointId = std::wstring(tempString);
|
|
log_wdebugcpp(endpointId);
|
|
CoTaskMemFree(tempString);
|
|
|
|
endpoint->OpenPropertyStore(STGM_READ, &properties);
|
|
PROPVARIANT pv;
|
|
properties->GetValue(PKEY_Device_FriendlyName , &pv);
|
|
if (pv.pwszVal == nullptr)
|
|
friendlyName = L"Unnamed Not Present Endpoint";
|
|
else
|
|
friendlyName = std::wstring(pv.pwszVal);
|
|
|
|
this->setFlow();
|
|
if (this->endpointState == EndpointState::ENDPOINT_ACTIVE && this->flow == Flows::FLOW_PLAYBACK) {
|
|
activateEndpointSessions();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Endpoint::Endpoint(IMMDevice* endpoint) : Endpoint(endpoint, 0) {};
|
|
*/
|
|
|
|
void Endpoint::activateEndpointSessions() {
|
|
//sessionManager;
|
|
if (FAILED(endpoint->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**) &sessionManager))) { log_wdebugcpp(L"sesionbros..."); return; }
|
|
|
|
IAudioSessionEnumerator* sessionEnumerator = nullptr;
|
|
if (FAILED(sessionManager->GetSessionEnumerator(&sessionEnumerator))) { log_wdebugcpp(L"sesEnumeratorBros..."); return; }
|
|
|
|
int sessionCount;
|
|
sessionEnumerator->GetCount(&sessionCount);
|
|
for (int i = 0; i < sessionCount; i++) {
|
|
IAudioSessionControl* sessionControlTmp;
|
|
sessionEnumerator->GetSession(i, (IAudioSessionControl**)&sessionControlTmp);
|
|
//todo:: asegurar lo del dynamic_cast
|
|
IAudioSessionControl2* sessionControl;
|
|
sessionControlTmp->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl);
|
|
sessionControl->AddRef();
|
|
sessionControlTmp->Release();
|
|
Session* session = new Session(this, sessionControl, (size_t)i);
|
|
endpointSessions.push_back(session);
|
|
}
|
|
sessionEnumerator->Release();
|
|
}
|
|
|
|
void Endpoint::addSession(Session* session) {
|
|
session->setIndex(this->getSessionCount());
|
|
endpointSessions.push_back(session);
|
|
}
|
|
|
|
void Endpoint::activateEndpointVolume() {
|
|
//bool extraThread = false;
|
|
/*
|
|
* Forgive me, for MS has sinned, and now I must too.
|
|
*/
|
|
if (this->endpointVolume == nullptr){
|
|
HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
|
endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&this->endpointVolume);
|
|
//if (endpointVolume == nullptr) { //why they returning 0 after dealing with the error jfc CO_E_NOTINITIALIZED) {
|
|
//CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
|
|
//extraThread = true;
|
|
//goto initialized;
|
|
//}
|
|
//log_debugcpp(std::string("no endpointVolume (IAudioEndpointVolume)"));
|
|
if (result == S_OK)
|
|
CoUninitialize();
|
|
}
|
|
}
|
|
|
|
void Endpoint::reloadEndpointChannels() {
|
|
if (this->endpointState == DEVICE_STATE_ACTIVE) {
|
|
if (FAILED(endpointVolume->GetChannelCount(&channelCount))) {log_debugcpp("get channel count fail");};/* */
|
|
}
|
|
}
|
|
|
|
void Endpoint::setIndex(uint64_t idx){
|
|
this->idx = idx;
|
|
}
|
|
|
|
uint64_t Endpoint::getIndex(){
|
|
return idx;
|
|
}
|
|
|
|
std::wstring Endpoint::getName(){
|
|
return friendlyName;
|
|
}
|
|
|
|
std::wstring Endpoint::getId(){
|
|
return endpointId;
|
|
}
|
|
|
|
float Endpoint::getVolume(int channel){
|
|
float volume;
|
|
if (channel == AudioChannel::CHANNEL_MAIN) {
|
|
if(FAILED(endpointVolume->GetMasterVolumeLevelScalar(&volume))) { /* log_debugcpp("si") */;}
|
|
} else {
|
|
if(FAILED(endpointVolume->GetChannelVolumeLevelScalar(channel, &volume))) { /* log_debugcpp("si"); */}
|
|
}
|
|
return volume;
|
|
}
|
|
|
|
uint32_t Endpoint::getChannelCount(){
|
|
return (uint32_t)channelCount;
|
|
}
|
|
|
|
|
|
bool Endpoint::getMute(){
|
|
BOOL mut;
|
|
if(FAILED(endpointVolume->GetMute(&mut))) { /* TIP: Below */ }
|
|
bool mute = (bool)mut;
|
|
return mute;
|
|
}
|
|
|
|
void Endpoint::setState(uint8_t state){
|
|
this->endpointState = state;
|
|
if(state == EndpointState::ENDPOINT_ACTIVE) {
|
|
this->activateEndpointVolume();
|
|
this->reloadEndpointChannels();
|
|
}
|
|
}
|
|
|
|
size_t Endpoint::getState(){
|
|
return this->endpointState;
|
|
}
|
|
|
|
void Endpoint::setVolume(NGuid guid, int channel, float volume) {
|
|
//TIP: There used to be log messages here. Now, it's a ghost town.
|
|
GUID tempMsGuid = NGuidToGUID(guid);
|
|
if (channel == AudioChannel::CHANNEL_MAIN) {
|
|
if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) {};
|
|
} else {
|
|
if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) {};
|
|
}
|
|
}
|
|
|
|
void Endpoint::setMute(NGuid guid, bool muted) {
|
|
GUID tempMsGuid = NGuidToGUID(guid);
|
|
if(FAILED(endpointVolume->SetMute(muted, &tempMsGuid))) { log_wdebugcpp(std::wstring(L"EndpointVolume null?")); };
|
|
}
|
|
|
|
void Endpoint::setVolumeCallback(EndpointVolumeCallback *epc){
|
|
if(endpointVolume == nullptr) {
|
|
this->activateEndpointVolume();
|
|
}
|
|
endpointVolume->RegisterControlChangeNotify((IAudioEndpointVolumeCallback*)epc);
|
|
}
|
|
|
|
void Endpoint::removeVolumeCallback(EndpointVolumeCallback *epc){
|
|
endpointVolume->UnregisterControlChangeNotify((IAudioEndpointVolumeCallback*)epc);
|
|
}
|
|
|
|
Roles Endpoint::getRoles(){
|
|
return this->endpointRoles;
|
|
}
|
|
|
|
void Endpoint::setRoles(Roles role){
|
|
//otro exe momento
|
|
STARTUPINFOEXW startupConfig;
|
|
PROCESS_INFORMATION processInfo;
|
|
SecureZeroMemory(&startupConfig, sizeof(STARTUPINFOEXW));
|
|
SecureZeroMemory(&startupConfig.StartupInfo, sizeof(STARTUPINFOW));
|
|
startupConfig.StartupInfo.cb = sizeof(STARTUPINFOEXW);
|
|
SecureZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
|
|
|
|
std::wstring command = L"SoundVolumeView.exe /SetDefault " + endpointId + L" ";
|
|
std::wstring troublePair = L"0";
|
|
switch (role) {
|
|
case Roles::ROLE_ALL:
|
|
/*
|
|
* console or multimedia, one sends both, at least for now;
|
|
* either cos of ms or dis guy;
|
|
* no choice but to treat them as one for now.
|
|
* command += L"all"; and nothing else would've been nice...
|
|
*/
|
|
troublePair = command + troublePair;
|
|
if(CreateProcessW(
|
|
NULL,
|
|
(wchar_t*)troublePair.c_str(),
|
|
NULL,
|
|
NULL,
|
|
false,
|
|
CREATE_UNICODE_ENVIRONMENT,
|
|
NULL,
|
|
NULL,
|
|
(LPSTARTUPINFOW)&startupConfig,
|
|
&processInfo
|
|
) == true) {
|
|
WaitForSingleObject(processInfo.hProcess, INFINITE );
|
|
CloseHandle(processInfo.hProcess);
|
|
CloseHandle(processInfo.hThread);
|
|
}
|
|
command += L"2";
|
|
break;
|
|
case Roles::ROLE_CONSOLE:
|
|
command += std::to_wstring(0);
|
|
break;
|
|
case Roles::ROLE_MULTIMEDIA:
|
|
command += std::to_wstring(1);
|
|
break;
|
|
case Roles::ROLE_COMMUNICATIONS:
|
|
command += std::to_wstring(2);
|
|
break;
|
|
}
|
|
|
|
if(CreateProcessW(
|
|
NULL,
|
|
(wchar_t*)command.c_str(),
|
|
NULL,
|
|
NULL,
|
|
false,
|
|
CREATE_UNICODE_ENVIRONMENT,
|
|
NULL,
|
|
NULL,
|
|
(LPSTARTUPINFOW)&startupConfig,
|
|
&processInfo
|
|
) == true) {
|
|
WaitForSingleObject(processInfo.hProcess, INFINITE );
|
|
CloseHandle(processInfo.hProcess);
|
|
CloseHandle(processInfo.hThread);
|
|
}
|
|
}
|
|
|
|
void Endpoint::assignRoles(Roles role){
|
|
Roles roles = (Roles)(endpointRoles | role);
|
|
this->endpointRoles = roles;
|
|
}
|
|
|
|
void Endpoint::removeRoles(Roles role){
|
|
Roles roles = (Roles)(endpointRoles ^ role);
|
|
this->endpointRoles = roles;
|
|
}
|
|
|
|
void Endpoint::setFlow() {
|
|
IMMEndpoint* flowGetter;
|
|
//this should be as simple as writing IID_IMMEndpoint, but it just won't find the macro, so I copied it. Sad.
|
|
GUID manual;
|
|
manual.Data1 = 0x1be09788;
|
|
manual.Data2 = 0x6894;
|
|
manual.Data3 = 0x4089;
|
|
manual.Data4[0] = 0x85;
|
|
manual.Data4[1] = 0x86;
|
|
manual.Data4[2] = 0x9a;
|
|
manual.Data4[3] = 0x2a;
|
|
manual.Data4[4] = 0x6c;
|
|
manual.Data4[5] = 0x26;
|
|
manual.Data4[6] = 0x5a;
|
|
manual.Data4[7] = 0xc5;
|
|
if(FAILED(this->endpoint->QueryInterface((const _GUID)manual, (void**)&flowGetter)))
|
|
{ log_debugcpp("no flow..."); }
|
|
EDataFlow MSflow;
|
|
HRESULT vafllar = flowGetter->GetDataFlow(&MSflow);
|
|
this->flow = (MSflow == EDataFlow::eRender ? Flows::FLOW_PLAYBACK : Flows::FLOW_CAPTURE);
|
|
flowGetter->Release();
|
|
}
|
|
|
|
Flows Endpoint::getFlow() {
|
|
return this->flow;
|
|
}
|
|
|
|
/* sessions */
|
|
std::vector<Session*> Endpoint::getSessions() {
|
|
return endpointSessions;
|
|
}
|
|
|
|
size_t Endpoint::getSessionCount() {
|
|
return endpointSessions.size();
|
|
}
|
|
|
|
Endpoint::~Endpoint(){
|
|
log_wdebugcpp(L"murio endpoint-san uwu");
|
|
properties->Release();
|
|
endpointVolume->Release();
|
|
endpoint->Release();
|
|
sessionManager->Release();
|
|
}
|
|
|
|
void Overseer::initCOMLibrary() {
|
|
OutputDebugStringW(L"EPWidget creation\n");
|
|
if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) {
|
|
log_debugcpp("si"); };
|
|
|
|
|
|
//Retrieving endpoint enumerator
|
|
//MMDeviceEnumerator es el CLSID de toda la vaina de MMDevicear
|
|
if(FAILED(CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL,
|
|
CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),
|
|
(void**)&deviceEnumerator)) )
|
|
{ log_debugcpp("si"); };
|
|
|
|
GUID tempGuid;
|
|
if(FAILED(CoCreateGuid(&tempGuid))) { log_debugcpp("Failed to obtain GUID: " ); };
|
|
//todo: wtf? why is it working? floats are ptrs...
|
|
this->guid = GUIDToNGuid(&tempGuid);
|
|
|
|
//if(FAILED(CoCreateInstance(__uuidof(CPolicyConfigClient),
|
|
// NULL, CLSCTX_ALL, __uuidof(IPolicyConfig10), (LPVOID *)&policyConfig))) {exit(-1);}
|
|
|
|
//TODO: Release lpguid?
|
|
//TODO: Uninitialize COM
|
|
}
|
|
|
|
void Overseer::reloadEndpoints(Flows flow) {
|
|
IMMDeviceCollection *deviceCollection;
|
|
unsigned int numEndpoints;
|
|
EDataFlow MSflow = (flow == Flows::FLOW_PLAYBACK ? EDataFlow::eRender : EDataFlow::eCapture);
|
|
// | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED
|
|
// NOTPRESENT shows a lot of garbage, unnamed devices.
|
|
if(FAILED(deviceEnumerator->EnumAudioEndpoints(MSflow, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED, &deviceCollection) ))
|
|
{ log_debugcpp("si"); };
|
|
|
|
/*
|
|
* Counting them
|
|
*/
|
|
if(FAILED(deviceCollection->GetCount(&numEndpoints))) { log_debugcpp("si");};
|
|
if(numEndpoints == 0) { log_debugcpp("si"); };
|
|
|
|
/*
|
|
* Retrieving actual endpoints and storing them on their own class
|
|
*/
|
|
IMMDevice *temp;
|
|
for (unsigned int i = 0; i < numEndpoints; i++){
|
|
if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); };
|
|
Endpoint *endpoint = new Endpoint(temp, i);
|
|
|
|
//endpoint->setIndex(i);
|
|
if (flow == Flows::FLOW_PLAYBACK)
|
|
this->playbackDevices.push_back(endpoint);
|
|
else
|
|
this->captureDevices.push_back(endpoint);
|
|
//TODO: le porblemx std::cout + "ola" + std::endl;
|
|
}
|
|
|
|
deviceCollection->Release();
|
|
|
|
/*
|
|
* Discerning default endpoints per role
|
|
* order: console, multimedia, communications
|
|
*/
|
|
for(int i = 0; i < ERole_enum_count; i++){
|
|
ERole val;
|
|
switch(i) {
|
|
case 0:
|
|
val = eConsole;
|
|
break;
|
|
case 1:
|
|
val = eMultimedia;
|
|
break;
|
|
case 2:
|
|
val = eCommunications;
|
|
break;
|
|
}
|
|
deviceEnumerator->GetDefaultAudioEndpoint(MSflow, val, &temp);
|
|
LPWSTR id = nullptr;
|
|
|
|
if (flow == Flows::FLOW_PLAYBACK) {
|
|
for (unsigned int j = 0; j < numEndpoints; j++) {
|
|
std::wstring eptId = playbackDevices.at(j)->getId();
|
|
temp->GetId(&id);
|
|
int comparison = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, eptId.c_str(), -987, id, -987, NULL, NULL, 0);
|
|
if (comparison - 2 == 0) {
|
|
log_wdebugcpp(L"ola defaul playback de "
|
|
+ std::to_wstring(i) + L" es " + id);
|
|
playbackDevices.at(j)->assignRoles((Roles)(1 << i));
|
|
}
|
|
}
|
|
} else {
|
|
for (unsigned int j = 0; j < numEndpoints; j++){
|
|
std::wstring eptId = captureDevices.at(j)->getId();
|
|
temp->GetId(&id);
|
|
int comparison = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, eptId.c_str(), -987, id, -987, NULL, NULL, 0);
|
|
if (comparison - 2 == 0) {
|
|
log_wdebugcpp(L"ola defaul capture de "
|
|
+ std::to_wstring(i) + L" es " + id);
|
|
captureDevices.at(j)->assignRoles((Roles)(1 << i));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Endpoint* Overseer::addEndpoint(std::wstring endpointId, /* out */Flows* flow = nullptr) {
|
|
IMMDevice* newep;
|
|
if(FAILED(deviceEnumerator->GetDevice((LPCWSTR)endpointId.c_str(), &newep)))
|
|
log_debugcpp("ay caramba con la hot metida.");
|
|
|
|
Endpoint *endpoint = new Endpoint(newep);
|
|
|
|
Flows getFlow = endpoint->getFlow();
|
|
if (getFlow == Flows::FLOW_PLAYBACK) {
|
|
endpoint->setIndex(osh->getPlaybackEndpointsCount());
|
|
this->playbackDevices.push_back(endpoint);
|
|
} else {
|
|
endpoint->setIndex(osh->getCaptureEndpointsCount());
|
|
this->captureDevices.push_back(endpoint);
|
|
}
|
|
if (flow != nullptr) *flow = getFlow;
|
|
return endpoint;
|
|
}
|
|
|
|
Overseer::Overseer() { //: epsc(deviceEnumerator, playbackDevices){
|
|
//Initializing COM library
|
|
log_debugcpp("Initializing Overseer");
|
|
initCOMLibrary();
|
|
|
|
//Obtaining playback endpoint collection on this point in time
|
|
reloadEndpoints(Flows::FLOW_PLAYBACK);
|
|
//reloadEndpoints(Flows::FLOW_CAPTURE);
|
|
|
|
//Registering for endpoint information callback
|
|
this->epsc.fill(deviceEnumerator, playbackDevices, captureDevices);
|
|
if(FAILED(deviceEnumerator->RegisterEndpointNotificationCallback(((IMMNotificationClient*)&epsc)))) { log_debugcpp("when no enchufas......"); }
|
|
}
|
|
|
|
NGuid Overseer::getGuid() {
|
|
return guid;
|
|
}
|
|
|
|
std::vector<Endpoint*> Overseer::getPlaybackEndpoints() {
|
|
return playbackDevices;
|
|
}
|
|
|
|
std::vector<Endpoint*> Overseer::getCaptureEndpoints() {
|
|
return captureDevices;
|
|
}
|
|
|
|
Overseer::~Overseer(){
|
|
log_debugcpp("cum");
|
|
deviceEnumerator->Release();
|
|
for(unsigned long long i = 0; i < playbackDevices.size(); i++){
|
|
delete(playbackDevices.at(i));
|
|
}
|
|
}
|
|
|
|
//int Overseer::getCaptureEndpoints(std::vector<Endpoint*> *captureEndpoints);
|
|
|
|
//IMMDeviceEnumerator** Overseer::setOrigin();
|
|
|