Compare commits

...
Sign in to create a new pull request.

22 commits

Author SHA1 Message Date
03e726f3e6 more code cleanup; changed define for channel enum 2023-08-15 18:06:55 +02:00
831dceb89a code cleanup; channels callback coalesced again 2023-08-15 17:03:23 +02:00
c4b1c4b796 Correctly update channel sliders 2023-08-14 22:32:00 +02:00
c435fcfa07 Remove frontend header from contclasses 2023-08-14 20:27:19 +02:00
e5eb0878a6 changed invoke instances with call-to-mem-fun macro 2023-08-14 18:23:49 +02:00
01d2611d65 added pdb generation, fixed unintended back call 2023-08-14 18:00:59 +02:00
4f900ad425 broken: fixed event toggling order 2023-08-14 16:24:07 +02:00
bea0a2af94 broken: play dj outside, get it stuck 2023-08-14 16:10:35 +02:00
67626a34e4 forgot todo 2023-08-13 18:31:34 +02:00
b4401dd984 wip channel callback 2023-08-13 18:29:24 +02:00
312de5ce2c channels added to front programmatically 2023-08-13 17:43:09 +02:00
833b417441 main slider cbk, detected minor l_dcpp bug 2023-08-13 15:25:34 +02:00
c5eed2774d fixed overload funcs and connect() 2023-08-12 19:48:22 +02:00
ad53af655b first callback implemented; overload not working 2023-08-12 19:26:50 +02:00
f21619aa1f reverted failed attempt, fixed callback release 2023-08-12 17:29:01 +02:00
a24bba35be guid sent and validated for mute 2023-08-12 12:29:01 +02:00
7e741f3bca template and fixed guid obtaining 2023-08-11 21:35:48 +02:00
80685f1a21 Refactored program structure 2023-08-11 16:39:10 +02:00
e43e4c0569 wip partial refactor 2023-08-10 21:34:09 +02:00
507dc37ad6 updated build files 2023-08-09 20:31:47 +02:00
2f728e41ea Declare EndpointWidget before using it 2023-08-09 20:16:43 +02:00
c28ec1f11d failed attempt at redrawing 2023-08-09 15:55:25 +02:00
12 changed files with 613 additions and 152 deletions

View file

@ -1,2 +1,2 @@
qmake -o build\Makefile .\qtest.pro qmake -o build\Makefile .\qtest.pro
mingw32-make.exe -C .\build -f Makefile.Release mingw32-make.exe -C .\build -f Makefile

View file

@ -1,8 +1,12 @@
QMAKE_CXXFLAGS += --target=x86_64-w64-mingw32 -g -gcodeview
#QMAKE_LINK += clang++
QMAKE_LFLAGS += --target=x86_64-w64-mingw32 -g -gcodeview -Wl,-pdb= -v
DEFINES += DEBUG
CONFIG += debug console CONFIG += debug console
QT += widgets QT += widgets
INCLUDEPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont" INCLUDEPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont"
DESTPATH += "$$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" VPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont"
SOURCES += qtestmain.cpp qtclasses.cpp backlasses.cpp contclasses.cpp SOURCES += qtestmain.cpp qtclasses.cpp backlasses.cpp contclasses.cpp
HEADERS += qtclasses.h backlasses.h contclasses.h global.h debug.h HEADERS += qtclasses.h backlasses.h contclasses.h global.h debug.h backfuncs.h
#DESTDIR += "build" #DESTDIR += "build"

33
src/back/backfuncs.h Normal file
View file

@ -0,0 +1,33 @@
GUID NGuidToGUID(NGuid* guid) {
GUID msGuid = GUID();
msGuid.Data1 = guid->data1;
msGuid.Data2 = guid->data2;
msGuid.Data3 = guid->data3;
msGuid.Data1 = guid->data1;
for (int i = 0; i < 8; i++){
msGuid.Data4[i] = guid->data4[i];
//log_debugcpp("MSGUID DATA4 BYTE " << i << ": ");
//log_debugcpp(print_as_binary(8, uint32_t, msGuid.Data4[i]));
}
//log_debugcpp("MSGUID DATA1: " << msGuid.Data1);
//log_debugcpp("MSGUID DATA2: " << msGuid.Data2);
//log_debugcpp("MSGUID DATA3: " << msGuid.Data3);
return msGuid;
}
NGuid GUIDToNGuid(LPGUID msGuid){
NGuid guid = NGuid();
guid.data1 = msGuid->Data1;
guid.data2 = msGuid->Data2;
guid.data3 = msGuid->Data3;
for (int i = 0; i < 8; i++){
guid.data4[i] = msGuid->Data4[i];
//log_debugcpp("GUID DATA4 BYTE " << i << ": ");
//log_debugcpp(print_as_binary(8, uint32_t, guid.data4[i]));
}
//log_debugcpp("GUID DATA1: " << guid.data1);
//log_debugcpp("GUID DATA2: " << guid.data2);
//log_debugcpp("GUID DATA3: " << guid.data3);
return guid;
}

View file

@ -1,17 +1,102 @@
#include <backlasses.h> #include <backlasses.h>
#include <backfuncs.h>
Endpoint::Endpoint(IMMDevice* ep){ EndpointCallback::EndpointCallback(Endpoint* ep){
this->ep = ep;
}
ULONG EndpointCallback::AddRef(){
return InterlockedIncrement(&ref);
}
ULONG EndpointCallback::Release(){
ULONG tempRef = InterlockedDecrement(&ref);
if (tempRef == 0) {
delete this;
}
return tempRef;
}
HRESULT EndpointCallback::QueryInterface(REFIID riid, VOID **ppvInterface) {
if (IID_IUnknown == riid)
{
AddRef();
*ppvInterface = (IUnknown*)this;
}
else if (__uuidof(IAudioEndpointVolumeCallback) == riid)
{
AddRef();
*ppvInterface = (IAudioEndpointVolumeCallback*)this;
}
else
{
*ppvInterface = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
HRESULT EndpointCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) {
if (pNotify == NULL) return E_INVALIDARG;
float extraChannelVol[pNotify->nChannels];
bool multiChannel = false;
AUDIO_VOLUME_NOTIFICATION_DATA eventData = *pNotify;
if(pNotify->nChannels > 1) {
multiChannel = true;
for (UINT i = 0; i < pNotify->nChannels; i++){
extraChannelVol[i] = pNotify->afChannelVolumes[i];
}
}
NGuid* guid = osh->getGuid();
if (memcmp(guid, &eventData, sizeof(*guid)) == 0) {
log_debugcpp("Onnanokotify says You Shall Not Update Thy Interface.");
} else {
log_debugcpp("Onnanokotify says Stored: " << guid->data1);
log_debugcpp("Onnanokotify says Grace of God: " << eventData.guidEventContext.Data1);
osh->updateMuteCallback(this->ep->getIndex(), eventData.bMuted);
osh->updateVolumeCallback(this->ep->getIndex(), AudioChannel::CHANNEL_MAIN ,eventData.fMasterVolume);
log_debugcpp("Onnanokotify says Reported Channel Qty: " << eventData.nChannels);
if(multiChannel)
for(UINT i = 0; i < eventData.nChannels; i++) {
osh->updateVolumeCallback(this->ep->getIndex(), (uint32_t)i, extraChannelVol[i]);
}
else
osh->updateVolumeCallback(this->ep->getIndex(), (uint32_t)0, pNotify->afChannelVolumes[0]);
}
return S_OK;
}
/* EndpointCallback::~EndpointCallback(){
* PAUDIO_VOLUME_NOTIFICATION_DATA->Release();
* } */
Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){
this->endpoint = ep; this->endpoint = ep;
this->idx = idx;
if(FAILED(endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&endpointVolume))) { log_debugcpp("si"); }; if(FAILED(endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&endpointVolume))) { log_debugcpp("si"); };
if (FAILED(endpointVolume->GetChannelCount(&channelCount))) log_debugcpp("get channel count fail");
//Obtaining friendly name: IPropertyStore creates PROPVARIANT per field //Obtaining friendly name: IPropertyStore creates PROPVARIANT per field
// hr = endpointPtr->GetId(&endpointID); // hr = endpointPtr->GetId(&endpointID);
endpoint->OpenPropertyStore(STGM_READ, &properties); endpoint->OpenPropertyStore(STGM_READ, &properties);
PROPVARIANT pv; PROPVARIANT pv;
properties->GetValue(PKEY_Device_FriendlyName , &pv); properties->GetValue(PKEY_Device_FriendlyName , &pv);
friendlyName = pv.pwszVal; friendlyName = std::wstring(pv.pwszVal);
} }
LPWSTR Endpoint::getName(){ void Endpoint::setIndex(uint64_t idx){
this->idx = idx;
}
uint64_t Endpoint::getIndex(){
return idx;
}
std::wstring Endpoint::getName(){
return friendlyName; return friendlyName;
} }
@ -25,6 +110,10 @@ float Endpoint::getVolume(int channel){
return volume; return volume;
} }
uint32_t Endpoint::getChannelCount(){
return (uint32_t)channelCount;
}
bool Endpoint::getMute(){ bool Endpoint::getMute(){
BOOL mut; BOOL mut;
@ -50,34 +139,44 @@ bool Endpoint::getMute(){
*/ */
void Endpoint::setVolume(int channel, float volume) { void Endpoint::setVolume(NGuid* guid, int channel, float volume) {
if (channel == ENDPOINT_MASTER_VOLUME) { GUID tempMsGuid = NGuidToGUID(guid);
if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, NULL))) { log_debugcpp("si"); }; if (channel == AudioChannel::CHANNEL_MAIN) {
if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) { log_debugcpp("MASTER VOLUME FAILED"); };
} else { } else {
if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, NULL))) { log_debugcpp("si"); }; log_debugcpp("Windows: Channel being updated: " << channel);
if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) { log_debugcpp("CHANNEL "<< channel <<" VOLUME FAILED"); };
} }
} }
void Endpoint::setMute() { void Endpoint::setMute(NGuid* guid, bool muted) {
log_debugcpp("bool mute arrives as " << mut); //BOOL mut;
BOOL mut; //log_debugcpp("bool mute arrives as " << mut);
if(FAILED(endpointVolume->GetMute(&mut))) { log_debugcpp("si"); } //if(FAILED(endpointVolume->GetMute(&mut))) { log_debugcpp("si"); }
log_debugcpp("translate to BOOL as " << mute); //log_debugcpp("translate to BOOL as " << mut);
if(FAILED(endpointVolume->SetMute((mut == false ? 1 : 0), NULL))) { log_debugcpp("si"); }; //TODO: use new funcs
GUID tempMsGuid = NGuidToGUID(guid);
if(FAILED(endpointVolume->SetMute(muted, &tempMsGuid))) { log_debugcpp("MUTE FAILED"); };
} }
void Endpoint::setCallback(EndpointCallback *epc){
endpointVolume->RegisterControlChangeNotify((IAudioEndpointVolumeCallback*)epc);
}
void Endpoint::removeCallback(EndpointCallback *epc){
endpointVolume->UnregisterControlChangeNotify((IAudioEndpointVolumeCallback*)epc);
}
Endpoint::~Endpoint(){ Endpoint::~Endpoint(){
log_debugcpp("cum"); log_debugcpp("cum");
free(friendlyName);
properties->Release(); properties->Release();
endpointVolume->Release(); endpointVolume->Release();
endpoint->Release(); endpoint->Release();
} }
void Overseer::initCOMLibrary() {
void Overseer::initCOMLibrary(){ if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) {
if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { log_debugcpp("si"); }; log_debugcpp("si"); };
//Retrieving endpoint enumerator //Retrieving endpoint enumerator
@ -87,6 +186,11 @@ void Overseer::initCOMLibrary(){
(void**)&deviceEnumerator)) ) (void**)&deviceEnumerator)) )
{ log_debugcpp("si"); }; { log_debugcpp("si"); };
GUID tempGuid;
if(FAILED(CoCreateGuid(&tempGuid))) { log_debugcpp("Failed to obtain GUID: " ); };
this->guid = GUIDToNGuid(&tempGuid);
//TODO: Release lpguid?
//TODO: Uninitialize COM
} }
void Overseer::reloadEndpoints() { void Overseer::reloadEndpoints() {
@ -105,7 +209,8 @@ void Overseer::reloadEndpoints() {
for (unsigned int i = 0; i < numPlaybackEndpoints; i++){ for (unsigned int i = 0; i < numPlaybackEndpoints; i++){
IMMDevice *temp; IMMDevice *temp;
if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); }; if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); };
Endpoint *endpoint = new Endpoint(temp); Endpoint *endpoint = new Endpoint(temp, i);
//endpoint->setIndex(i);
this->playbackDevices.push_back(endpoint); this->playbackDevices.push_back(endpoint);
//TODO: le porblemx std::cout << "ola" << std::endl; //TODO: le porblemx std::cout << "ola" << std::endl;
} }
@ -115,6 +220,7 @@ void Overseer::reloadEndpoints() {
Overseer::Overseer(){ Overseer::Overseer(){
//Initializing COM library //Initializing COM library
log_debugcpp("Initializing Overseer");
initCOMLibrary(); initCOMLibrary();
//Obtaining playback endpoint collection on this point in time //Obtaining playback endpoint collection on this point in time
@ -129,6 +235,11 @@ Overseer::Overseer(){
//int Overseer::getDefaultCaptureEndpoint(Endpoint** defaultEndpoint); //int Overseer::getDefaultCaptureEndpoint(Endpoint** defaultEndpoint);
//TODO guid
NGuid* Overseer::getGuid() {
return &guid;
}
std::vector<Endpoint*> Overseer::getPlaybackEndpoints() { std::vector<Endpoint*> Overseer::getPlaybackEndpoints() {
return playbackDevices; return playbackDevices;
} }

View file

@ -1,10 +1,11 @@
#pragma once #pragma once
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
//done by qt by def #define UNICODE
#include "debug.h" //#include "debug.h"
#include "global.h" /* #include <vector> */
#include <vector> /* #include <iostream> */
#include <iostream> /* #include <wstring> */
#include <Windows.h> #include <Windows.h>
#include <mmdeviceapi.h> #include <mmdeviceapi.h>
@ -19,33 +20,60 @@
//#include <comip.h> //#include <comip.h>
#include <Winerror.h> #include <Winerror.h>
#include "global.h"
#include "contclasses.h"
class EndpointCallback;
class Endpoint { class Endpoint {
public: public:
Endpoint(IMMDevice* endpoint); Endpoint(IMMDevice* endpoint, uint64_t idx);
void setVolume(int channel, float volume); uint64_t getIndex();
/* float getLeftChannelVolume(); */ void setIndex(uint64_t idx);
/* float getRightChannelVolume(); */ void setVolume(NGuid* guid, int channel, float volume);
uint32_t getChannelCount();
float getVolume(int channel); float getVolume(int channel);
void setMute(); void setMute(NGuid* guid, bool muted);
bool getMute(); bool getMute();
LPWSTR getName(); std::wstring getName();
void setCallback(EndpointCallback *epc);
void removeCallback(EndpointCallback *epc);
~Endpoint(); ~Endpoint();
private: private:
uint32_t channelCount;
IMMDevice* endpoint; IMMDevice* endpoint;
IAudioEndpointVolume *endpointVolume ; IAudioEndpointVolume *endpointVolume ;
IPropertyStore *properties; IPropertyStore *properties;
LPWSTR friendlyName; std::wstring friendlyName;
uint64_t idx;
// LPWSTR endpointID = NULL; // LPWSTR endpointID = NULL;
}; };
class EndpointCallback : public IAudioEndpointVolumeCallback {
public:
EndpointCallback(Endpoint* ep);
ULONG AddRef();
ULONG Release();
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
HRESULT OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA update);
//~EndpointCallback();
private:
ULONG ref = 1;
Endpoint* ep;
};
class Overseer { class Overseer {
//TODO singleton? //TODO singleton?
public: public:
Overseer(); Overseer();
std::vector<Endpoint*> getPlaybackEndpoints(); std::vector<Endpoint*> getPlaybackEndpoints();
void reloadEndpoints(); void reloadEndpoints();
NGuid* getGuid();
//~Overseer(); //~Overseer();
//int getDefaultPlaybackEndpoint(Endpoint** defaultEndpoint); //int getDefaultPlaybackEndpoint(Endpoint** defaultEndpoint);
//int getDefaultCaptureEndpoint(Endpoint** defaultEndpoint); //int getDefaultCaptureEndpoint(Endpoint** defaultEndpoint);
@ -54,6 +82,7 @@ class Overseer {
~Overseer(); ~Overseer();
private: private:
NGuid guid;
unsigned int numPlaybackEndpoints; unsigned int numPlaybackEndpoints;
IMMDeviceEnumerator *deviceEnumerator; IMMDeviceEnumerator *deviceEnumerator;
std::vector<Endpoint*> playbackDevices; std::vector<Endpoint*> playbackDevices;

View file

@ -1,50 +1,138 @@
#include "backlasses.h"
#include "contclasses.h" #include "contclasses.h"
//TODO: pragma once
//TODO: ?????
Overseer OverseerHandler::os; Overseer OverseerHandler::os;
EndpointHandler::EndpointHandler(Endpoint *ept, QObject *parent) : QObject(parent) { EndpointHandler::EndpointHandler(uint64_t idx) {
this->ept = ept; //std::vector<Endpoint*> endpoints = osh->getPlaybackEndpoints().at(idx);
eptName = QString::fromStdWString(ept->getName()); this->ep = osh->getPlaybackEndpoints().at(idx);
epc = new EndpointCallback(ep);
//epName = ep->getName();
ep->setCallback(epc);
} }
uint32_t EndpointHandler::getChannelCount(){
return ep->getChannelCount();
}
void EndpointHandler::setIndex(uint64_t idx){
this->idx = idx;
}
uint64_t EndpointHandler::getIndex(){
return idx;
}
/* /*
* -1 for master volume * -1 for master volume
*/ */
void EndpointHandler::setValue(int channel, int value){ void EndpointHandler::setVolume(NGuid* guid, int channel, int value){
if (channel == ENDPOINT_MASTER_VOLUME) if (channel == ENDPOINT_MASTER_VOLUME)
ept->setVolume(channel, (float)value / 100); ep->setVolume(guid, channel, (float)value / 100);
else ept->setVolume(channel, (float)value / 100); else ep->setVolume(guid, channel, (float)value / 100);
} }
void EndpointHandler::setMute(){ void EndpointHandler::setMute(NGuid* guid, bool muted){
//Qt momento, de ahi el param? //Qt momento, de ahi el param?
log_debugcpp("kinda handling the muting tbh"); log_debugcpp("kinda handling the muting tbh");
ept->setMute(); ep->setMute(guid, muted);
} }
QString EndpointHandler::getName(){ std::wstring EndpointHandler::getName(){
return eptName; return ep->getName();
} }
float EndpointHandler::getVolume(int channel){ float EndpointHandler::getVolume(int channel){
return ept->getVolume(channel); return ep->getVolume(channel);
} }
bool EndpointHandler::getMute(){ bool EndpointHandler::getMute(){
return ept->getMute(); return ep->getMute();
} }
Overseer* OverseerHandler::getOverseer(){ EndpointHandler::~EndpointHandler() {
return &os; ep->removeCallback(epc);
epc->Release();
delete ep;
} }
OverseerHandler::OverseerHandler(QObject *parent) : QObject(parent) { std::vector<Endpoint*> OverseerHandler::getPlaybackEndpoints() {
return this->os.getPlaybackEndpoints();
} }
std::vector<EndpointHandler*>* OverseerHandler::getEndpointHandlers(){
std::vector<EndpointHandler*> OverseerHandler::getEndpointHandlers(){
return endpointHandlers; return endpointHandlers;
} }
void OverseerHandler::setEndpointHandlers(std::vector<EndpointHandler*> *ephs){ uint64_t OverseerHandler::getPlaybackEndpointsCount(){
return this->os.getPlaybackEndpoints().size();
}
void OverseerHandler::reloadEndpointHandlers(){
//std::vector<EndpointHandler*>* ephs = new std::vector<EndpointHandler*>;
log_debugcpp(" VSize: " << this->getPlaybackEndpointsCount());
for(uint64_t i = 0; i < this->getPlaybackEndpointsCount(); i++){
log_debugcpp("Creating handler " << i);
if(i < (this->endpointHandlers.size()) &&
this->endpointHandlers.at(i) != nullptr)
delete endpointHandlers.at(i);
EndpointHandler* eph = new EndpointHandler(i);
log_debugcpp("Created handler " << i << ", adding to vector. " << " VSize: " << this->getPlaybackEndpointsCount());
if (i >= this->endpointHandlers.size())
endpointHandlers.push_back(eph);
else endpointHandlers.at(i) = eph;
}
//setEndpointHandlers(ephs);
}
NGuid* OverseerHandler::getGuid() {
return this->os.getGuid();
}
void OverseerHandler::setEndpointHandlers(std::vector<EndpointHandler*> ephs){
this->endpointHandlers = ephs; this->endpointHandlers = ephs;
} }
void OverseerHandler::setFrontVolumeCallback(std::function<void(uint64_t, uint32_t, float)> f) {
this->updateFrontVolumeCallback = f;
}
void OverseerHandler::setFrontMuteCallback(std::function<void(uint64_t, bool)> f) {
this->updateFrontMuteCallback = f;
}
void OverseerHandler::updateMuteCallback(uint64_t idx, bool muted){
updateFrontMuteCallback(idx, muted);
}
/*
* void OverseerHandler::updateMainVolumeCallback(uint64_t idx, float newVal){
*
* }
*/
void OverseerHandler::updateVolumeCallback(uint64_t idx, uint32_t channel, float newVal){
if (channel == (uint32_t)AudioChannel::CHANNEL_MAIN) {
log_debugcpp("mainvolcallback float: " << newVal);
updateFrontVolumeCallback(idx, AudioChannel::CHANNEL_MAIN, newVal);
return;
}
// convert channel to bitmask
uint32_t i = 0;
while (i < channel)
i++;
uint32_t mask = (1 << i);
log_debugcpp("Back->Cont Channel: " << mask << " volcallback float: " << newVal);
updateFrontVolumeCallback(idx, mask, newVal);
}

View file

@ -1,48 +1,84 @@
#pragma once #pragma once
#include <QObject> #define invoke_mem_fn(object,ptrToMember) ((object).*(ptrToMember))
#include "backlasses.h" #define pinvoke_mem_fn(object,ptrToMember) ((object)->*(ptrToMember))
/* #ifndef QTBLESSED */
/* //#define Q_OBJECT */
/* class QWidget{}; */
/* class QMainWindow{}; */
/* #endif */
class EndpointHandler : public QObject { class EndpointWidget;
Q_OBJECT class Endpoint;
class EndpointCallback;
class Overseer;
enum AudioChannel {
CHANNEL_LEFT = (1 << 0),
CHANNEL_RIGHT = (1 << 1),
CHANNEL_MAIN = ~0,
};
struct NGuid {
uint32_t data1;
uint16_t data2;
uint16_t data3;
unsigned char data4[8];
};
class EndpointHandler {
public: public:
EndpointHandler(Endpoint *ept, QObject *parent = nullptr); EndpointHandler(uint64_t idx);
QString getName(); //TODO: get();
Endpoint *ep = nullptr;
EndpointCallback *epc = nullptr;
//std::wstring epName;
uint32_t getChannelCount();
void setIndex(uint64_t idx);
uint64_t getIndex();
void setVolume(int channel, float volume);
std::wstring getName();
float getVolume(int channel); float getVolume(int channel);
bool getMute(); bool getMute();
void setVolume(NGuid* guid, int channel, int value);
void setMute(NGuid* guid, bool muted);
~EndpointHandler();
private: private:
Endpoint *ept; uint64_t idx;
QString eptName;
//QSlider *slidy; //QSlider *slidy;
public slots:
void setValue(int channel, int value);
void setMute();
//signals: //signals:
}; };
class OverseerHandler : public QObject { class OverseerHandler {
Q_OBJECT
public: public:
OverseerHandler(QObject *parent = nullptr); //OverseerHandler();
void setEndpointHandlers(std::vector<EndpointHandler*> *ephs); void setEndpointHandlers(std::vector<EndpointHandler*> ephs);
std::vector<EndpointHandler*>* getEndpointHandlers(); std::vector<EndpointHandler*> getEndpointHandlers();
static Overseer* getOverseer(); std::vector<Endpoint*> getPlaybackEndpoints();
uint64_t getPlaybackEndpointsCount();
void reloadEndpointHandlers();
NGuid* getGuid();
void updateMuteCallback(uint64_t idx, bool muted);
void setFrontMuteCallback(std::function<void(uint64_t, bool)> f);
void setFrontVolumeCallback(std::function<void(uint64_t, uint32_t, float)> f);
//void updateMainVolumeCallback(uint64_t idx, float newVal);
void updateVolumeCallback(uint64_t idx, uint32_t channel, float newVal);
private: private:
static Overseer os; static Overseer os;
std::vector<EndpointHandler*> *endpointHandlers; std::vector<EndpointHandler*> endpointHandlers;
//QSlider *slidy; std::function<void(uint64_t /* device */, uint32_t /* channel */, float /* value */)> updateFrontVolumeCallback;
std::function<void(uint64_t /* device */, bool /* mute */)> updateFrontMuteCallback;
//public slots:
//void setValue(int value);
}; };

View file

@ -2,9 +2,28 @@
#if defined (QT_DEBUG) || defined (DEBUG) || defined (_DEBUG) #if defined (QT_DEBUG) || defined (DEBUG) || defined (_DEBUG)
template<size_t Y, typename T>
std::bitset<Y> varToBitset(T info) {
std::bitset<Y> content(info);
return content;
}
#define log_debugcpp(str) do { \ #define log_debugcpp(str) do { \
std::cout << "[DEBUG]" << "(" << __FILE__ << ":" << __LINE__ << "): " << str << std::endl; \ std::cout << "[DEBUG]" << "(" << __FILE__ << ":" << __LINE__ << "): " << str << std::endl; \
} while (0) } while (0)
#define print_as_binary(len, type, info) varToBitset<len, type>(info)
#else #else
#define log_debugcpp(str) #define log_debugcpp(str)
#define print_as_binary(len, type, info)
#endif #endif
/* Here as a quick reference, in case smthn similar is needed again */
/* typedef void (EndpointWidget::*epwMuteFunc)(bool muted); */
/* typedef void (EndpointWidget::*epwMainVolumeFunc)(float newValue); */
/* typedef void (EndpointWidget::*epwChannelVolumeFunc)(uint32_t channel, float newValue); */
/* typedef void (EndpointWidget::*epwToggleFrontFunc)(bool active); */

View file

@ -1,15 +1,20 @@
#pragma once #pragma once
//TODO enum capullo #include <vector>
#include <iostream>
#include <string>
#include <bitset>
#include "debug.h"
#define ENDPOINT_MASTER_VOLUME -1 #define ENDPOINT_MASTER_VOLUME -1
#define ENDPOINT_LEFT_CHANNEL_VOLUME 0 /* #define ENDPOINT_LEFT_CHANNEL_VOLUME 0 */
#define ENDPOINT_RIGHT_CHANNEL_VOLUME 1 /* #define ENDPOINT_RIGHT_CHANNEL_VOLUME 1 */
#define STRING_MUTE "Mute" #define STRING_MUTE "Mute"
#define STRING_UNMUTE "Unmute" #define STRING_UNMUTE "Unmute"
//INIT BACK //INIT BACK
class OverseerHandler; class OverseerHandler;
extern OverseerHandler *osh; extern OverseerHandler *osh;

View file

@ -1,5 +1,20 @@
#include "qtclasses.h" #include "qtclasses.h"
/*
* ToggleButton::ToggleButton(QWidget *parent) : QAbstractButton(parent) {
* this->setCheckable(true);
* }
*
* ToggleButton::~ToggleButton(){
*
* }
*
* void ToggleButton::checkStateSet(){ }
*
* bool hitButton(const QPoint &pos) {
*
* }
*/
EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent) : QWidget(parent){ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent) : QWidget(parent){
this->eph = eph; this->eph = eph;
@ -8,36 +23,21 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent) : QWidget(
log_debugcpp("olaW"); log_debugcpp("olaW");
if (parent == nullptr) { log_debugcpp("owo?"); } if (parent == nullptr) { log_debugcpp("owo?"); }
muteButton = new QPushButton(); muteButton = new QCheckBox();
mainLabel = new QLabel(eph->getName()); mainLabel = new QLabel(QString::fromStdWString(eph->getName()));
leftChannelLabel = new QLabel("88");
rightChannelLabel = new QLabel("77");
mainSlider = new QSlider(Qt::Horizontal); mainSlider = new QSlider(Qt::Horizontal);
leftChannelSlider = new QSlider(Qt::Horizontal);
rightChannelSlider = new QSlider(Qt::Horizontal);
muteButton->setStyleSheet("background-color: #A3C1DA; color: red"); //muteButton->setStyleSheet("background-color: #A3C1DA; color: red");
mainSlider->setFocusPolicy(Qt::StrongFocus); mainSlider->setFocusPolicy(Qt::StrongFocus);
mainSlider->setTickPosition(QSlider::TicksBothSides); mainSlider->setTickPosition(QSlider::TicksBothSides);
mainSlider->setTickInterval(5); mainSlider->setTickInterval(5);
mainSlider->setSingleStep(1); mainSlider->setSingleStep(1);
mainSlider->setRange(0,100); mainSlider->setRange(0,100);
leftChannelSlider->setTickInterval(5);
leftChannelSlider->setSingleStep(1);
leftChannelSlider->setRange(0,100);
rightChannelSlider->setTickInterval(5);
rightChannelSlider->setSingleStep(1);
rightChannelSlider->setRange(0,100);
muteButton->setCheckState((eph->getMute() == false ? Qt::Unchecked : Qt::Checked));
muteButton->setText(eph->getMute() ? STRING_UNMUTE : STRING_MUTE); muteButton->setText(eph->getMute() ? STRING_UNMUTE : STRING_MUTE);
float volume = eph->getVolume(ENDPOINT_MASTER_VOLUME) * 100; float volume = eph->getVolume(ENDPOINT_MASTER_VOLUME) * 100;
mainSlider->setValue((int)volume); mainSlider->setValue((int)volume);
volume = eph->getVolume(ENDPOINT_LEFT_CHANNEL_VOLUME) * 100;
leftChannelSlider->setValue((int)volume);
leftChannelLabel->setText(QString::number(volume));
volume = eph->getVolume(ENDPOINT_RIGHT_CHANNEL_VOLUME) * 100;
rightChannelSlider->setValue((int)volume);
rightChannelLabel->setText(QString::number(volume));
log_debugcpp("ENDPOINT SET WITH VOLUME " << volume); log_debugcpp("ENDPOINT SET WITH VOLUME " << volume);
mainMuteLayout = new QGridLayout(); mainMuteLayout = new QGridLayout();
@ -45,25 +45,108 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent) : QWidget(
mainMuteLayout->addWidget(mainLabel, 0, 0); mainMuteLayout->addWidget(mainLabel, 0, 0);
mainMuteLayout->addWidget(muteButton, 0, 1); mainMuteLayout->addWidget(muteButton, 0, 1);
layout->addWidget(mainSlider, 0, 1); layout->addWidget(mainSlider, 0, 1);
layout->addWidget(leftChannelSlider, 1, 0);
layout->addWidget(leftChannelLabel, 2, 0); connect<void(QSlider::*)(int), void(EndpointWidget::*)(int)>(mainSlider, &QSlider::valueChanged, this,&EndpointWidget::updateMainVolume);
layout->addWidget(rightChannelSlider, 1, 1); connect<void(QCheckBox::*)(int), void(EndpointWidget::*)(int)>(muteButton, &QCheckBox::stateChanged, this, (&EndpointWidget::updateMute));
layout->addWidget(rightChannelLabel, 2, 1);
for(uint32_t i = 0; i < eph->getChannelCount(); i++){
QSlider* tmp = new QSlider(Qt::Horizontal);
QLabel* tmpLb = new QLabel("");
tmp->setTickInterval(5);
tmp->setSingleStep(1);
tmp->setRange(0,100);
volume = eph->getVolume(i) * 100;
tmp->setValue((int) volume);
tmpLb->setText(QString::number(volume));
this->channelSliders.push_back(tmp);
this->channelLabels.push_back(tmpLb);
layout->addWidget(tmp, 1, i);
layout->addWidget(tmpLb, 2, i);
//TODO: check if there's a need to prevent deadlocks; probably this will eventually turn into its own func
connect(tmp, &QSlider::valueChanged, [this, i](int newValue){ this->eph->setVolume(osh->getGuid(), i, newValue); this->channelLabels.at(i)->setText(QString::number(newValue)); });
}
layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 3, 0); layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 3, 0);
layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 3, 1); layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 3, 1);
/*
* connect(mainSlider, &QSlider::valueChanged, eph, &EndpointHandler::setValue);
*/
connect(mainSlider, &QSlider::valueChanged, [this](int newValue){this->eph->setValue(ENDPOINT_MASTER_VOLUME, newValue); });
connect(leftChannelSlider, &QSlider::valueChanged, [this](int newValue){ this->eph->setValue(ENDPOINT_LEFT_CHANNEL_VOLUME, newValue); this->leftChannelLabel->setText(QString::number(newValue)); });
connect(rightChannelSlider, &QSlider::valueChanged, [this](int newValue){ this->eph->setValue(ENDPOINT_RIGHT_CHANNEL_VOLUME, newValue); this->rightChannelLabel->setText(QString::number(newValue)); });
connect(muteButton, &QPushButton::clicked, [this](bool clicked){ log_debugcpp("cliqui" << clicked << "cloqui"); this->eph->setMute(); this->muteButton->setText(this->eph->getMute() ? STRING_UNMUTE : STRING_MUTE); });
log_debugcpp("ENDPOINT_WIDGETED"); log_debugcpp("ENDPOINT_WIDGETED");
} }
void EndpointWidget::updateMute(bool muted){
log_debugcpp("cliqui callboqui cloqui");
//TIP: Blocksignals here to diagnose slider visuals locking when playing DJ with external volume bar. Functionality is restored when mute checkbox is clicked.
//this->blockSignals(true);
//this->muteButton->blockSignals(true);
MainWindow::MainWindow(std::vector<EndpointHandler*> *ephs, QWidget *parent) : QMainWindow(parent) { //this->eph->setMute(osh->getGuid(), muted);
this->muteButton->setChecked(muted);
this->muteButton->setText(this->eph->getMute() ? STRING_UNMUTE : STRING_MUTE);
//this->muteButton->blockSignals(false);
//this->blockSignals(false);
}
void EndpointWidget::updateMute(int checked){
log_debugcpp("cliqui slOtty cloqui");
bool muted = (checked == 2 ? true : false);
log_debugcpp("int: " << checked << " bool: " << muted);
this->eph->setMute(osh->getGuid(), muted);
//this->muteButton->setCheckState();
this->muteButton->setText(this->eph->getMute() ? STRING_UNMUTE : STRING_MUTE);
}
void EndpointWidget::updateMainVolume(int newValue){
log_debugcpp("updateMainVolume slot.");
this->eph->setVolume(osh->getGuid(), ENDPOINT_MASTER_VOLUME, newValue);
}
void EndpointWidget::updateVolume(uint32_t channel, float newValue){
//this->blockSignals(true);
int newVal = newValue * 100;
if (channel == (uint32_t)AudioChannel::CHANNEL_MAIN) {
log_debugcpp("mainvolcallback int: " << newVal);
//this->mainSlider->blockSignals(true);
if(this->mainSlider->value() != newVal) {
this->mainSlider->setValue(newVal);
}
return;
}
log_debugcpp("Cont->Front Channel:: " << channel << " volcallback int: " << newVal);
for (size_t i = 0; i < sizeof(uint32_t) * 8 && i < channelSliders.size(); ++i) {
if (((channel >> i) & 1) && this->channelSliders.at(i)->value() != newVal) {
//this->channelSliders.at(i)->blockSignals(true);
this->channelSliders.at(i)->setValue(newVal);
this->channelLabels.at(i)->setText(QString::number((int)(newValue * 100)));
//this->channelSliders.at(i)->blockSignals(false);
}
}
//this->blockSignals(false);
}
/*
* void EndpointWidget::toggleFrontEvents(bool active){
* this->muteButton->blockSignals(active);
* this->mainSlider->blockSignals(active);
* for(uint32_t i = 0; i < this->channelSliders.size(); i++){
* this->channelSliders.at(i)->blockSignals(active);
* }
* }
*/
void EndpointWidget::setIndex(uint64_t idx){
this->idx = idx;
}
uint64_t EndpointWidget::getIndex(){
return idx;
}
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
// setWindowState(Qt::WindowFullScreen); // setWindowState(Qt::WindowFullScreen);
// setCentralWidget(centralWidget); // setCentralWidget(centralWidget);
widget = new QWidget(); widget = new QWidget();
@ -75,26 +158,30 @@ MainWindow::MainWindow(std::vector<EndpointHandler*> *ephs, QWidget *parent) : Q
setWindowTitle("slidea resbala nu c"); setWindowTitle("slidea resbala nu c");
/*s reloadEndpointWidgets();
* setEndpointHandlers(ephs); }
*/
void MainWindow::reloadEndpointWidgets() {
unsigned int i = 0; unsigned int i = 0;
for (; i < ephs->size(); i++) { for (; i < (osh->getEndpointHandlers().size()); i++) {
log_debugcpp("EPWidget creation"); log_debugcpp("EPWidget creation");
EndpointWidget *epw = new EndpointWidget(ephs->at(i), widget); EndpointWidget *epw = new EndpointWidget(osh->getEndpointHandlers().at(i), widget);
ews.push_back(epw); ews.push_back(epw);
layout->addWidget(epw, i, 0); layout->addWidget(epw, i, 0);
} }
layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), i, 0); layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), i, 0);
osh->setFrontVolumeCallback([this](uint64_t device, uint32_t channel, float value) {
if (device < ews.size())
ews[device]->updateVolume(channel, value);
});
osh->setFrontMuteCallback([this](uint64_t device, bool muted) {
if (device < ews.size())
ews[device]->updateMute(muted);
});
} }
/*
* void MainWindow::setEndpointHandlers(std::vector<EndpointHandler*> *ephs){
* this->ephs = ephs;
*/
/* /*
* void MainWindow::setPlotButton() { * void MainWindow::setPlotButton() {
* button = new QPushButton("push"), * button = new QPushButton("push"),
@ -112,3 +199,4 @@ MainWindow::MainWindow(std::vector<EndpointHandler*> *ephs, QWidget *parent) : Q
* ... * ...
*/ */

View file

@ -1,54 +1,104 @@
#pragma once #pragma once
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include <vector>
#include <QMainWindow> #include <QMainWindow>
#include <QApplication> #include <QApplication>
#include <QLabel> #include <QLabel>
#include <QSlider> #include <QSlider>
#include <QGridLayout> #include <QGridLayout>
#include <QPushButton> #include <QPushButton>
#include "contclasses.h" #include <QCheckBox>
//#include <Q> /*
//#include <QWidgets> * #else
* class QSlider;
* class QLabel;
* class QGridLayout;
* class QPushButton;
* class QWidget;
* class QMainWindow;
* #endif
*/
#include "global.h"
#include "contclasses.h"
//class EndpointHandler;
/*
* class ToggleButton : public QAbstractButton {
* Q_OBJECT
*
* public:
* ToggleButton(QWidget *parent = nullptr);
* void checkStateSet();
* bool hitButton(const QPoint &pos) const;
* void nextCheckState();
* void changeEvent(QEvent *e) override;
* bool event(QEvent *e) override;
* void focusInEvent(QFocusEvent *e) override;
* void focusOutEvent(QFocusEvent *e) override;
* void keyPressEvent(QKeyEvent *e) override;
* void keyReleaseEvent(QKeyEvent *e) override;
* void mouseMoveEvent(QMouseEvent *e) override;
* void mousePressEvent(QMouseEvent *e) override;
* void mouseReleaseEvent(QMouseEvent *e) override;
* void paintEvent(QPaintEvent *e) override = 0;
* void timerEvent(QTimerEvent *e) override;
* ToggleButton(QWidget *parent = nullptr);
* };
*/
class EndpointWidget : public QWidget { class EndpointWidget : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
EndpointWidget(EndpointHandler* eph, QWidget *parent = nullptr); EndpointWidget(EndpointHandler* eph, QWidget *parent = nullptr);
//TODO: get();
EndpointHandler* eph;
void setIndex(uint64_t idx);
uint64_t getIndex();
void setVolume(int channel, float volume);
QCheckBox *muteButton = nullptr;
QLabel *mainLabel = nullptr, *leftChannelLabel = nullptr, *rightChannelLabel = nullptr;
QSlider *mainSlider = nullptr;
std::vector<QSlider*> channelSliders;
std::vector<QLabel*> channelLabels;
QGridLayout *layout = nullptr;
QGridLayout *mainMuteLayout = nullptr;
//void updateMainVolume(float newValue);
void updateVolume(uint32_t channel, float newValue);
void updateMute(bool muted);
//void toggleFrontEvents(bool active);
//void populateEndpointWidget(EndpointHandler *eph); //void populateEndpointWidget(EndpointHandler *eph);
//void setEndpointHandlers(std::vector<EndpointHandler*> *ephs); //void setEndpointHandlers(std::vector<EndpointHandler*> *ephs);
public slots:
void updateMainVolume(int newValue);
void updateMute(int checked);
private: private:
EndpointHandler* eph; uint64_t idx;
QPushButton *muteButton = nullptr;
QLabel *mainLabel = nullptr, *leftChannelLabel = nullptr, *rightChannelLabel = nullptr;
QSlider *mainSlider = nullptr;
QSlider *leftChannelSlider = nullptr;
QSlider *rightChannelSlider = nullptr;
QGridLayout *layout = nullptr;
QGridLayout *mainMuteLayout = nullptr;
//std::vector<EndpointHandler*> *ephs; //std::vector<EndpointHandler*> *ephs;
//std::vector<QSlider> *sliders; //std::vector<QSlider> *sliders;
//public slots:
// void setEndpointHandlers(std::vector<EndpointHandler*> *ephs);
//signals: //signals:
//void valueChanged(int value); //void valueChanged(int value);
}; };
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
//QWidget *centralWidget; //QWidget *centralWidget;
public: public:
MainWindow(std::vector<EndpointHandler*> *ephs, QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
void reloadEndpointWidgets();
//TODO: destroy/empty existing EndpointWidgets
//void setEndpointHandlers(std::vector<EndpointHandler*> *ephs); //void setEndpointHandlers(std::vector<EndpointHandler*> *ephs);
private: private:

View file

@ -1,14 +1,15 @@
#include <iostream>
#include <vector>
//#include <stdio.h> //#include <stdio.h>
//#include <stdlib.h> //#include <stdlib.h>
//#include <qapplicationstatic.h> //#include <qapplicationstatic.h>
//#define QTBLESSED
#include <QApplication> #include <QApplication>
#include <QMainWindow> #include <QMainWindow>
//#include "contclasses.h"
#include "qtclasses.h" #include "qtclasses.h"
#include "global.h"
OverseerHandler *osh = new OverseerHandler(); OverseerHandler *osh = new OverseerHandler();
@ -21,19 +22,16 @@ QApplication* createApplication(int &argc, char *argv[])
int main (int argc, char* argv[]) { int main (int argc, char* argv[]) {
//QApplication::setStyle("windowsvista"); //QApplication::setStyle("windowsvista");
//INIT CONT //INIT CONT
std::vector<Endpoint*> epts = OverseerHandler::getOverseer()->getPlaybackEndpoints(); log_debugcpp("main init");
std::vector<EndpointHandler*>* ephs = new std::vector<EndpointHandler*>; osh->reloadEndpointHandlers();
for(unsigned int i = 0; i < epts.size(); i++){ log_debugcpp("Reloaded endpoint handlers");
EndpointHandler *eph = new EndpointHandler(epts.at(i));
ephs->push_back(eph);
}
osh->setEndpointHandlers(ephs);
//INIT FRONT //INIT FRONT
QScopedPointer<QApplication> app(createApplication(argc, argv)); QScopedPointer<QApplication> app(createApplication(argc, argv));
MainWindow window = MainWindow(ephs); MainWindow window = MainWindow();
//window.setEndpointHandlers(ephs); //window.setEndpointHandlers(ephs);
app->setStyle("windowsvista"); app->setStyle("windowsvista");
window.show(); window.show();
return app->exec(); return app->exec();
} }