mic back/cont & plug/unplug done; devicead/rem to go

This commit is contained in:
Hane 2023-09-15 19:29:41 +02:00
commit 6f8455c63d
5 changed files with 129 additions and 46 deletions

View file

@ -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) ); //memcpy(&osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller, &pNotify->guidEventContext,sizeof(NGuid) );
Flows flow = this->ep->getFlow();
EndpointHandler* eph = nullptr;
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->muted = pNotify->bMuted; if (flow & Flows::FLOW_PLAYBACK) {
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->mainVolume = pNotify->fMasterVolume; eph = osh->getPlaybackEndpointHandlers().at(this->ep->getIndex());
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->channels = pNotify->nChannels; } 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; UINT j = 0;
//todo: do while here caused stack corruption; sus //todo: do while here caused stack corruption; sus
while(j < pNotify->nChannels) { while(j < pNotify->nChannels) {
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j]; if (flow & Flows::FLOW_PLAYBACK)
j++; eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j];
} else
eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j];
j++;
}
return S_OK; 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 //todo: preguntitas owindows dword no es uint32_t even tho mingw mingas
if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-1);}; if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-1);};
activateEndpointVolume(); if(this->endpointState == EndpointState::ENDPOINT_ACTIVE) {
activateEndpointVolume();
}
reloadEndpointChannels(); reloadEndpointChannels();
@ -214,6 +226,8 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){
friendlyName = L"Unnamed Not Present Endpoint"; friendlyName = L"Unnamed Not Present Endpoint";
else else
friendlyName = std::wstring(pv.pwszVal); friendlyName = std::wstring(pv.pwszVal);
this->setFlow();
} }
/* /*
@ -222,13 +236,27 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){
void Endpoint::activateEndpointVolume() { void Endpoint::activateEndpointVolume() {
if (this->endpointVolume == nullptr) //bool extraThread = false;
if(FAILED(endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&this->endpointVolume))) { log_debugcpp(std::string("no endpointVolume (IAudioEndpointVolume)")); }; /*
* 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() { void Endpoint::reloadEndpointChannels() {
if (this->endpointState == DEVICE_STATE_ACTIVE) { 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){ void Endpoint::setState(uint8_t state){
this->endpointState = state; this->endpointState = state;
if(state == EndpointState::ENDPOINT_ACTIVE) if(state == EndpointState::ENDPOINT_ACTIVE) {
this->activateEndpointVolume();
this->reloadEndpointChannels(); this->reloadEndpointChannels();
}
} }
size_t Endpoint::getState(){ size_t Endpoint::getState(){
@ -468,7 +498,7 @@ void Overseer::reloadEndpoints(Flows flow) {
for (unsigned int i = 0; i < numEndpoints; i++){ for (unsigned int i = 0; i < numEndpoints; i++){
if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); }; if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); };
Endpoint *endpoint = new Endpoint(temp, i); Endpoint *endpoint = new Endpoint(temp, i);
endpoint->setFlow();
//endpoint->setIndex(i); //endpoint->setIndex(i);
if (flow == Flows::FLOW_PLAYBACK) if (flow == Flows::FLOW_PLAYBACK)
this->playbackDevices.push_back(endpoint); this->playbackDevices.push_back(endpoint);

View file

@ -14,15 +14,14 @@ EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) {
//epName = ep->getName(); //epName = ep->getName();
this->setBackEndpointVolumeCallbackInfoContent(this->getState()); this->setBackEndpointVolumeCallbackInfoContent(this->getState());
osh->pushBackEndpointHandler(this, flow); osh->pushBackEndpointHandler(this, flow);
} }
void OverseerHandler::pushBackEndpointHandler(EndpointHandler* eph, Flows flow) { void OverseerHandler::pushBackEndpointHandler(EndpointHandler* eph, Flows flow) {
if (eph == nullptr) return; if (eph == nullptr) return;
if (flow = Flows::FLOW_PLAYBACK) if (flow == Flows::FLOW_PLAYBACK)
playbackEndpointHandlers.push_back(eph); this->playbackEndpointHandlers.push_back(eph);
else else
captureEndpointHandlers.push_back(eph); this->captureEndpointHandlers.push_back(eph);
return; return;
} }
@ -39,6 +38,10 @@ EndpointState EndpointHandler::getFrontVisibilityState(){
return ephfv.visibility; return ephfv.visibility;
} }
Flows EndpointHandler::getFlow(){
return ep->getFlow();
}
/* these two, currently unused. If I use them, I should feel bad. /* these two, currently unused. If I use them, I should feel bad.
* Endpoint* EndpointHandler::getEndpoint() { * Endpoint* EndpointHandler::getEndpoint() {
* return this->ep; * return this->ep;
@ -212,16 +215,16 @@ void OverseerHandler::reloadEndpointHandlers(){
//setEndpointHandlers(ephs); //setEndpointHandlers(ephs);
} }
EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId){ EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId, /* out */ Flows *flow = nullptr){
Flows flow; Flows localFlow;
Endpoint* newEp = this->os->addEndpoint(endpointId, &flow); 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<EndpointHandler*> getPlaybackEndpointHandlers(); // std::vector<EndpointHandler*> getPlaybackEndpointHandlers();
//std::vector<EndpointHandler*> getCaptureEndpointHandlers(); //std::vector<EndpointHandler*> getCaptureEndpointHandlers();
if (flow != nullptr) *flow = localFlow;
return newEph; return newEph;
} }
@ -238,24 +241,34 @@ void OverseerHandler::changeFrontDefaultsCallback(Roles role, std::wstring endpo
} }
void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointState state) { void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointState state) {
std::vector<EndpointHandler*> allHandlers;
allHandlers.insert(allHandlers.end(), this->captureEndpointHandlers.begin(), this->captureEndpointHandlers.end());
allHandlers.insert(allHandlers.end(), this->playbackEndpointHandlers.begin(), this->playbackEndpointHandlers.end());
EndpointHandler* eph = nullptr; EndpointHandler* eph = nullptr;
for (auto loopEph : this->playbackEndpointHandlers) { for (auto loopEph : allHandlers) {
if (loopEph->getId() == endpointId) { if (loopEph->getId() == endpointId) {
eph = loopEph; eph = loopEph;
break; break;
} }
} }
//debug
Flows flow;
if (!eph) { 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 //todo: mic done but disabled. Tab-kun will come...
//if(!eph) osh-> if (flow == Flows::FLOW_CAPTURE) return;
if(EndpointState::ENDPOINT_ACTIVE & state) {
if(eph && EndpointState::ENDPOINT_ACTIVE & state) {
this->addEndpointWidget(eph); this->addEndpointWidget(eph);
} else if (eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE){ } else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE){
this->removeEndpointWidget(eph->getFrontVisibilityIndex()); this->removeEndpointWidget(eph->getFrontVisibilityIndex());
} }
return; return;

View file

@ -134,7 +134,7 @@ public:
uint64_t getPlaybackEndpointsCount(); uint64_t getPlaybackEndpointsCount();
uint64_t getCaptureEndpointsCount(); uint64_t getCaptureEndpointsCount();
void reloadEndpointHandlers(); void reloadEndpointHandlers();
EndpointHandler* addEndpoint(std::wstring endpointId); EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow);
NGuid getGuid(); NGuid getGuid();
private: private:

View file

@ -85,7 +85,8 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare
/* /*
* Channel sliders setup * 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); QSlider* tmp = new QSlider(Qt::Horizontal);
QLabel* tmpLb = new QLabel(""); QLabel* tmpLb = new QLabel("");
tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 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)); mainSlider->setValue((int)((eph->getCallbackInfo()->mainVolume + roundingFactor) * 100));
muteButton->setCheckState((eph->getCallbackInfo()->muted == false ? Qt::Unchecked : Qt::Checked)); muteButton->setCheckState((eph->getCallbackInfo()->muted == false ? Qt::Unchecked : Qt::Checked));
muteButton->setText(eph->getCallbackInfo()->muted ? STRING_UNMUTE : STRING_MUTE); 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)->blockSignals(true);
this->channelSliders.at(i)->setValue((int)((eph->getCallbackInfo()->channelVolumes[i] + roundingFactor) * 100)); 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))); this->channelLabels.at(i)->setText(QString::number((int)((eph->getCallbackInfo()->channelVolumes[i] + roundingFactor) * 100)));
@ -210,15 +211,20 @@ void MainWindow::removeEndpointWidget(EndpointWidgetEvent<uint64_t>* ev){
uint64_t i = ev->payload; uint64_t i = ev->payload;
this->ews.at(i)->setParent(nullptr); this->ews.at(i)->setParent(nullptr);
this->layout->removeWidget(ews.at(i)); this->layout->removeWidget(ews.at(i));
uint64_t saisu = ews.size(); //uint64_t saisu = ews.size();
//delete ews.at(index); //delete ews.at(index);
delete ews.at(i); delete ews.at(i);
while ((i + 1) < ews.size()) { ews.at(i) = nullptr;
ews.at(i) = ews.at(i + 1); this->ewsUpdateTimer->start();
ews.at(i)->setIndex(i);
i++; /*
} * while ((i + 1) < ews.size()) {
ews.pop_back(); * ews.at(i) = ews.at(i + 1);
* ews.at(i)->setIndex(i);
* i++;
* }
* ews.pop_back();
*/
return; return;
} }
@ -229,6 +235,34 @@ void MainWindow::addEndpointWidget(EndpointWidgetEvent<EndpointHandler*>* ev){
return; 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){ void EndpointWidget::updateMute(int checked){
bool muted = (checked == 2 ? true : false); bool muted = (checked == 2 ? true : false);
this->eph->setMute(osh->getGuid(), muted); this->eph->setMute(osh->getGuid(), muted);
@ -304,13 +338,17 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
QEvent::registerEventType(CustomQEvent::EndpointWidgetObsolete); QEvent::registerEventType(CustomQEvent::EndpointWidgetObsolete);
QEvent::registerEventType(CustomQEvent::EndpointWidgetCreated); QEvent::registerEventType(CustomQEvent::EndpointWidgetCreated);
QEvent::registerEventType(CustomQEvent::EndpointDefaultChange); QEvent::registerEventType(CustomQEvent::EndpointDefaultChange);
ewsUpdateTimer = new QTimer(this);
widget = new QWidget(); widget = new QWidget();
layout = new QGridLayout(); layout = new QGridLayout();
trayIcon = new QSystemTrayIcon(); trayIcon = new QSystemTrayIcon();
trayIconMenu = new QMenu(); trayIconMenu = new QMenu();
trayIconMenuQuit = new QAction(STRING_QUIT); trayIconMenuQuit = new QAction(STRING_QUIT);
ewsUpdateTimer->setSingleShot(true);
ewsUpdateTimer->setInterval(ewsUpdateTimerFrequency);
connect(ewsUpdateTimer, &QTimer::timeout, this, &MainWindow::reorderEndpointWidgetCollection);
widget->setLayout(layout); widget->setLayout(layout);
setCentralWidget(widget); setCentralWidget(widget);
//layout->addWidget(pintas, 0, 0); //layout->addWidget(pintas, 0, 0);

View file

@ -150,6 +150,7 @@ private slots:
void trayIconActivated(QSystemTrayIcon::ActivationReason reason); void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
void removeEndpointWidget(EndpointWidgetEvent<uint64_t>* ev); void removeEndpointWidget(EndpointWidgetEvent<uint64_t>* ev);
void addEndpointWidget(EndpointWidgetEvent<EndpointHandler*>* ev); void addEndpointWidget(EndpointWidgetEvent<EndpointHandler*>* ev);
void reorderEndpointWidgetCollection();
//TODO: destroy/empty existing EndpointWidgets //TODO: destroy/empty existing EndpointWidgets
//void setEndpointHandlers(std::vector<EndpointHandler*> *ephs); //void setEndpointHandlers(std::vector<EndpointHandler*> *ephs);
@ -162,7 +163,8 @@ private:
QSystemTrayIcon *trayIcon; QSystemTrayIcon *trayIcon;
QMenu *trayIconMenu; QMenu *trayIconMenu;
QAction *trayIconMenuQuit; QAction *trayIconMenuQuit;
QTimer *ewsUpdateTimer;
static constexpr uint64_t ewsUpdateTimerFrequency = 500;
//public slots: //public slots:
// void setEndpointHandlers(std::vector<EndpointHandler*> *ephs); // void setEndpointHandlers(std::vector<EndpointHandler*> *ephs);