diff --git a/qtest.pro b/qtest.pro index dd5e215..046d8d8 100644 --- a/qtest.pro +++ b/qtest.pro @@ -9,8 +9,8 @@ QT += widgets network INCLUDEPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont" DESTPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont" VPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont" -SOURCES += qtestmain.cpp qtclasses.cpp backlasses.cpp contclasses.cpp -HEADERS += qtclasses.h backlasses.h contclasses.h global.h debug.h backfuncs.h ipolicyconfig.h +SOURCES += qtestmain.cpp qtclasses.cpp backlasses.cpp backsessionclasses.cpp contclasses.cpp contsessionclasses.cpp +HEADERS += qtclasses.h backlasses.h backsessionclasses.h contclasses.h contsessionclasses.h global.h debug.h backfuncs.h ipolicyconfig.h msinclude.h RESOURCES = assets.qrc #DESTDIR += "build" diff --git a/src/back/backfuncs.h b/src/back/backfuncs.h index 1062ba1..b8e1c6c 100644 --- a/src/back/backfuncs.h +++ b/src/back/backfuncs.h @@ -1,4 +1,4 @@ -GUID NGuidToGUID(NGuid guid) { +GUID inline NGuidToGUID(NGuid guid) { GUID msGuid = GUID(); msGuid.Data1 = guid.data1; msGuid.Data2 = guid.data2; @@ -15,7 +15,7 @@ GUID NGuidToGUID(NGuid guid) { return msGuid; } -NGuid GUIDToNGuid(LPGUID msGuid){ +NGuid inline GUIDToNGuid(LPGUID msGuid){ NGuid guid = NGuid(); guid.data1 = msGuid->Data1; guid.data2 = msGuid->Data2; diff --git a/src/back/backlasses.cpp b/src/back/backlasses.cpp index 66a8015..dea09b6 100644 --- a/src/back/backlasses.cpp +++ b/src/back/backlasses.cpp @@ -207,7 +207,7 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ reloadEndpointChannels(); - /* + /* todo: check header * if(FAILED(endpoint->Activate(__uuidof(IAudioMeterInformation), * CLSCTX_ALL, NULL, (void**)&endpointPeakMeter))) { log_debugcpp("peakbros..."); } */ @@ -228,12 +228,37 @@ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ friendlyName = std::wstring(pv.pwszVal); this->setFlow(); + if (this->endpointState == EndpointState::ENDPOINT_ACTIVE && this->flow == Flows::FLOW_PLAYBACK) { + activateEndpointSessions(); + } } /* * Endpoint::Endpoint(IMMDevice* endpoint) : Endpoint(endpoint, 0) {}; */ +void Endpoint::activateEndpointSessions() { + //sessionManager; + if (FAILED(endpoint->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**) &sessionManager))) { log_wdebugcpp(L"sesionbros..."); return; } + + IAudioSessionEnumerator* sessionEnumerator = nullptr; + if (FAILED(sessionManager->GetSessionEnumerator(&sessionEnumerator))) { log_wdebugcpp(L"sesEnumeratorBros..."); return; } + + int sessionCount; + sessionEnumerator->GetCount(&sessionCount); + for (int i = 0; i < sessionCount; i++) { + IAudioSessionControl* sessionControlTmp; + sessionEnumerator->GetSession(i, (IAudioSessionControl**)&sessionControlTmp); + //todo:: asegurar lo del dynamic_cast + IAudioSessionControl2* sessionControl; + sessionControlTmp->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl); + sessionControl->AddRef(); + sessionControlTmp->Release(); + Session* session = new Session(this, sessionControl, (size_t)i); + endpointSessions.push_back(session); + } + sessionEnumerator->Release(); +} void Endpoint::activateEndpointVolume() { //bool extraThread = false; @@ -444,11 +469,21 @@ Flows Endpoint::getFlow() { return this->flow; } +/* sessions */ +std::vector Endpoint::getSessions() { + return endpointSessions; +} + +size_t Endpoint::getSessionCount() { + return endpointSessions.size(); +} + Endpoint::~Endpoint(){ - log_debugcpp("murio endpoint-san uwu"); + log_wdebugcpp(L"murio endpoint-san uwu"); properties->Release(); endpointVolume->Release(); endpoint->Release(); + sessionManager->Release(); } void Overseer::initCOMLibrary() { diff --git a/src/back/backlasses.h b/src/back/backlasses.h index ebfc07e..453e7a5 100644 --- a/src/back/backlasses.h +++ b/src/back/backlasses.h @@ -1,33 +1,12 @@ #pragma once -#define _WIN32_WINNT 0x0A00 -#include - -//done by qt by def #define UNICODE - -#include -#include -#include -#include -#include -#include -#include -//#include - -#include -#include -#include -//#include -//#include -#include -#include -#include "ipolicyconfig.h" -#include - +#include "msinclude.h" +#include "backsessionclasses.h" #include "global.h" #include "contclasses.h" class EndpointVolumeCallback; +class Session; class Endpoint { @@ -53,15 +32,25 @@ class Endpoint { Flows getFlow(); std::wstring getId(); std::wstring getName(); + + void setVolumeCallback(EndpointVolumeCallback *epc); void removeVolumeCallback(EndpointVolumeCallback *epc); + + /* sessions */ + std::vector getSessions(); + size_t getSessionCount(); + ~Endpoint(); private: void inline activateEndpointVolume(); - + void inline activateEndpointSessions(); + + std::vector endpointSessions; uint32_t channelCount = 0; IMMDevice* endpoint; + IAudioSessionManager2 *sessionManager; Flows flow; IAudioEndpointVolume *endpointVolume = nullptr; IPropertyStore *properties; diff --git a/src/back/backsessionclasses.cpp b/src/back/backsessionclasses.cpp new file mode 100644 index 0000000..fce5ad8 --- /dev/null +++ b/src/back/backsessionclasses.cpp @@ -0,0 +1,62 @@ +#include "backsessionclasses.h" +#include "backfuncs.h" +Session::Session(Endpoint* ep, IAudioSessionControl2* sessionControl, size_t idx) { + this->ep = ep; + this->sessionControl = sessionControl; + this->idx = idx; + + sessionControl->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&sessionVolume); + DWORD pid; + sessionControl->GetProcessId(&pid); + if (sessionControl->IsSystemSoundsSession() == S_OK) + this->sessionName = std::wstring(LSTRING_SYSTEM_SOUNDS); + else { + LPWSTR sessionDisplayName; + this->sessionControl->GetDisplayName(&sessionDisplayName); + this->sessionName = std::wstring(sessionDisplayName); + CoTaskMemFree(sessionDisplayName); + } +} + +float Session::getVolume(int channel){ + float volume; + if (channel == AudioChannel::CHANNEL_MAIN) { + if(FAILED(sessionVolume->GetMasterVolume(&volume))) { /* log_debugcpp("si") */;} + } else { + return 0.0; + //if(FAILED(endpointVolume->GetChannelVolumeLevelScalar(channel, &volume))) { /* log_debugcpp("si"); */} + } + return volume; +} + +/* + * uint32_t Endpoint::getChannelCount(){ + * return (uint32_t)channelCount; + * } + */ + +std::wstring Session::getName() { + return sessionName; +} + +bool Session::getMute() { + BOOL mut; + if(FAILED(sessionVolume->GetMute(&mut))) { /* TIP: Below */ } + bool mute = (bool)mut; + return mute; +} + +void Session::setVolume(NGuid guid, int channel, float volume) { + //TIP: There used to be log messages here. Now, it's a ghost town. + GUID tempMsGuid = NGuidToGUID(guid); + if (channel == AudioChannel::CHANNEL_MAIN) { + if(FAILED(sessionVolume->SetMasterVolume(volume, &tempMsGuid))) {}; + } else { + //if(FAILED(sessionVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) {}; + } +} + +void Session::setMute(NGuid guid, bool muted) { + GUID tempMsGuid = NGuidToGUID(guid); + if(FAILED(sessionVolume->SetMute(muted, &tempMsGuid))) { log_wdebugcpp(std::wstring(L"SessionVolume null?")); }; +} diff --git a/src/back/backsessionclasses.h b/src/back/backsessionclasses.h new file mode 100644 index 0000000..56e4cfc --- /dev/null +++ b/src/back/backsessionclasses.h @@ -0,0 +1,26 @@ +#pragma once +#include "msinclude.h" + +#include "global.h" +#include "contclasses.h" + +class Endpoint; + +class Session { + + public: + Session(Endpoint* ep, IAudioSessionControl2* sessionControl, size_t idx); + void setVolume(NGuid guid, int channel, float volume); + float getVolume(int channel); + void setMute(NGuid guid, bool muted); + bool getMute(); + std::wstring getName(); + //uint32_t getChannelCount(); + + private: + std::wstring sessionName; + Endpoint* ep; + IAudioSessionControl2* sessionControl = nullptr; + ISimpleAudioVolume* sessionVolume = nullptr; + size_t idx; +}; diff --git a/src/back/msinclude.h b/src/back/msinclude.h new file mode 100644 index 0000000..6709400 --- /dev/null +++ b/src/back/msinclude.h @@ -0,0 +1,25 @@ +#pragma once + +#define _WIN32_WINNT 0x0A00 +#include + +//done by qt by def #define UNICODE + +#include +#include +#include +#include +#include +#include +#include +//#include + +#include +#include +#include +//#include +//#include +#include +#include +#include "ipolicyconfig.h" +#include diff --git a/src/cont/contclasses.cpp b/src/cont/contclasses.cpp index ef2cbfb..653517b 100644 --- a/src/cont/contclasses.cpp +++ b/src/cont/contclasses.cpp @@ -14,6 +14,14 @@ EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) { //epName = ep->getName(); this->setBackEndpointVolumeCallbackInfoContent(this->getState()); osh->pushBackEndpointHandler(this, flow); + + + if (this->flow == Flows::FLOW_PLAYBACK && this->getState() == EndpointState::ENDPOINT_ACTIVE) { + for (int i = 0; i < this->getSessionCount(); i++) { + SessionHandler* sessionHandler = new SessionHandler(this, this->getSessions().at(i),i); + sessionHandlers.push_back(sessionHandler); + } + } } void OverseerHandler::pushBackEndpointHandler(EndpointHandler* eph, Flows flow) { @@ -141,6 +149,19 @@ void EndpointHandler::removeRoles(Roles newRole){ ep->removeRoles(newRole); } +/* sessions */ +size_t EndpointHandler::getSessionCount() { + return ep->getSessionCount(); +} + +std::vector EndpointHandler::getSessions(){ + return ep->getSessions(); +} + +std::vector EndpointHandler::getSessionHandlers(){ + return this->sessionHandlers; +} + EndpointHandler::~EndpointHandler() { ep->removeVolumeCallback(epc); epc->Release(); diff --git a/src/cont/contclasses.h b/src/cont/contclasses.h index 85ecff9..a89a42a 100644 --- a/src/cont/contclasses.h +++ b/src/cont/contclasses.h @@ -1,4 +1,7 @@ #pragma once + +#include "global.h" +#include "contsessionclasses.h" //#define invoke_mem_fn(object,ptrToMember) ((object).*(ptrToMember)) //#define pinvoke_mem_fn(object,ptrToMember) ((object)->*(ptrToMember)) @@ -6,50 +9,7 @@ class EndpointWidget; class Endpoint; class EndpointVolumeCallback; class Overseer; - -enum AudioChannel { - CHANNEL_LEFT = (1 << 0), - CHANNEL_RIGHT = (1 << 1), - CHANNEL_MAIN = ~0, -}; - -enum EndpointState { - ENDPOINT_ACTIVE = (1 << 0), - ENDPOINT_DISABLED = (1 << 1), - ENDPOINT_NOTPRESENT = (1 << 2), - ENDPOINT_UNPLUGGED = (1 << 3), - ENDPOINT_ALL = 0x0F -}; - -enum Flows { - FLOW_PLAYBACK = (1 << 0), - FLOW_CAPTURE = (1 << 1), - FLOW_BOTH = (1 << 2), -}; - -enum Roles { - ROLE_CONSOLE = (1 << 0), - ROLE_MULTIMEDIA = (1 << 1), - ROLE_COMMUNICATIONS = (1 << 2), - ROLE_ALL = 0x07, -}; - -struct NGuid { - //todo: still leaking? - uint32_t data1; - uint16_t data2; - uint16_t data3; - unsigned char data4[8]; - - - /* void freeData4(){ */ - /* int i = 0; */ - /* do{ */ - /* if(this->data4 + i != nullptr) free(data4 + i); */ - /* i++; */ - /* }while (i < 8); */ - /* } */ -}; +class SessionHandler; struct BackEndpointVolumeCallbackInfo { NGuid caller; @@ -98,8 +58,14 @@ public: void setState(uint8_t state); void setState(uint8_t state, uint64_t idx); + /* sessions */ + size_t getSessionCount(); + std::vector getSessionHandlers(); + ~EndpointHandler(); private: + std::vector getSessions(); + uint64_t idx; Endpoint *ep = nullptr; EndpointVolumeCallback *epc = nullptr; @@ -110,6 +76,7 @@ private: uint64_t frontIdx = INT_MAX; }; EndpointHandlerFrontVisibility ephfv; + std::vector sessionHandlers; //QSlider *slidy; }; diff --git a/src/cont/contsessionclasses.cpp b/src/cont/contsessionclasses.cpp new file mode 100644 index 0000000..92d6d6a --- /dev/null +++ b/src/cont/contsessionclasses.cpp @@ -0,0 +1,30 @@ +#include "contsessionclasses.h" +#include "backsessionclasses.h" + +SessionHandler::SessionHandler(EndpointHandler* eph, Session* session, size_t idx) { + this->eph = eph; + this->idx = idx; + this->session = session; +} + +void SessionHandler::setVolume(NGuid guid, int channel, int value){ + if (channel == AudioChannel::CHANNEL_MAIN) + session->setVolume(guid, channel, (float)value / 100); + else session->setVolume(guid, channel, (float)value / 100); +} + +float SessionHandler::getVolume(int channel){ + return session->getVolume(channel); +} + +void SessionHandler::setMute(NGuid guid, bool muted){ + session->setMute(guid, muted); +} + +std::wstring SessionHandler::getName(){ + return session->getName(); +} + +bool SessionHandler::getMute(){ + return session->getMute(); +} diff --git a/src/cont/contsessionclasses.h b/src/cont/contsessionclasses.h new file mode 100644 index 0000000..aea425e --- /dev/null +++ b/src/cont/contsessionclasses.h @@ -0,0 +1,23 @@ +#pragma once + +#include "global.h" +//#include "contclasses.h" + +class EndpointHandler; +class Session; + +class SessionHandler { + public: + SessionHandler(EndpointHandler* eph, Session* session, size_t idx); + void setVolume(NGuid guid, int channel, int value); + float getVolume(int channel); + void setMute(NGuid guid, bool muted); + bool getMute(); + std::wstring getName(); + + private: + EndpointHandler* eph; + Session* session; + size_t idx; + +}; diff --git a/src/global.h b/src/global.h index 0d7de5e..008fbc5 100644 --- a/src/global.h +++ b/src/global.h @@ -18,8 +18,56 @@ #define STRING_ROLE_MULTIMEDIA "Multimedia" #define STRING_ROLE_COMMUNICATIONS "Communications" #define STRING_ROLE_ALL "All" + +#define STRING_SYSTEM_SOUNDS "System Sounds" +#define LSTRING_SYSTEM_SOUNDS L"System Sounds" //INIT BACK +enum AudioChannel { + CHANNEL_LEFT = (1 << 0), + CHANNEL_RIGHT = (1 << 1), + CHANNEL_MAIN = ~0, +}; + +enum EndpointState { + ENDPOINT_ACTIVE = (1 << 0), + ENDPOINT_DISABLED = (1 << 1), + ENDPOINT_NOTPRESENT = (1 << 2), + ENDPOINT_UNPLUGGED = (1 << 3), + ENDPOINT_ALL = 0x0F +}; + +enum Flows { + FLOW_PLAYBACK = (1 << 0), + FLOW_CAPTURE = (1 << 1), + FLOW_BOTH = (1 << 2), +}; + +enum Roles { + ROLE_CONSOLE = (1 << 0), + ROLE_MULTIMEDIA = (1 << 1), + ROLE_COMMUNICATIONS = (1 << 2), + ROLE_ALL = 0x07, +}; + +struct NGuid { + //todo: still leaking? + uint32_t data1; + uint16_t data2; + uint16_t data3; + unsigned char data4[8]; + + + /* void freeData4(){ */ + /* int i = 0; */ + /* do{ */ + /* if(this->data4 + i != nullptr) free(data4 + i); */ + /* i++; */ + /* }while (i < 8); */ + /* } */ +}; + + class OverseerHandler; extern OverseerHandler *osh; diff --git a/src/qt/qtclasses.cpp b/src/qt/qtclasses.cpp index d47bd72..d2fdf3b 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -25,8 +25,56 @@ void ExtendedCheckBox::customEvent(QEvent* ev) { QCheckBox::customEvent(ev); } +SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent) : QWidget(parent){ + //todo: based on qgridlayout, name+mute should be its own widget, same with channels + this->idx = idx; + this->sh = sh; + + layout = new QGridLayout(this); + //this->setLayout( + + muteButton = new QCheckBox(this); + mainLabel = new QLabel(QString::fromStdWString(sh->getName()), this); + mainSlider = new QSlider(Qt::Horizontal, this); + + mainSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + mainSlider->setFocusPolicy(Qt::StrongFocus); + mainSlider->setTickPosition(QSlider::TicksBothSides); + mainSlider->setTickInterval(5); + mainSlider->setSingleStep(1); + mainSlider->setRange(0,100); + + muteButton->setCheckState((sh->getMute() == false ? Qt::Unchecked : Qt::Checked)); + muteButton->setText(sh->getMute() ? STRING_UNMUTE : STRING_MUTE); + float volume = sh->getVolume(AudioChannel::CHANNEL_MAIN) * 100; + mainSlider->setValue((int)volume); + log_debugcpp("SESSION SET WITH VOLUME " + std::to_string(volume)); + + //tip: would need to be new widget with layout in it + //mainMuteLayout = new QGridLayout(); + layout->addWidget(mainLabel, 0, 0, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(muteButton, 0, 1, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(mainSlider, 0, 2, 1, 2); + + //TODO:0 = mute and muted, change volume = unmuted are client side tricks = 2 callbacks, one for volume, one for mute state. Implement as an user selectable option? + connect(mainSlider, &QSlider::valueChanged, this,&SessionWidget::updateMainVolume); + connect(muteButton, &QCheckBox::stateChanged, this, (&SessionWidget::updateMute)); + +} + +void SessionWidget::updateMute(int checked){ + bool muted = (checked == 2 ? true : false); + this->sh->setMute(osh->getGuid(), muted); + this->muteButton->setText(this->sh->getMute() ? STRING_UNMUTE : STRING_MUTE); +} + +void SessionWidget::updateMainVolume(int newValue){ + this->sh->setVolume(osh->getGuid(), AudioChannel::CHANNEL_MAIN, newValue); +} + 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 + int row = 0; this->idx = idx; this->eph = eph; //todo: sussy @@ -52,7 +100,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare mainSlider = new QSlider(Qt::Horizontal, this); if (this->eph->getState() != EndpointState::ENDPOINT_ACTIVE) { - layout->addWidget(mainLabel, 0, 0); + layout->addWidget(mainLabel, row, 0); layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 1, 0); return; } @@ -73,9 +121,10 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare //tip: would need to be new widget with layout in it //mainMuteLayout = new QGridLayout(); - layout->addWidget(mainLabel, 0, 0, Qt::AlignLeft | Qt::AlignBottom); - layout->addWidget(muteButton, 0, 1, Qt::AlignLeft | Qt::AlignBottom); - layout->addWidget(mainSlider, 0, 2, 1, 2); + layout->addWidget(mainLabel, row, 0, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(muteButton, row, 1, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(mainSlider, row, 2, 1, 2); + row++; //TODO:0 = mute and muted, change volume = unmuted are client side tricks = 2 callbacks, one for volume, one for mute state. Implement as an user selectable option? connect(mainSlider, &QSlider::valueChanged, this,&EndpointWidget::updateMainVolume); @@ -99,8 +148,9 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare tmpLb->setText(QString::number(volume)); this->channelSliders.push_back(tmp); this->channelLabels.push_back(tmpLb); - layout->addWidget(tmp, 2, i); - layout->addWidget(tmpLb, 3, i); + layout->addWidget(tmp, row + 1, i); + layout->addWidget(tmpLb, row + 2, i); + //TODO: check if there's a need to prevent deadlocks; probably this will eventually turn into its own func //this causes channel bar desync when back -> front. blocksignals below fix it. huh. connect(tmp, &QSlider::valueChanged, [this, i](int newValue){ @@ -108,6 +158,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare this->channelLabels.at(i)->setText(QString::number(newValue)); }); } + row += 3; /* * Role ExtendedCheckBoxes setup @@ -145,11 +196,11 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare this->eph->setRoles(Roles::ROLE_COMMUNICATIONS); }); - 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); - + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_ALL), row, 0); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE), row, 1); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA), row, 2); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS), row, 3); + row++; /* ----------------------------------------------------------- */ /* @@ -158,6 +209,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare 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. + //todo: global + constexpr + ratio const float roundingFactor = 0.005; mainSlider->blockSignals(true); muteButton->blockSignals(true); @@ -179,6 +231,14 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare muteButton->blockSignals(false); }); timer->start(10); + + /* sessions */ + for (size_t i = 0; i < eph->getSessionCount(); i++) { + SessionWidget* sessionWidget = new SessionWidget(i, eph->getSessionHandlers().at(i), this); + layout->addWidget(sessionWidget, row, 4); + row++; + sessionWidgets.push_back(sessionWidget); + } //todo parent? layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 1, 0); diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index 6f1a51e..3afb63f 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -85,6 +85,25 @@ public: }; +class SessionWidget : public QWidget { +Q_OBJECT + +public: + SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent /* = nullptr */); + +public slots: + void updateMainVolume(int newValue); + void updateMute(int checked); + +private: + QLabel *mainLabel = nullptr; + QSlider *mainSlider = nullptr; + uint64_t idx; + QGridLayout *layout = nullptr; + QCheckBox *muteButton = nullptr; + SessionHandler* sh; +}; + class EndpointWidget : public QWidget { Q_OBJECT @@ -120,12 +139,13 @@ private: QGridLayout *layout = nullptr; QGridLayout *mainMuteLayout = nullptr; std::map defaultRolesCheckBoxes; - + EndpointHandler* eph; size_t defaultRolesVectorSize = 4; QTimer* timer = nullptr; uint64_t idx; + std::vector sessionWidgets; //std::vector *ephs; //std::vector *sliders;