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->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){
this->deviceEnumerator = deviceEnumerator;
this->playbackDevices = playbackDevices;
}
ULONG EndpointSituationCallback::AddRef(){
return InterlockedIncrement(&ref);
}
@ -132,36 +132,30 @@ HRESULT EndpointSituationCallback::OnDefaultDeviceChanged(EDataFlow flow, ERole
}
HRESULT EndpointSituationCallback::OnDeviceAdded(LPCWSTR pwstrDeviceId) {
log_wdebugcpp(L"ayo we eventing za adin" << pwstrDeviceId);
return S_OK;
};
HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
log_wdebugcpp(L"ayo we eventing za rmovin" << pwstrDeviceId);
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);
*/
switch (dwNewState){
case DEVICE_STATE_ACTIVE:
break;
case DEVICE_STATE_DISABLED:
break;
case DEVICE_STATE_NOTPRESENT:
break;
case DEVICE_STATE_UNPLUGGED:
break;
}
return S_OK;
}
@ -184,6 +178,10 @@ 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);};
@ -203,6 +201,9 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){
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);
}
@ -214,7 +215,6 @@ uint64_t Endpoint::getIndex(){
return idx;
}
std::wstring Endpoint::getName(){
return friendlyName;
}
@ -253,14 +253,13 @@ 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))) { };
if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) {};
}
}
@ -391,7 +390,8 @@ void Overseer::initCOMLibrary() {
void Overseer::reloadEndpoints() {
IMMDeviceCollection *deviceCollection;
// | 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"); };
/*

View file

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

View file

@ -1,6 +1,7 @@
#include "qtclasses.h"
bool ExtendedCheckBox::event(QEvent* ev) {
if (ev->type() == QEvent::User) {
this->blockSignals(true);
@ -20,26 +21,27 @@ bool ExtendedCheckBox::event(QEvent* ev) {
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->eph = eph;
layout = new QGridLayout();
this->setLayout(layout);
log_debugcpp("olaW");
layout = new QGridLayout(this);
//this->setLayout(layout);
log_debugcpp("epw main layout parent: "<< layout->parent());
if (parent == nullptr) { log_debugcpp("owo?"); }
defaultRolesCheckBoxes = {
{Roles::ROLE_ALL, new ExtendedCheckBox()},
{Roles::ROLE_CONSOLE, new ExtendedCheckBox()},
{Roles::ROLE_MULTIMEDIA, new ExtendedCheckBox()},
{Roles::ROLE_COMMUNICATIONS, new ExtendedCheckBox()}
{Roles::ROLE_ALL, new ExtendedCheckBox(this)},
{Roles::ROLE_CONSOLE, new ExtendedCheckBox(this)},
{Roles::ROLE_MULTIMEDIA, new ExtendedCheckBox(this)},
{Roles::ROLE_COMMUNICATIONS, new ExtendedCheckBox(this)}
};
/*
* Mute, main slider and label setup
*/
muteButton = new QCheckBox();
mainLabel = new QLabel(QString::fromStdWString(eph->getName()));
mainSlider = new QSlider(Qt::Horizontal);
muteButton = new QCheckBox(this);
mainLabel = new QLabel(QString::fromStdWString(eph->getName()), this);
mainSlider = new QSlider(Qt::Horizontal, this);
if (this->eph->getState() != EndpointState::ENDPOINT_ACTIVE) {
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");
mainSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mainSlider->setFocusPolicy(Qt::StrongFocus);
mainSlider->setTickPosition(QSlider::TicksBothSides);
mainSlider->setTickInterval(5);
@ -60,12 +63,11 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
mainSlider->setValue((int)volume);
log_debugcpp("ENDPOINT SET WITH VOLUME " << volume);
//todo: parent
mainMuteLayout = new QGridLayout();
layout->addLayout(mainMuteLayout, 0, 0, 2, 1, Qt::AlignLeft | Qt::AlignBottom);
mainMuteLayout->addWidget(mainLabel, 0, 0);
mainMuteLayout->addWidget(muteButton, 0, 1);
layout->addWidget(mainSlider, 0, 2, 1, 2, Qt::AlignLeft | Qt::AlignBottom);
//tip: would need to be new widget with layout in it
//mainMuteLayout = new QGridLayout();
layout->addWidget(mainLabel, 0, 0, Qt::AlignLeft | Qt::AlignBottom);
layout->addWidget(muteButton, 0, 1, Qt::AlignLeft | Qt::AlignBottom);
layout->addWidget(mainSlider, 0, 2, 1, 2);
//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);
@ -78,6 +80,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
for(uint32_t i = 0; i < eph->getChannelCount(); i++){
QSlider* tmp = new QSlider(Qt::Horizontal);
QLabel* tmpLb = new QLabel("");
tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
tmp->setTickInterval(5);
tmp->setSingleStep(1);
tmp->setRange(0,100);
@ -87,8 +90,8 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
tmpLb->setText(QString::number(volume));
this->channelSliders.push_back(tmp);
this->channelLabels.push_back(tmpLb);
layout->addWidget(tmp, 2, i, 1, 2, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(tmpLb, 3, i, 1, 2, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(tmp, 2, i);
layout->addWidget(tmpLb, 3, i);
//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.
connect(tmp, &QSlider::valueChanged, [this, i](int newValue){
@ -329,16 +332,18 @@ void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason) {
void MainWindow::reloadEndpointWidgets() {
size_t i = 0;
for (; i < (osh->getEndpointHandlers().size()); i++) {
for (size_t epwIndex = 0; i < (osh->getEndpointHandlers().size()); i++) {
if (osh->getEndpointHandlers().at(i)->getState() == EndpointState::ENDPOINT_ACTIVE){
log_debugcpp("EPWidget creation");
osh->getEndpointHandlers().at(i)->getCallbackInfo()->caller = osh->getGuid();
EndpointWidget *epw = new EndpointWidget(i, osh->getEndpointHandlers().at(i), widget);
EndpointWidget *epw = new EndpointWidget(epwIndex, osh->getEndpointHandlers().at(i), widget);
epwIndex++;
//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);
}

View file

@ -61,6 +61,10 @@
class ExtendedCheckBox : public QCheckBox {
Q_OBJECT
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;
};