From 04da76c021e59e86fe36ffe8ab61f39e07fb33a9 Mon Sep 17 00:00:00 2001 From: Hane Date: Wed, 6 Sep 2023 19:59:55 +0200 Subject: [PATCH] enable/disable/add/remove groundwork done --- src/back/backlasses.cpp | 60 ++++++++++++++++++++--------------------- src/back/backlasses.h | 1 - src/qt/qtclasses.cpp | 59 +++++++++++++++++++++------------------- src/qt/qtclasses.h | 4 +++ 4 files changed, 66 insertions(+), 58 deletions(-) diff --git a/src/back/backlasses.cpp b/src/back/backlasses.cpp index d5d4906..c726753 100644 --- a/src/back/backlasses.cpp +++ b/src/back/backlasses.cpp @@ -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 playbackDevices){ this->deviceEnumerator = deviceEnumerator; this->playbackDevices = playbackDevices; } - ULONG EndpointSituationCallback::AddRef(){ return InterlockedIncrement(&ref); } @@ -132,37 +132,31 @@ 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); - */ +HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD 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,7 +201,10 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ endpoint->OpenPropertyStore(STGM_READ, &properties); PROPVARIANT 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){ @@ -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"); }; /* diff --git a/src/back/backlasses.h b/src/back/backlasses.h index 469839f..44407a0 100644 --- a/src/back/backlasses.h +++ b/src/back/backlasses.h @@ -61,7 +61,6 @@ class Endpoint { unsigned long endpointState; uint8_t endpointRoles = 0; uint64_t idx; - // LPWSTR endpointID = NULL; }; class EndpointVolumeCallback : public IAudioEndpointVolumeCallback { diff --git a/src/qt/qtclasses.cpp b/src/qt/qtclasses.cpp index 8bea983..38b0e44 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -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(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++) { - log_debugcpp("EPWidget creation"); - osh->getEndpointHandlers().at(i)->getCallbackInfo()->caller = osh->getGuid(); - EndpointWidget *epw = new EndpointWidget(i, osh->getEndpointHandlers().at(i), widget); - //TODO: ALWAYS PUSH BACK??? PSZ CHANGE DIS WHEN IMPLEMENTING DYN ENDPOINT DET - ews.push_back(epw); - layout->addWidget(epw, i, 0); - + 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(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); } diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index db9917a..77265e8 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -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; };