diff --git a/src/back/backlasses.cpp b/src/back/backlasses.cpp index 8983942..66a8015 100644 --- a/src/back/backlasses.cpp +++ b/src/back/backlasses.cpp @@ -53,18 +53,28 @@ HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify } //memcpy(&osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller, &pNotify->guidEventContext,sizeof(NGuid) ); - - - osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->muted = pNotify->bMuted; - osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->mainVolume = pNotify->fMasterVolume; - osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->channels = pNotify->nChannels; + Flows flow = this->ep->getFlow(); + EndpointHandler* eph = nullptr; + if (flow & Flows::FLOW_PLAYBACK) { + eph = osh->getPlaybackEndpointHandlers().at(this->ep->getIndex()); + } else { + eph = osh->getCaptureEndpointHandlers().at(this->ep->getIndex()); + } + + eph->getCallbackInfo()->muted = pNotify->bMuted; + eph->getCallbackInfo()->mainVolume = pNotify->fMasterVolume; + eph->getCallbackInfo()->channels = pNotify->nChannels; + - UINT j = 0; - //todo: do while here caused stack corruption; sus - while(j < pNotify->nChannels) { - osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j]; - j++; - } + UINT j = 0; + //todo: do while here caused stack corruption; sus + while(j < pNotify->nChannels) { + if (flow & Flows::FLOW_PLAYBACK) + eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j]; + else + eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j]; + j++; + } return S_OK; } @@ -191,7 +201,9 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ //todo: preguntitas owindows dword no es uint32_t even tho mingw mingas if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-1);}; - activateEndpointVolume(); + if(this->endpointState == EndpointState::ENDPOINT_ACTIVE) { + activateEndpointVolume(); + } reloadEndpointChannels(); @@ -214,6 +226,8 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ friendlyName = L"Unnamed Not Present Endpoint"; else friendlyName = std::wstring(pv.pwszVal); + + this->setFlow(); } /* @@ -222,13 +236,27 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ void Endpoint::activateEndpointVolume() { - if (this->endpointVolume == nullptr) - if(FAILED(endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&this->endpointVolume))) { log_debugcpp(std::string("no endpointVolume (IAudioEndpointVolume)")); }; + //bool extraThread = false; + /* + * Forgive me, for MS has sinned, and now I must too. + */ + if (this->endpointVolume == nullptr){ + HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&this->endpointVolume); + //if (endpointVolume == nullptr) { //why they returning 0 after dealing with the error jfc CO_E_NOTINITIALIZED) { + //CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); + //extraThread = true; + //goto initialized; + //} + //log_debugcpp(std::string("no endpointVolume (IAudioEndpointVolume)")); + if (result == S_OK) + CoUninitialize(); + } } void Endpoint::reloadEndpointChannels() { if (this->endpointState == DEVICE_STATE_ACTIVE) { - if (FAILED(endpointVolume->GetChannelCount(&channelCount))) {};/* log_debugcpp("get channel count fail"); */ + if (FAILED(endpointVolume->GetChannelCount(&channelCount))) {log_debugcpp("get channel count fail");};/* */ } } @@ -272,8 +300,10 @@ bool Endpoint::getMute(){ void Endpoint::setState(uint8_t state){ this->endpointState = state; - if(state == EndpointState::ENDPOINT_ACTIVE) + if(state == EndpointState::ENDPOINT_ACTIVE) { + this->activateEndpointVolume(); this->reloadEndpointChannels(); + } } size_t Endpoint::getState(){ @@ -468,7 +498,7 @@ void Overseer::reloadEndpoints(Flows flow) { for (unsigned int i = 0; i < numEndpoints; i++){ if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); }; Endpoint *endpoint = new Endpoint(temp, i); - endpoint->setFlow(); + //endpoint->setIndex(i); if (flow == Flows::FLOW_PLAYBACK) this->playbackDevices.push_back(endpoint); diff --git a/src/cont/contclasses.cpp b/src/cont/contclasses.cpp index 937ee67..ef2cbfb 100644 --- a/src/cont/contclasses.cpp +++ b/src/cont/contclasses.cpp @@ -14,15 +14,14 @@ EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) { //epName = ep->getName(); this->setBackEndpointVolumeCallbackInfoContent(this->getState()); osh->pushBackEndpointHandler(this, flow); - } void OverseerHandler::pushBackEndpointHandler(EndpointHandler* eph, Flows flow) { if (eph == nullptr) return; - if (flow = Flows::FLOW_PLAYBACK) - playbackEndpointHandlers.push_back(eph); + if (flow == Flows::FLOW_PLAYBACK) + this->playbackEndpointHandlers.push_back(eph); else - captureEndpointHandlers.push_back(eph); + this->captureEndpointHandlers.push_back(eph); return; } @@ -39,6 +38,10 @@ EndpointState EndpointHandler::getFrontVisibilityState(){ return ephfv.visibility; } +Flows EndpointHandler::getFlow(){ + return ep->getFlow(); +} + /* these two, currently unused. If I use them, I should feel bad. * Endpoint* EndpointHandler::getEndpoint() { * return this->ep; @@ -212,16 +215,16 @@ void OverseerHandler::reloadEndpointHandlers(){ //setEndpointHandlers(ephs); } -EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId){ - Flows flow; - Endpoint* newEp = this->os->addEndpoint(endpointId, &flow); +EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId, /* out */ Flows *flow = nullptr){ + Flows localFlow; + Endpoint* newEp = this->os->addEndpoint(endpointId, &localFlow); - uint64_t ephIdx = (flow == Flows::FLOW_PLAYBACK ? this->getPlaybackEndpointsCount() : this->getCaptureEndpointsCount()); + uint64_t ephIdx = (localFlow == Flows::FLOW_PLAYBACK ? this->getPlaybackEndpointsCount() : this->getCaptureEndpointsCount()) - 1; - EndpointHandler* newEph = new EndpointHandler(ephIdx, flow); + EndpointHandler* newEph = new EndpointHandler(ephIdx, localFlow); // std::vector getPlaybackEndpointHandlers(); //std::vector getCaptureEndpointHandlers(); - + if (flow != nullptr) *flow = localFlow; return newEph; } @@ -238,24 +241,34 @@ void OverseerHandler::changeFrontDefaultsCallback(Roles role, std::wstring endpo } void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointState state) { + std::vector allHandlers; + allHandlers.insert(allHandlers.end(), this->captureEndpointHandlers.begin(), this->captureEndpointHandlers.end()); + allHandlers.insert(allHandlers.end(), this->playbackEndpointHandlers.begin(), this->playbackEndpointHandlers.end()); EndpointHandler* eph = nullptr; - for (auto loopEph : this->playbackEndpointHandlers) { + for (auto loopEph : allHandlers) { if (loopEph->getId() == endpointId) { eph = loopEph; break; } } + //debug + Flows flow; if (!eph) { - - } + if (state ^ EndpointState::ENDPOINT_ACTIVE) return; + //return; + //flow = Flows::FLOW_CAPTURE; + eph = osh->addEndpoint(endpointId, &flow); + } else + flow = eph->getFlow(); - //todo: testing missing shiez. sowwy - //if(!eph) osh-> + //todo: mic done but disabled. Tab-kun will come... + if (flow == Flows::FLOW_CAPTURE) return; - if(EndpointState::ENDPOINT_ACTIVE & state) { + + if(eph && EndpointState::ENDPOINT_ACTIVE & state) { this->addEndpointWidget(eph); - } else if (eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE){ + } else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE){ this->removeEndpointWidget(eph->getFrontVisibilityIndex()); } return; diff --git a/src/cont/contclasses.h b/src/cont/contclasses.h index b64389d..85ecff9 100644 --- a/src/cont/contclasses.h +++ b/src/cont/contclasses.h @@ -134,7 +134,7 @@ public: uint64_t getPlaybackEndpointsCount(); uint64_t getCaptureEndpointsCount(); void reloadEndpointHandlers(); - EndpointHandler* addEndpoint(std::wstring endpointId); + EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow); NGuid getGuid(); private: diff --git a/src/qt/qtclasses.cpp b/src/qt/qtclasses.cpp index da01a60..d47bd72 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -85,7 +85,8 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare /* * Channel sliders setup */ - for(uint32_t i = 0; i < eph->getChannelCount(); i++){ + uint32_t epChannelCount = eph->getChannelCount(); + for(uint32_t i = 0; i < epChannelCount && epChannelCount > 1; i++){ QSlider* tmp = new QSlider(Qt::Horizontal); QLabel* tmpLb = new QLabel(""); tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -163,7 +164,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare mainSlider->setValue((int)((eph->getCallbackInfo()->mainVolume + roundingFactor) * 100)); muteButton->setCheckState((eph->getCallbackInfo()->muted == false ? Qt::Unchecked : Qt::Checked)); muteButton->setText(eph->getCallbackInfo()->muted ? STRING_UNMUTE : STRING_MUTE); - for(uint32_t i = 0; i < eph->getCallbackInfo()->channels; i++){ + for(uint32_t i = 0; i < eph->getCallbackInfo()->channels && eph->getChannelCount() > 1; i++){ this->channelSliders.at(i)->blockSignals(true); this->channelSliders.at(i)->setValue((int)((eph->getCallbackInfo()->channelVolumes[i] + roundingFactor) * 100)); this->channelLabels.at(i)->setText(QString::number((int)((eph->getCallbackInfo()->channelVolumes[i] + roundingFactor) * 100))); @@ -210,15 +211,20 @@ void MainWindow::removeEndpointWidget(EndpointWidgetEvent* ev){ uint64_t i = ev->payload; this->ews.at(i)->setParent(nullptr); this->layout->removeWidget(ews.at(i)); - uint64_t saisu = ews.size(); + //uint64_t saisu = ews.size(); //delete ews.at(index); delete ews.at(i); - while ((i + 1) < ews.size()) { - ews.at(i) = ews.at(i + 1); - ews.at(i)->setIndex(i); - i++; - } - ews.pop_back(); + ews.at(i) = nullptr; + this->ewsUpdateTimer->start(); + + /* + * while ((i + 1) < ews.size()) { + * ews.at(i) = ews.at(i + 1); + * ews.at(i)->setIndex(i); + * i++; + * } + * ews.pop_back(); + */ return; } @@ -229,6 +235,34 @@ void MainWindow::addEndpointWidget(EndpointWidgetEvent* ev){ return; } +void MainWindow::reorderEndpointWidgetCollection() { + size_t firstNullPosition = 0; + size_t ewsSize = ews.size(); + bool breakSorting = false; + + //todo: is all of gui really atomic by definition? im afraid of cutting through amazing add momentos, but I think I did my homework. Must check back. + for (size_t i = 0; i < ewsSize; i++) { + if (ews.at(i) == nullptr) { + for (size_t j = (i + 1); j < ewsSize; j++) { + + if (ews.at(j) != nullptr) { + ews.at(i) = ews.at(j); + ews.at(i)->setIndex(i); + ews.at(j) = nullptr; + break; + } + if (j == ewsSize - 1) { + firstNullPosition = i; + breakSorting = true; + } + + } + if (breakSorting) break; + } + } + ews.resize(firstNullPosition + 1); +} + void EndpointWidget::updateMute(int checked){ bool muted = (checked == 2 ? true : false); this->eph->setMute(osh->getGuid(), muted); @@ -304,13 +338,17 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { QEvent::registerEventType(CustomQEvent::EndpointWidgetObsolete); QEvent::registerEventType(CustomQEvent::EndpointWidgetCreated); QEvent::registerEventType(CustomQEvent::EndpointDefaultChange); - + + ewsUpdateTimer = new QTimer(this); widget = new QWidget(); layout = new QGridLayout(); trayIcon = new QSystemTrayIcon(); trayIconMenu = new QMenu(); trayIconMenuQuit = new QAction(STRING_QUIT); + ewsUpdateTimer->setSingleShot(true); + ewsUpdateTimer->setInterval(ewsUpdateTimerFrequency); + connect(ewsUpdateTimer, &QTimer::timeout, this, &MainWindow::reorderEndpointWidgetCollection); widget->setLayout(layout); setCentralWidget(widget); //layout->addWidget(pintas, 0, 0); diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index 9a40d39..6f1a51e 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -150,6 +150,7 @@ private slots: void trayIconActivated(QSystemTrayIcon::ActivationReason reason); void removeEndpointWidget(EndpointWidgetEvent* ev); void addEndpointWidget(EndpointWidgetEvent* ev); + void reorderEndpointWidgetCollection(); //TODO: destroy/empty existing EndpointWidgets //void setEndpointHandlers(std::vector *ephs); @@ -162,7 +163,8 @@ private: QSystemTrayIcon *trayIcon; QMenu *trayIconMenu; QAction *trayIconMenuQuit; - + QTimer *ewsUpdateTimer; + static constexpr uint64_t ewsUpdateTimerFrequency = 500; //public slots: // void setEndpointHandlers(std::vector *ephs);