wip: default callback

This commit is contained in:
Hane 2023-09-01 19:30:04 +02:00
commit 7f05cc09f6
7 changed files with 230 additions and 15 deletions

BIN
assets/SoundVolumeView.exe Normal file

Binary file not shown.

View file

@ -1,2 +1,4 @@
qmake -o build\Makefile .\qtest.pro
copy /Y /B .\assets\SoundVolumeView.exe .\build\debug
copy /Y /B .\assets\SoundVolumeView.exe .\build\release
mingw32-make.exe -C .\build -f Makefile

View file

@ -66,6 +66,124 @@ HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify
return S_OK;
}
/*
* EndpointSituationCallback::EndpointSituationCallback(IMMDeviceEnumerator *deviceEnumerator, std::vector<Endpoint*> playbackDevices){
* this->deviceEnumerator = deviceEnumerator;
* this->playbackDevices = playbackDevices;
* }
*/
void EndpointSituationCallback::fill(IMMDeviceEnumerator *deviceEnumerator, std::vector<Endpoint*> playbackDevices){
this->deviceEnumerator = deviceEnumerator;
this->playbackDevices = playbackDevices;
}
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;
}
osh
return S_OK;
}
HRESULT EndpointSituationCallback::OnDeviceAdded(LPCWSTR pwstrDeviceId) {
printf(" -->Added device\n");
return S_OK;
};
HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
printf(" -->Removed device\n");
return S_OK;
}
HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
/*
* char *pszState = "?????";
*
* switch (dwNewState)
* {
* case DEVICE_STATE_ACTIVE:
* pszState = "ACTIVE";
* break;
* case DEVICE_STATE_DISABLED:
* pszState = "DISABLED";
* break;
* case DEVICE_STATE_NOTPRESENT:
* pszState = "NOTPRESENT";
* break;
* case DEVICE_STATE_UNPLUGGED:
* pszState = "UNPLUGGED";
* break;
* }
*
* printf(" -->New device state is DEVICE_STATE_%s (0x%8.8x)\n",
* pszState, dwNewState);
*/
return S_OK;
}
HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
/*
* printf(" -->Changed device property "
* "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}#%d\n",
* key.fmtid.Data1, key.fmtid.Data2, key.fmtid.Data3,
* key.fmtid.Data4[0], key.fmtid.Data4[1],
* key.fmtid.Data4[2], key.fmtid.Data4[3],
* key.fmtid.Data4[4], key.fmtid.Data4[5],
* key.fmtid.Data4[6], key.fmtid.Data4[7],
* key.pid);
*/
return S_OK;
}
Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){
this->endpoint = ep;
this->idx = idx;
@ -168,7 +286,51 @@ uint8_t Endpoint::getRoles(){
return this->endpointRoles;
}
void Endpoint::setRoles(uint8_t role){
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));
//const wchar_t* pCrutch = crutch.c_str();
std::wstring command = L"SoundVolumeView.exe /SetDefault " + endpointId + L" ";
switch (role) {
case Roles::ROLE_ALL:
command += L"all";
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(uint8_t role){
//todo: operador virtuoso
uint8_t roles = endpointRoles | role;
this->endpointRoles = roles;
@ -252,30 +414,24 @@ void Overseer::reloadEndpoints() {
int comparison = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, eptId.c_str(), -987, id, -987, NULL, NULL, 0);
if (comparison - 2 == 0) {
log_wdebugcpp("ola defaul de " << i << " es " << id);
playbackDevices.at(j)->setRoles((1 << i));
playbackDevices.at(j)->assignRoles((1 << i));
}
//uint8_t debg = playbackDevices.at(j)->getRoles();
}
}
}
Overseer::Overseer(){
Overseer::Overseer() { //: epsc(deviceEnumerator, playbackDevices){
//Initializing COM library
log_debugcpp("Initializing Overseer");
initCOMLibrary();
//Obtaining playback endpoint collection on this point in time
reloadEndpoints();
this->epsc.fill(deviceEnumerator, playbackDevices);
if(FAILED(deviceEnumerator->RegisterEndpointNotificationCallback(((IMMNotificationClient*)&epsc)))) { log_debugcpp("when no enchufas......"); }
}
//Overseer::int getDefaultPlaybackEndpoint(Endpoint** defaultEndpoint){
//if (FAILED(deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &endpointPtr)))
// return 1;
//return 0;
//}
//int Overseer::getDefaultCaptureEndpoint(Endpoint** defaultEndpoint);
NGuid Overseer::getGuid() {
return guid;
}

View file

@ -6,6 +6,7 @@
//done by qt by def #define UNICODE
#include <Windows.h>
#include <processthreadsapi.h>
#include <mmdeviceapi.h>
#include <combaseapi.h>
#include <initguid.h>
@ -41,7 +42,8 @@ class Endpoint {
void setState(uint8_t state);
uint8_t getState();
uint8_t getRoles();
void setRoles(uint8_t role);
void setRoles(Roles role);
void assignRoles(uint8_t role);
std::wstring getId();
std::wstring getName();
void setVolumeCallback(EndpointVolumeCallback *epc);
@ -77,6 +79,25 @@ class EndpointVolumeCallback : public IAudioEndpointVolumeCallback {
Endpoint* ep;
};
class EndpointSituationCallback : public IMMNotificationClient {
public:
//EndpointSituationCallback(IMMDeviceEnumerator *deviceEnumerator, std::vector<Endpoint*> playbackDevices);
ULONG AddRef();
ULONG Release();
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
HRESULT OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId);
HRESULT OnDeviceAdded(LPCWSTR pwstrDeviceId);
HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId);
HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState);
HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key);
void fill(IMMDeviceEnumerator *deviceEnumerator, std::vector<Endpoint*> playbackDevices);
private:
ULONG ref = 1;
IMMDeviceEnumerator *deviceEnumerator;
std::vector<Endpoint*> playbackDevices;
};
class Overseer {
//TODO singleton?
public:
@ -84,6 +105,9 @@ class Overseer {
std::vector<Endpoint*> getPlaybackEndpoints();
void reloadEndpoints();
NGuid getGuid();
//void setEndpointStatusCallback();
//void setEndpointStatusCallback();
//~Overseer();
//int getDefaultPlaybackEndpoint(Endpoint** defaultEndpoint);
//int getDefaultCaptureEndpoint(Endpoint** defaultEndpoint);
@ -95,7 +119,8 @@ class Overseer {
NGuid guid;
unsigned int numPlaybackEndpoints;
IMMDeviceEnumerator *deviceEnumerator;
IPolicyConfig *policyConfig;
EndpointSituationCallback epsc;
//IPolicyConfig *policyConfig;
std::vector<Endpoint*> playbackDevices;
void initCOMLibrary();
//IMMDeviceCollection *deviceCollection;

View file

@ -70,6 +70,10 @@ uint8_t EndpointHandler::getRoles(){
return ep->getRoles();
}
void EndpointHandler::setRoles(Roles newRole){
ep->setRoles(newRole);
}
EndpointHandler::~EndpointHandler() {
ep->removeVolumeCallback(epc);
epc->Release();
@ -118,6 +122,10 @@ NGuid OverseerHandler::getGuid() {
return this->os->getGuid();
}
void setChangeFrontDefaultsFunction(std::function<void(Roles, wchar* endpointId)> changeFrontDefaults){
this->changeFrontDefaults = changeFrontDefaults;
}
void OverseerHandler::setEndpointHandlers(std::vector<EndpointHandler*> ephs){
this->endpointHandlers = ephs;
}

View file

@ -18,6 +18,7 @@ enum EndpointState {
ENDPOINT_DISABLED = (1 << 1),
ENDPOINT_NOTPRESENT = (1 << 2),
ENDPOINT_UNPLUGGED = (1 << 3),
ENDPOINT_ALL = 0x0F
};
enum Flows {
@ -78,6 +79,7 @@ public:
bool getMute();
uint8_t getState();
uint8_t getRoles();
void setRoles(Roles newRole);
void setVolume(NGuid guid, int channel, int value);
void setMute(NGuid guid, bool muted);
@ -95,6 +97,7 @@ class OverseerHandler {
public:
OverseerHandler();
void setChangeFrontDefaultsFunction(std::function<void(Roles, wchar* endpointId)> changeFrontDefaults);
void setEndpointHandlers(std::vector<EndpointHandler*> ephs);
std::vector<EndpointHandler*> getEndpointHandlers();
std::vector<Endpoint*> getPlaybackEndpoints();
@ -105,7 +108,7 @@ public:
private:
Overseer *os;
std::vector<EndpointHandler*> endpointHandlers;
std::function<void(Roles, wchar* endpointId)> changeFrontDefaults;
//std::function<void(uint64_t /* device */, uint32_t /* channel */, float /* value */)> updateFrontVolumeCallback;
//std::function<void(uint64_t /* device */, bool /* mute */)> updateFrontMuteCallback;

View file

@ -67,18 +67,39 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
uint8_t assignedRoles = eph->getRoles();
defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setCheckState(assignedRoles == Roles::ROLE_ALL ? Qt::Checked : Qt::Unchecked);
//todo duditas de &
defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setDisabled(assignedRoles == Roles::ROLE_ALL ? true : false);
defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setText(STRING_ROLE_ALL);
defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE)->setCheckState(assignedRoles & Roles::ROLE_CONSOLE ? Qt::Checked : Qt::Unchecked);
defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE)->setDisabled(assignedRoles & Roles::ROLE_CONSOLE ? true : false);
defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE)->setText(STRING_ROLE_CONSOLE);
defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA)->setCheckState(assignedRoles & Roles::ROLE_MULTIMEDIA ? Qt::Checked : Qt::Unchecked);
defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA)->setDisabled(assignedRoles & Roles::ROLE_MULTIMEDIA ? true : false);
defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA)->setText(STRING_ROLE_MULTIMEDIA);
defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS)->setCheckState(assignedRoles & Roles::ROLE_COMMUNICATIONS ? Qt::Checked : Qt::Unchecked);
defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS)->setDisabled(assignedRoles & Roles::ROLE_COMMUNICATIONS ? true : false);
defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS)->setText(STRING_ROLE_COMMUNICATIONS);
connect(defaultRolesCheckBoxes.at(Roles::ROLE_ALL), &QCheckBox::stateChanged,[this] {
this->eph->setRoles(Roles::ROLE_ALL);
//todo: bloquiar pto
});
connect(defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE), &QCheckBox::stateChanged,[this] {
this->eph->setRoles(Roles::ROLE_CONSOLE);
//todo: bloquiar pto
});
connect(defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA), &QCheckBox::stateChanged,[this] {
this->eph->setRoles(Roles::ROLE_MULTIMEDIA);
//todo: bloquiar pto
});
connect(defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS), &QCheckBox::stateChanged,[this] {
this->eph->setRoles(Roles::ROLE_COMMUNICATIONS);
//todo: bloquiar pto
});
defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setText(STRING_ROLE_ALL);
layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_ALL), 3, 0);
layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE), 3, 1);
layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA), 3, 2);