From a6a052f34876ef28154e937e949acd231c0427bf Mon Sep 17 00:00:00 2001 From: Hane Date: Wed, 6 Sep 2023 17:57:15 +0200 Subject: [PATCH] endpoint add/remove foundational work --- src/back/backlasses.cpp | 62 +++++++++++++++-------- src/back/backlasses.h | 6 +-- src/cont/contclasses.cpp | 18 ++++--- src/cont/contclasses.h | 2 +- src/qt/qtclasses.cpp | 105 +++++++++++++++++---------------------- src/qt/qtclasses.h | 6 +-- 6 files changed, 103 insertions(+), 96 deletions(-) diff --git a/src/back/backlasses.cpp b/src/back/backlasses.cpp index 13ae38e..d5d4906 100644 --- a/src/back/backlasses.cpp +++ b/src/back/backlasses.cpp @@ -183,16 +183,15 @@ HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ this->endpoint = ep; this->idx = idx; - //if(FAILED()) {}; - DWORD tempState = 0; - if(FAILED(endpoint->GetState(&tempState))) {exit(-1);}; - this->endpointState = tempState; - - if (tempState == DEVICE_STATE_ACTIVE) { + + //todo: preguntitas owindows dword no es uint32_t even tho mingw mingas + if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-1);}; + + if (this->endpointState == DEVICE_STATE_ACTIVE) { if(FAILED(endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&endpointVolume))) { /* log_debugcpp("si"); */ }; if (FAILED(endpointVolume->GetChannelCount(&channelCount))) {};/* log_debugcpp("get channel count fail"); */ - } else channelCount = 0; + } //todo:: atexit into exit Gather ID LPWSTR tempString = nullptr; @@ -250,7 +249,7 @@ void Endpoint::setState(uint8_t state){ this->endpointState = state; } -uint8_t Endpoint::getState(){ +size_t Endpoint::getState(){ return this->endpointState; } @@ -291,17 +290,34 @@ void Endpoint::setRoles(Roles role){ 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" "; + std::wstring troublePair = L"0"; switch (role) { case Roles::ROLE_ALL: /* - * 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"; + * 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... */ - command += L"0 1"; + 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); @@ -375,16 +391,18 @@ 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) )) + if(FAILED(deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &deviceCollection) )) { log_debugcpp("si"); }; - - //Counting them + /* + * Counting them + */ if(FAILED(deviceCollection->GetCount(&numPlaybackEndpoints))) { log_debugcpp("si");}; if(numPlaybackEndpoints == 0) { log_debugcpp("si"); }; - - //Retrieving actual endpoints and storing them on their own class + /* + * Retrieving actual endpoints and storing them on their own class + */ IMMDevice *temp; for (unsigned int i = 0; i < numPlaybackEndpoints; i++){ if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); }; @@ -396,8 +414,10 @@ void Overseer::reloadEndpoints() { deviceCollection->Release(); - //Discerning default endpoints per role - //order: console, multimedia, communications + /* + * Discerning default endpoints per role + * order: console, multimedia, communications + */ for(int i = 0; i < ERole_enum_count; i++){ ERole val; switch(i) { diff --git a/src/back/backlasses.h b/src/back/backlasses.h index d8b0d2b..469839f 100644 --- a/src/back/backlasses.h +++ b/src/back/backlasses.h @@ -40,7 +40,7 @@ class Endpoint { void setMute(NGuid guid, bool muted); bool getMute(); void setState(uint8_t state); - uint8_t getState(); + size_t getState(); uint8_t getRoles(); void setRoles(Roles role); void assignRoles(uint8_t role); @@ -52,13 +52,13 @@ class Endpoint { ~Endpoint(); private: - uint32_t channelCount; + uint32_t channelCount = 0; IMMDevice* endpoint; IAudioEndpointVolume *endpointVolume ; IPropertyStore *properties; std::wstring friendlyName; std::wstring endpointId; - uint8_t endpointState; + unsigned long endpointState; uint8_t endpointRoles = 0; uint64_t idx; // LPWSTR endpointID = NULL; diff --git a/src/cont/contclasses.cpp b/src/cont/contclasses.cpp index abedbfd..28864c5 100644 --- a/src/cont/contclasses.cpp +++ b/src/cont/contclasses.cpp @@ -7,13 +7,15 @@ EndpointHandler::EndpointHandler(uint64_t idx) { this->ep = osh->getPlaybackEndpoints().at(idx); epc = new EndpointVolumeCallback(ep); //epName = ep->getName(); - ep->setVolumeCallback(epc); - callbackInfo.muted = this->getMute(); - callbackInfo.mainVolume = this->getVolume(AudioChannel::CHANNEL_MAIN); - callbackInfo.channels = this->getChannelCount(); - callbackInfo.channelVolumes.resize(this->callbackInfo.channels); - for(uint32_t i = 0; i < this->getChannelCount(); i++){ - callbackInfo.channelVolumes[i] = this->getVolume(i); + if (this->ep->getState() == EndpointState::ENDPOINT_ACTIVE) { + callbackInfo.muted = this->getMute(); + callbackInfo.mainVolume = this->getVolume(AudioChannel::CHANNEL_MAIN); + callbackInfo.channels = this->getChannelCount(); + ep->setVolumeCallback(epc); + callbackInfo.channelVolumes.resize(this->callbackInfo.channels); + for(uint32_t i = 0; i < this->getChannelCount(); i++){ + callbackInfo.channelVolumes[i] = this->getVolume(i); + } } } @@ -72,7 +74,7 @@ bool EndpointHandler::getMute(){ return ep->getMute(); } -uint8_t EndpointHandler::getState(){ +size_t EndpointHandler::getState(){ return ep->getState(); } diff --git a/src/cont/contclasses.h b/src/cont/contclasses.h index 7ea9f6e..7ff6882 100644 --- a/src/cont/contclasses.h +++ b/src/cont/contclasses.h @@ -79,7 +79,7 @@ public: float getVolume(int channel); bool getMute(); - uint8_t getState(); + size_t getState(); uint8_t getRoles(); void setRoles(Roles newRole); void assignRoles(Roles newRole); diff --git a/src/qt/qtclasses.cpp b/src/qt/qtclasses.cpp index 0bb0f08..8bea983 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -33,10 +33,19 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare {Roles::ROLE_MULTIMEDIA, new ExtendedCheckBox()}, {Roles::ROLE_COMMUNICATIONS, new ExtendedCheckBox()} }; - + + /* + * Mute, main slider and label setup + */ muteButton = new QCheckBox(); mainLabel = new QLabel(QString::fromStdWString(eph->getName())); mainSlider = new QSlider(Qt::Horizontal); + + if (this->eph->getState() != EndpointState::ENDPOINT_ACTIVE) { + layout->addWidget(mainLabel, 0, 0); + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 1, 0); + return; + } //muteButton->setStyleSheet("background-color: #A3C1DA; color: red"); mainSlider->setFocusPolicy(Qt::StrongFocus); @@ -44,7 +53,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare mainSlider->setTickInterval(5); mainSlider->setSingleStep(1); mainSlider->setRange(0,100); - + muteButton->setCheckState((eph->getMute() == false ? Qt::Unchecked : Qt::Checked)); muteButton->setText(eph->getMute() ? STRING_UNMUTE : STRING_MUTE); float volume = eph->getVolume(AudioChannel::CHANNEL_MAIN) * 100; @@ -63,6 +72,9 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare connect(muteButton, &QCheckBox::stateChanged, this, (&EndpointWidget::updateMute)); +/* + * Channel sliders setup + */ for(uint32_t i = 0; i < eph->getChannelCount(); i++){ QSlider* tmp = new QSlider(Qt::Horizontal); QLabel* tmpLb = new QLabel(""); @@ -84,6 +96,10 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare this->channelLabels.at(i)->setText(QString::number(newValue)); }); } + + /* + * Role ExtendedCheckBoxes setup + */ uint8_t assignedRoles = eph->getRoles(); defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setCheckState(assignedRoles == Roles::ROLE_ALL ? Qt::Checked : Qt::Unchecked); @@ -105,29 +121,28 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare 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 }); layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_ALL), 5, 0); layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE), 5, 1); layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA), 5, 2); layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS), 5, 3); + +/* ----------------------------------------------------------- */ - - //Polling time + /* + * EndpointVolume Polling time + */ timer = new QTimer(); connect(timer, &QTimer::timeout, [this, eph](){ //if (memcmp(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)) == 0) return; CHECK IF THIS PROGRAM GENERATED THE FUNSIES IS NO LONGER IN USE FOR NOW. @@ -151,6 +166,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare muteButton->blockSignals(false); }); timer->start(10); + //todo parent? layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 1, 0); layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 4, 0); @@ -159,20 +175,6 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare log_debugcpp("ENDPOINT_WIDGETED"); } -/* - * void EndpointWidget::updateMute(bool muted){ - * //TIP: Blocksignals here to diagnose slider visuals locking when playing DJ with external volume bar. Functionality is restored when mute checkbox is clicked. - * //this->blockSignals(true); - * this->muteButton->blockSignals(true); - * - * //this->eph->setMute(osh->getGuid(), muted); - * this->muteButton->setChecked(muted); - * this->muteButton->setText(this->eph->getMute() ? STRING_UNMUTE : STRING_MUTE); - * this->muteButton->blockSignals(false); - * //this->blockSignals(false); - * } - */ - void EndpointWidget::updateMute(int checked){ bool muted = (checked == 2 ? true : false); this->eph->setMute(osh->getGuid(), muted); @@ -180,7 +182,6 @@ void EndpointWidget::updateMute(int checked){ } void EndpointWidget::updateMainVolume(int newValue){ - //QObject* obj = sender(); this->eph->setVolume(osh->getGuid(), AudioChannel::CHANNEL_MAIN, newValue); } @@ -246,7 +247,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { reloadEndpointWidgets(); - //Tray Icon + /* + * Tray Icon code + */ trayIconMenu->addSeparator(); trayIconMenu->addAction(trayIconMenuQuit); connect(trayIconMenuQuit, &QAction::triggered, qApp, &QCoreApplication::quit); @@ -257,14 +260,16 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { trayIcon->show(); trayIcon->setToolTip(STRING_TITLE); trayIcon->setContextMenu(trayIconMenu); - //todo: ayo... - QString as = trayIcon->toolTip(); connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::trayIconActivated); - - + + /* + * Set of function callback definitinos for EndpointSituationCallback + */ osh->setChangeFrontDefaultsFunction([this](Roles role, std::wstring endpointId) { - for (auto epw : this->ews) { + /* + * Is this the new default endpoint? + */ if (epw->getEndpointHandler()->getId() == endpointId) { //not necessary to keep endpointState flags up to date right now, but updating it will allow for later config files / profiles epw->defaultRolesCheckBoxes.at(role)->blockSignals(true); @@ -272,39 +277,32 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { epw->defaultRolesCheckBoxes.at(role)->blockSignals(false); QCoreApplication::instance()->postEvent(epw->defaultRolesCheckBoxes.at(role), changeDefaultCheckboxEnablement); //epw->defaultRolesCheckBoxes.at(role)->postEnableChange(); - + /* + * And were you THE default? + */ if (epw->getEndpointHandler()->getRoles() == Roles::ROLE_ALL) { QCoreApplication::instance()->postEvent(epw->defaultRolesCheckBoxes.at(Roles::ROLE_ALL), changeDefaultCheckboxEnablement); } - - /* - * switch (role) { - * case Roles::ROLE_CONSOLE: - * epw->getEndpointHandler()->assignRoles(role); - * break; - * case Roles::ROLE_MULTIMEDIA: - * break; - * case Roles::ROLE_COMMUNICATIONS: - * break; - * - * } - */ - } else { - if (epw->getEndpointHandler()->getRoles() & role) { + /* + * Are you the dethroned king? + */ + } else if (epw->getEndpointHandler()->getRoles() & role) { + /* + * And were you THE default up until now? + */ if (epw->getEndpointHandler()->getRoles() == Roles::ROLE_ALL) { QCoreApplication::instance()->postEvent(epw->defaultRolesCheckBoxes.at(Roles::ROLE_ALL), changeDefaultCheckboxEnablement); } epw->defaultRolesCheckBoxes.at(role)->blockSignals(true); + //Same as before. ini-san will come... epw->getEndpointHandler()->removeRoles(role); - //epw->defaultRolesCheckBoxes.at(role)->setDisabled(false); epw->defaultRolesCheckBoxes.at(role)->blockSignals(false); QCoreApplication::instance()->postEvent(epw->defaultRolesCheckBoxes.at(role), changeDefaultCheckboxEnablement); } } - } - }); + }); } void MainWindow::closeEvent(QCloseEvent *event) { @@ -342,16 +340,5 @@ void MainWindow::reloadEndpointWidgets() { } layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), i, 0); - - /* - * osh->setFrontVolumeCallback([this](uint64_t device, uint32_t channel, float value) { - * if (device < ews.size()) - * ews.at(device)->updateVolume(channel, value); - * }); - * osh->setFrontMuteCallback([this](uint64_t device, bool muted) { - * if (device < ews.size()) - * ews.at(device)->updateMute(muted); - * }); - */ } diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index df21c9b..db9917a 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -59,14 +59,12 @@ class ExtendedCheckBox : public QCheckBox { - Q_OBJECT - - + Q_OBJECT public: bool event(QEvent* ev) override; - }; + class EndpointWidget : public QWidget { Q_OBJECT