enable/disable/add/remove groundwork done

This commit is contained in:
Hane 2023-09-06 19:59:55 +02:00
commit 04da76c021
4 changed files with 66 additions and 58 deletions

View file

@ -71,14 +71,14 @@ HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify
* this->deviceEnumerator = deviceEnumerator; * this->deviceEnumerator = deviceEnumerator;
* this->playbackDevices = playbackDevices; * 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){ void EndpointSituationCallback::fill(IMMDeviceEnumerator *deviceEnumerator, std::vector<Endpoint*> playbackDevices){
this->deviceEnumerator = deviceEnumerator; this->deviceEnumerator = deviceEnumerator;
this->playbackDevices = playbackDevices; this->playbackDevices = playbackDevices;
} }
ULONG EndpointSituationCallback::AddRef(){ ULONG EndpointSituationCallback::AddRef(){
return InterlockedIncrement(&ref); return InterlockedIncrement(&ref);
} }
@ -132,36 +132,30 @@ HRESULT EndpointSituationCallback::OnDefaultDeviceChanged(EDataFlow flow, ERole
} }
HRESULT EndpointSituationCallback::OnDeviceAdded(LPCWSTR pwstrDeviceId) { HRESULT EndpointSituationCallback::OnDeviceAdded(LPCWSTR pwstrDeviceId) {
log_wdebugcpp(L"ayo we eventing za adin" << pwstrDeviceId);
return S_OK; return S_OK;
}; };
HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) { HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
log_wdebugcpp(L"ayo we eventing za rmovin" << pwstrDeviceId);
return S_OK; return S_OK;
} }
HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
/* switch (dwNewState){
* char *pszState = "?????"; case DEVICE_STATE_ACTIVE:
*
* switch (dwNewState) break;
* { case DEVICE_STATE_DISABLED:
* case DEVICE_STATE_ACTIVE:
* pszState = "ACTIVE"; break;
* break; case DEVICE_STATE_NOTPRESENT:
* case DEVICE_STATE_DISABLED:
* pszState = "DISABLED"; break;
* break; case DEVICE_STATE_UNPLUGGED:
* case DEVICE_STATE_NOTPRESENT:
* pszState = "NOTPRESENT"; break;
* 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; return S_OK;
} }
@ -184,6 +178,10 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){
this->endpoint = ep; this->endpoint = ep;
this->idx = idx; 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 //todo: preguntitas owindows dword no es uint32_t even tho mingw mingas
if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-1);}; if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-1);};
@ -203,7 +201,10 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){
endpoint->OpenPropertyStore(STGM_READ, &properties); endpoint->OpenPropertyStore(STGM_READ, &properties);
PROPVARIANT pv; PROPVARIANT pv;
properties->GetValue(PKEY_Device_FriendlyName , &pv); properties->GetValue(PKEY_Device_FriendlyName , &pv);
friendlyName = std::wstring(pv.pwszVal); if (pv.pwszVal == nullptr)
friendlyName = L"Unnamed Not Present Endpoint";
else
friendlyName = std::wstring(pv.pwszVal);
} }
void Endpoint::setIndex(uint64_t idx){ void Endpoint::setIndex(uint64_t idx){
@ -214,7 +215,6 @@ uint64_t Endpoint::getIndex(){
return idx; return idx;
} }
std::wstring Endpoint::getName(){ std::wstring Endpoint::getName(){
return friendlyName; return friendlyName;
} }
@ -253,14 +253,13 @@ size_t Endpoint::getState(){
return this->endpointState; return this->endpointState;
} }
void Endpoint::setVolume(NGuid guid, int channel, float volume) { void Endpoint::setVolume(NGuid guid, int channel, float volume) {
//TIP: There used to be log messages here. Now, it's a ghost town. //TIP: There used to be log messages here. Now, it's a ghost town.
GUID tempMsGuid = NGuidToGUID(guid); GUID tempMsGuid = NGuidToGUID(guid);
if (channel == AudioChannel::CHANNEL_MAIN) { if (channel == AudioChannel::CHANNEL_MAIN) {
if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) {}; if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) {};
} else { } else {
if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) { }; if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) {};
} }
} }
@ -391,7 +390,8 @@ void Overseer::initCOMLibrary() {
void Overseer::reloadEndpoints() { void Overseer::reloadEndpoints() {
IMMDeviceCollection *deviceCollection; IMMDeviceCollection *deviceCollection;
// | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED // | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED
if(FAILED(deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &deviceCollection) )) // NOTPRESENT shows a lot of garbage, unnamed devices.
if(FAILED(deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED, &deviceCollection) ))
{ log_debugcpp("si"); }; { log_debugcpp("si"); };
/* /*

View file

@ -61,7 +61,6 @@ class Endpoint {
unsigned long endpointState; unsigned long endpointState;
uint8_t endpointRoles = 0; uint8_t endpointRoles = 0;
uint64_t idx; uint64_t idx;
// LPWSTR endpointID = NULL;
}; };
class EndpointVolumeCallback : public IAudioEndpointVolumeCallback { class EndpointVolumeCallback : public IAudioEndpointVolumeCallback {

View file

@ -1,6 +1,7 @@
#include "qtclasses.h" #include "qtclasses.h"
bool ExtendedCheckBox::event(QEvent* ev) { bool ExtendedCheckBox::event(QEvent* ev) {
if (ev->type() == QEvent::User) { if (ev->type() == QEvent::User) {
this->blockSignals(true); this->blockSignals(true);
@ -20,26 +21,27 @@ bool ExtendedCheckBox::event(QEvent* ev) {
EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *parent) : QWidget(parent){ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *parent) : QWidget(parent){
//todo: based on qgridlayout, name+mute should be its own widget, same with channels
this->idx = idx; this->idx = idx;
this->eph = eph; this->eph = eph;
layout = new QGridLayout(); layout = new QGridLayout(this);
this->setLayout(layout); //this->setLayout(layout);
log_debugcpp("olaW"); log_debugcpp("epw main layout parent: "<< layout->parent());
if (parent == nullptr) { log_debugcpp("owo?"); } if (parent == nullptr) { log_debugcpp("owo?"); }
defaultRolesCheckBoxes = { defaultRolesCheckBoxes = {
{Roles::ROLE_ALL, new ExtendedCheckBox()}, {Roles::ROLE_ALL, new ExtendedCheckBox(this)},
{Roles::ROLE_CONSOLE, new ExtendedCheckBox()}, {Roles::ROLE_CONSOLE, new ExtendedCheckBox(this)},
{Roles::ROLE_MULTIMEDIA, new ExtendedCheckBox()}, {Roles::ROLE_MULTIMEDIA, new ExtendedCheckBox(this)},
{Roles::ROLE_COMMUNICATIONS, new ExtendedCheckBox()} {Roles::ROLE_COMMUNICATIONS, new ExtendedCheckBox(this)}
}; };
/* /*
* Mute, main slider and label setup * Mute, main slider and label setup
*/ */
muteButton = new QCheckBox(); muteButton = new QCheckBox(this);
mainLabel = new QLabel(QString::fromStdWString(eph->getName())); mainLabel = new QLabel(QString::fromStdWString(eph->getName()), this);
mainSlider = new QSlider(Qt::Horizontal); mainSlider = new QSlider(Qt::Horizontal, this);
if (this->eph->getState() != EndpointState::ENDPOINT_ACTIVE) { if (this->eph->getState() != EndpointState::ENDPOINT_ACTIVE) {
layout->addWidget(mainLabel, 0, 0); layout->addWidget(mainLabel, 0, 0);
@ -48,6 +50,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
} }
//muteButton->setStyleSheet("background-color: #A3C1DA; color: red"); //muteButton->setStyleSheet("background-color: #A3C1DA; color: red");
mainSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mainSlider->setFocusPolicy(Qt::StrongFocus); mainSlider->setFocusPolicy(Qt::StrongFocus);
mainSlider->setTickPosition(QSlider::TicksBothSides); mainSlider->setTickPosition(QSlider::TicksBothSides);
mainSlider->setTickInterval(5); mainSlider->setTickInterval(5);
@ -60,12 +63,11 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
mainSlider->setValue((int)volume); mainSlider->setValue((int)volume);
log_debugcpp("ENDPOINT SET WITH VOLUME " << volume); log_debugcpp("ENDPOINT SET WITH VOLUME " << volume);
//todo: parent //tip: would need to be new widget with layout in it
mainMuteLayout = new QGridLayout(); //mainMuteLayout = new QGridLayout();
layout->addLayout(mainMuteLayout, 0, 0, 2, 1, Qt::AlignLeft | Qt::AlignBottom); layout->addWidget(mainLabel, 0, 0, Qt::AlignLeft | Qt::AlignBottom);
mainMuteLayout->addWidget(mainLabel, 0, 0); layout->addWidget(muteButton, 0, 1, Qt::AlignLeft | Qt::AlignBottom);
mainMuteLayout->addWidget(muteButton, 0, 1); layout->addWidget(mainSlider, 0, 2, 1, 2);
layout->addWidget(mainSlider, 0, 2, 1, 2, Qt::AlignLeft | Qt::AlignBottom);
//TODO:0 = mute and muted, change volume = unmuted are client side tricks = 2 callbacks, one for volume, one for mute state. Implement as an user selectable option? //TODO:0 = mute and muted, change volume = unmuted are client side tricks = 2 callbacks, one for volume, one for mute state. Implement as an user selectable option?
connect<void(QSlider::*)(int), void(EndpointWidget::*)(int)>(mainSlider, &QSlider::valueChanged, this,&EndpointWidget::updateMainVolume); connect<void(QSlider::*)(int), void(EndpointWidget::*)(int)>(mainSlider, &QSlider::valueChanged, this,&EndpointWidget::updateMainVolume);
@ -78,6 +80,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
for(uint32_t i = 0; i < eph->getChannelCount(); i++){ for(uint32_t i = 0; i < eph->getChannelCount(); i++){
QSlider* tmp = new QSlider(Qt::Horizontal); QSlider* tmp = new QSlider(Qt::Horizontal);
QLabel* tmpLb = new QLabel(""); QLabel* tmpLb = new QLabel("");
tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
tmp->setTickInterval(5); tmp->setTickInterval(5);
tmp->setSingleStep(1); tmp->setSingleStep(1);
tmp->setRange(0,100); tmp->setRange(0,100);
@ -87,8 +90,8 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
tmpLb->setText(QString::number(volume)); tmpLb->setText(QString::number(volume));
this->channelSliders.push_back(tmp); this->channelSliders.push_back(tmp);
this->channelLabels.push_back(tmpLb); this->channelLabels.push_back(tmpLb);
layout->addWidget(tmp, 2, i, 1, 2, Qt::AlignLeft | Qt::AlignTop); layout->addWidget(tmp, 2, i);
layout->addWidget(tmpLb, 3, i, 1, 2, Qt::AlignLeft | Qt::AlignTop); layout->addWidget(tmpLb, 3, i);
//TODO: check if there's a need to prevent deadlocks; probably this will eventually turn into its own func //TODO: check if there's a need to prevent deadlocks; probably this will eventually turn into its own func
//this causes channel bar desync when back -> front. blocksignals below fix it. huh. //this causes channel bar desync when back -> front. blocksignals below fix it. huh.
connect(tmp, &QSlider::valueChanged, [this, i](int newValue){ connect(tmp, &QSlider::valueChanged, [this, i](int newValue){
@ -329,16 +332,18 @@ void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason) {
void MainWindow::reloadEndpointWidgets() { void MainWindow::reloadEndpointWidgets() {
size_t i = 0; size_t i = 0;
for (; i < (osh->getEndpointHandlers().size()); i++) { for (size_t epwIndex = 0; i < (osh->getEndpointHandlers().size()); i++) {
log_debugcpp("EPWidget creation"); if (osh->getEndpointHandlers().at(i)->getState() == EndpointState::ENDPOINT_ACTIVE){
osh->getEndpointHandlers().at(i)->getCallbackInfo()->caller = osh->getGuid(); log_debugcpp("EPWidget creation");
EndpointWidget *epw = new EndpointWidget(i, osh->getEndpointHandlers().at(i), widget); osh->getEndpointHandlers().at(i)->getCallbackInfo()->caller = osh->getGuid();
//TODO: ALWAYS PUSH BACK??? PSZ CHANGE DIS WHEN IMPLEMENTING DYN ENDPOINT DET EndpointWidget *epw = new EndpointWidget(epwIndex, osh->getEndpointHandlers().at(i), widget);
ews.push_back(epw); epwIndex++;
layout->addWidget(epw, i, 0); //TODO: ALWAYS PUSH BACK??? PSZ CHANGE DIS WHEN IMPLEMENTING DYN ENDPOINT DET
ews.push_back(epw);
layout->addWidget(epw, i, 0);
}
} }
//todo:: tas aqui tirao, no me gustas y probablemente yo a ti tampoco
layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), i, 0); layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), i, 0);
} }

View file

@ -61,6 +61,10 @@
class ExtendedCheckBox : public QCheckBox { class ExtendedCheckBox : public QCheckBox {
Q_OBJECT Q_OBJECT
public: public:
//c++11: this inherits all parent's constructors unconditionally
using QCheckBox::QCheckBox;
//alternative being calling parent ctor directly after declaring child ctor:
//B(int x) : A(x) { }
bool event(QEvent* ev) override; bool event(QEvent* ev) override;
}; };