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,16 +53,26 @@ HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify
}
//memcpy(&osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller, &pNotify->guidEventContext,sizeof(NGuid) );
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;
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;
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];
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);};
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);

View file

@ -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<EndpointHandler*> getPlaybackEndpointHandlers();
//std::vector<EndpointHandler*> 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<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;
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: mic done but disabled. Tab-kun will come...
if (flow == Flows::FLOW_CAPTURE) return;
//todo: testing missing shiez. sowwy
//if(!eph) osh->
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;

View file

@ -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:

View file

@ -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<uint64_t>* 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<EndpointHandler*>* 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);
@ -305,12 +339,16 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
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);

View file

@ -150,6 +150,7 @@ private slots:
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
void removeEndpointWidget(EndpointWidgetEvent<uint64_t>* ev);
void addEndpointWidget(EndpointWidgetEvent<EndpointHandler*>* ev);
void reorderEndpointWidgetCollection();
//TODO: destroy/empty existing EndpointWidgets
//void setEndpointHandlers(std::vector<EndpointHandler*> *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<EndpointHandler*> *ephs);