diff --git a/src/back/backlasses.cpp b/src/back/backlasses.cpp index c726753..93122f0 100644 --- a/src/back/backlasses.cpp +++ b/src/back/backlasses.cpp @@ -141,19 +141,16 @@ HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) { return S_OK; } -HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { +HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { + std::wstring endpointId = std::wstring(pwstrDeviceId); switch (dwNewState){ case DEVICE_STATE_ACTIVE: - + osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_ACTIVE); break; case DEVICE_STATE_DISABLED: - - break; case DEVICE_STATE_NOTPRESENT: - - break; case DEVICE_STATE_UNPLUGGED: - + osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_DISABLED); break; } @@ -161,16 +158,15 @@ HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, D } 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); - */ + + log_debugcpp(" -->Changed device property " << + key.fmtid.Data1 << key.fmtid.Data2 << key.fmtid.Data3 << "\n" << + key.fmtid.Data4[0]<< key.fmtid.Data4[1]<< "\n"<< + key.fmtid.Data4[2]<< key.fmtid.Data4[3] << "\n"<< + key.fmtid.Data4[4]<< key.fmtid.Data4[5] << "\n"<< + key.fmtid.Data4[6]<< key.fmtid.Data4[7]<< "\n"<< + " pid " << key.pid); + return S_OK; } @@ -391,7 +387,7 @@ void Overseer::reloadEndpoints() { IMMDeviceCollection *deviceCollection; // | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED // NOTPRESENT shows a lot of garbage, unnamed devices. - if(FAILED(deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED, &deviceCollection) )) + if(FAILED(deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED, &deviceCollection) )) { log_debugcpp("si"); }; /* diff --git a/src/cont/contclasses.cpp b/src/cont/contclasses.cpp index 28864c5..0d38d46 100644 --- a/src/cont/contclasses.cpp +++ b/src/cont/contclasses.cpp @@ -19,6 +19,19 @@ EndpointHandler::EndpointHandler(uint64_t idx) { } } +void EndpointHandler::setFrontVisibilityInfo(EndpointState state, uint64_t frontIdx){ + ephfv.visibility = state; + ephfv.frontIdx = frontIdx; +} + +uint64_t EndpointHandler::getFrontVisibilityIndex(){ + return ephfv.frontIdx; +} + +EndpointState EndpointHandler::getFrontVisibilityState(){ + return ephfv.visibility; +} + /* these two, currently unused. If I use them, I should feel bad. * Endpoint* EndpointHandler::getEndpoint() { * return this->ep; @@ -152,7 +165,32 @@ void OverseerHandler::setChangeFrontDefaultsFunction(std::functionchangeFrontDefaults(role, endpointId); -} +} + +void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointState state) { + EndpointHandler* affected = nullptr; + for (auto eph : this->endpointHandlers) { + if (eph->getId() == endpointId) { + affected = eph; + break; + } + } + //todo: + if(EndpointState::ENDPOINT_ACTIVE & state) { + //todo: + return; + } else if (affected->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE){ + this->removeEndpointWidget(affected->getFrontVisibilityIndex()); + affected->setFrontVisibilityInfo(EndpointState::ENDPOINT_ALL, INT_MAX); + } + return; + //this->reviseEndpointShowing(endpointId, role); +} + +void OverseerHandler::setRemoveEndpointWidgetFunction(std::function removeEndpointWidget){ + this->removeEndpointWidget = removeEndpointWidget; +} + void OverseerHandler::setEndpointHandlers(std::vector ephs){ this->endpointHandlers = ephs; diff --git a/src/cont/contclasses.h b/src/cont/contclasses.h index 7ff6882..8bd07b0 100644 --- a/src/cont/contclasses.h +++ b/src/cont/contclasses.h @@ -76,7 +76,11 @@ public: std::wstring getName(); std::wstring getId(); - + + void setFrontVisibilityInfo(EndpointState state, uint64_t frontIdx); + uint64_t getFrontVisibilityIndex(); + EndpointState getFrontVisibilityState(); + float getVolume(int channel); bool getMute(); size_t getState(); @@ -95,6 +99,11 @@ private: Endpoint *ep = nullptr; EndpointVolumeCallback *epc = nullptr; BackEndpointVolumeCallbackInfo callbackInfo; + struct EndpointHandlerFrontVisibility { + EndpointState visibility = EndpointState::ENDPOINT_ALL; + uint64_t frontIdx = INT_MAX; + }; + EndpointHandlerFrontVisibility ephfv; //QSlider *slidy; }; @@ -105,7 +114,10 @@ public: OverseerHandler(); void setChangeFrontDefaultsFunction(std::function changeFrontDefaults); void changeFrontDefaultsCallback(Roles role, std::wstring endpointId); - + + //void setReviseEndpointShowingFunction(std::function reviseEndpointShowing); + void reviseEndpointShowing(std::wstring endpointId, EndpointState state); + void setRemoveEndpointWidgetFunction(std::function removeEndpointWidget); void setEndpointHandlers(std::vector ephs); std::vector getEndpointHandlers(); std::vector getPlaybackEndpoints(); @@ -116,7 +128,8 @@ public: private: Overseer *os; std::vector endpointHandlers; - std::function changeFrontDefaults; + std::function changeFrontDefaults; + std::function removeEndpointWidget; //std::function updateFrontVolumeCallback; //std::function updateFrontMuteCallback; diff --git a/src/global.h b/src/global.h index 0ae2a75..0d7de5e 100644 --- a/src/global.h +++ b/src/global.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "debug.h" diff --git a/src/qt/qtclasses.cpp b/src/qt/qtclasses.cpp index 38b0e44..6a49b52 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -1,9 +1,12 @@ #include "qtclasses.h" - +EndpointWidgetEvent::EndpointWidgetEvent(QEvent::Type type, int idx) : QEvent(type){ + this->idx = idx; +} bool ExtendedCheckBox::event(QEvent* ev) { if (ev->type() == QEvent::User) { + //todo: still prone to bugs; whack-a-mole to come this->blockSignals(true); if (this->isEnabled()) { this->setCheckState(Qt::Checked); @@ -19,11 +22,11 @@ bool ExtendedCheckBox::event(QEvent* ev) { return QCheckBox::event(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; + this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ACTIVE, idx); layout = new QGridLayout(this); //this->setLayout(layout); log_debugcpp("epw main layout parent: "<< layout->parent()); @@ -178,6 +181,31 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare log_debugcpp("ENDPOINT_WIDGETED"); } +void MainWindow::customEvent(QEvent* ev) { + if (ev->type() == (QEvent::Type)CustomQEvent::EndpointWidgetObsolete) { + this->removeEndpointWidget((EndpointWidgetEvent*)ev); + return; + } + // Make sure the rest of events are handled + return QMainWindow::customEvent(ev); +} + +void MainWindow::removeEndpointWidget(EndpointWidgetEvent* ev){ + uint64_t i = ev->idx; + this->ews.at(i)->setParent(nullptr); + this->layout->removeWidget(ews.at(i)); + uint64_t saisu = ews.size(); + //delete ews.at(index); + while ((i + 1) < ews.size()) { + ews.at(i) = ews.at(i + 1); + ews.at(i)->updateEndpointHandlerFrontInfo(i); + i++; + } + ews.pop_back(); + return; +} + + void EndpointWidget::updateMute(int checked){ bool muted = (checked == 2 ? true : false); this->eph->setMute(osh->getGuid(), muted); @@ -223,6 +251,11 @@ EndpointHandler* EndpointWidget::getEndpointHandler(){ return this->eph; } +void EndpointWidget::updateEndpointHandlerFrontInfo(uint64_t index){ + this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ACTIVE, index); +} + + void EndpointWidget::setIndex(uint64_t idx){ this->idx = idx; } @@ -234,18 +267,24 @@ uint64_t EndpointWidget::getIndex(){ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { // setWindowState(Qt::WindowFullScreen); // setCentralWidget(centralWidget); + + /* + * Registering needed custom events + */ + QEvent::registerEventType(CustomQEvent::EndpointWidgetObsolete); + widget = new QWidget(); layout = new QGridLayout(); trayIcon = new QSystemTrayIcon(); trayIconMenu = new QMenu(); trayIconMenuQuit = new QAction(STRING_QUIT); + changeDefaultCheckboxEnablement = new QEvent(QEvent::User); changeDefaultCheckboxEnablement->setAccepted(true); widget->setLayout(layout); setCentralWidget(widget); //layout->addWidget(pintas, 0, 0); - setWindowTitle(STRING_TITLE); reloadEndpointWidgets(); @@ -266,7 +305,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::trayIconActivated); /* - * Set of function callback definitinos for EndpointSituationCallback + * Set of function callback definitons for EndpointSituationCallback */ osh->setChangeFrontDefaultsFunction([this](Roles role, std::wstring endpointId) { for (auto epw : this->ews) { @@ -306,8 +345,23 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { } } }); + + osh->setRemoveEndpointWidgetFunction([this](uint64_t index) { + EndpointWidgetEvent removeObsoleteEndpointWidget((QEvent::Type)CustomQEvent::EndpointWidgetObsolete, index); + removeObsoleteEndpointWidget.setAccepted(true); + QCoreApplication::instance()->postEvent(this, &removeObsoleteEndpointWidget); + }); + + /* + * osh->setReviseEndpointShowingFunction([this](std::wstring endpointId, Roles role){ + * + * + * }); + */ + } + void MainWindow::closeEvent(QCloseEvent *event) { if (!event->spontaneous() || !isVisible()) return; @@ -338,7 +392,7 @@ void MainWindow::reloadEndpointWidgets() { 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 + //alfinal estoes solopara inicializarlmao ews.push_back(epw); layout->addWidget(epw, i, 0); } diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index 77265e8..b81dbed 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -56,7 +56,17 @@ * ToggleButton(QWidget *parent = nullptr); * }; */ +enum CustomQEvent { + EndpointWidgetObsolete = 1001, +}; +class EndpointWidgetEvent : public QEvent { + Q_OBJECT + +public: + EndpointWidgetEvent(QEvent::Type type, int idx); + uint64_t idx; +}; class ExtendedCheckBox : public QCheckBox { Q_OBJECT @@ -76,6 +86,8 @@ public: EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *parent = nullptr); EndpointHandler* getEndpointHandler(); + void updateEndpointHandlerFrontInfo(uint64_t index); + void setIndex(uint64_t idx); uint64_t getIndex(); @@ -124,9 +136,11 @@ public: protected: void closeEvent(QCloseEvent *event) override; - + void customEvent(QEvent* ev) override; + private slots: void trayIconActivated(QSystemTrayIcon::ActivationReason reason); + void removeEndpointWidget(EndpointWidgetEvent* ev); //TODO: destroy/empty existing EndpointWidgets //void setEndpointHandlers(std::vector *ephs); @@ -140,6 +154,7 @@ private: QMenu *trayIconMenu; QAction *trayIconMenuQuit; QEvent* changeDefaultCheckboxEnablement; + //public slots: // void setEndpointHandlers(std::vector *ephs);