fixed race cons ep/eph coll, unwanted session state update crash

+ some minor code cleanup
This commit is contained in:
Hane 2025-01-15 21:47:35 +01:00
commit 59a92fa34b
7 changed files with 144 additions and 127 deletions

View file

@ -48,8 +48,8 @@ HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSe
Session* newSession = new Session(this->eph->getEndpoint(), sessionControl); Session* newSession = new Session(this->eph->getEndpoint(), sessionControl);
SessionThreadParams tp = { .eph = this->eph, .session = newSession, .isDelete = false }; SessionThreadParams tp = { .eph = this->eph, .session = newSession, .isDelete = false };
std::thread sessionThread(EndpointNewSessionCallback::createSessionThread, tp); std::thread newSessionThread(EndpointNewSessionCallback::createSessionThread, tp);
sessionThread.detach(); newSessionThread.detach();
} }
return S_OK; return S_OK;
@ -97,20 +97,32 @@ HRESULT EndpointVolumeCallback::QueryInterface(REFIID riid, VOID **ppvInterface)
HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) { HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) {
if (pNotify == NULL) return E_INVALIDARG; if (pNotify == NULL) return E_INVALIDARG;
AUDIO_VOLUME_NOTIFICATION_DATA paramCopy;
memcpy(&paramCopy, pNotify, sizeof(AUDIO_VOLUME_NOTIFICATION_DATA));
float* channelVolumes = (float*)malloc(pNotify->nChannels * sizeof(float));
for (int i = 0; i < pNotify->nChannels; i++) {
channelVolumes[i] = pNotify->afChannelVolumes[i];
}
std::thread updateVolumeThread(&EndpointVolumeCallback::updateVolumeInfo, this, paramCopy, channelVolumes);
updateVolumeThread.detach();
return S_OK;
}
void EndpointVolumeCallback::updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes) {
//delete osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller; //delete osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller;
//osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.freeData4(); //osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.freeData4();
//Could've made a function or = override to hide this within Nguid, but back in cont = bad. //Could've made a function or = override to hide this within Nguid, but back in cont = bad.
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data1 \ osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data1 \
= pNotify->guidEventContext.Data1; = newVolume.guidEventContext.Data1;
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \ osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \
= pNotify->guidEventContext.Data2; = newVolume.guidEventContext.Data2;
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data3 \ osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data3 \
= pNotify->guidEventContext.Data3; = newVolume.guidEventContext.Data3;
for(int i = 0; i < 8 /* Data4 size */; i++){ for(int i = 0; i < 8 /* Data4 size */; i++){
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data4[i] = pNotify->guidEventContext.Data4[i]; osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data4[i] = newVolume.guidEventContext.Data4[i];
} }
//memcpy(&osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller, &pNotify->guidEventContext,sizeof(NGuid) ); //memcpy(&osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller, &newVolume.guidEventContext,sizeof(NGuid) );
Flows flow = this->ep->getFlow(); Flows flow = this->ep->getFlow();
EndpointHandler* eph = nullptr; EndpointHandler* eph = nullptr;
if (flow & Flows::FLOW_PLAYBACK) { if (flow & Flows::FLOW_PLAYBACK) {
@ -119,21 +131,21 @@ HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify
eph = osh->getCaptureEndpointHandlers().at(this->ep->getIndex()); eph = osh->getCaptureEndpointHandlers().at(this->ep->getIndex());
} }
eph->getCallbackInfo()->muted = pNotify->bMuted; eph->getCallbackInfo()->muted = newVolume.bMuted;
eph->getCallbackInfo()->mainVolume = pNotify->fMasterVolume; eph->getCallbackInfo()->mainVolume = newVolume.fMasterVolume;
eph->getCallbackInfo()->channels = pNotify->nChannels; eph->getCallbackInfo()->channels = newVolume.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 < newVolume.nChannels) {
if (flow & Flows::FLOW_PLAYBACK) if (flow & Flows::FLOW_PLAYBACK)
eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j]; eph->getCallbackInfo()->channelVolumes[j] = channelVolumes[j];
else else
eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j]; eph->getCallbackInfo()->channelVolumes[j] = channelVolumes[j];
j++; j++;
} }
return S_OK; free(channelVolumes);
} }
@ -210,31 +222,34 @@ HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
std::wstring endpointId = std::wstring(pwstrDeviceId); std::wstring endpointId = std::wstring(pwstrDeviceId);
EndpointState newState;
switch (dwNewState) { switch (dwNewState) {
case DEVICE_STATE_ACTIVE: case DEVICE_STATE_ACTIVE:
osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_ACTIVE); newState = EndpointState::ENDPOINT_ACTIVE;
break; break;
case DEVICE_STATE_DISABLED: case DEVICE_STATE_DISABLED:
osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_DISABLED); newState = EndpointState::ENDPOINT_DISABLED;
break; break;
case DEVICE_STATE_NOTPRESENT: case DEVICE_STATE_NOTPRESENT:
osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_NOTPRESENT); newState = EndpointState::ENDPOINT_NOTPRESENT;
break; break;
case DEVICE_STATE_UNPLUGGED: case DEVICE_STATE_UNPLUGGED:
osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_UNPLUGGED); newState = EndpointState::ENDPOINT_UNPLUGGED;
break; break;
} }
std::thread newEndpointThread(&OverseerHandler::reviseEndpointShowing, osh,
endpointId, newState);
newEndpointThread.detach();
return S_OK; return S_OK;
} }
HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
//TODO: New thread + Mutex std::thread propertyThread(&Overseer::updateEndpointInfo, os, std::wstring(pwstrDeviceId));
os->updateEndpointInfo(std::wstring(pwstrDeviceId)); propertyThread.detach();
return S_OK; return S_OK;
} }
Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx){ Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx) {
this->endpoint = ep; this->endpoint = ep;
this->idx = idx; this->idx = idx;
this->policyConfig = policyConfig; this->policyConfig = policyConfig;
@ -242,7 +257,9 @@ Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx){
* It can't multiflag, it's that stupid. MS momento. * It can't multiflag, it's that stupid. MS momento.
* Only shows most relevant flag according to MS, i.e. 0110 sends 0010 * Only shows most relevant flag according to MS, i.e. 0110 sends 0010
*/ */
if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-2);}; DWORD state;
if(FAILED(endpoint->GetState(&state))) {exit(-2);};
this->endpointState = (EndpointState)state;
if(this->endpointState == EndpointState::ENDPOINT_ACTIVE) { if(this->endpointState == EndpointState::ENDPOINT_ACTIVE) {
activateEndpointVolume(); activateEndpointVolume();
@ -253,11 +270,9 @@ Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx){
} }
reloadEndpointChannels();
//todo: atexit into exit Gather ID //todo: atexit into exit Gather ID
LPWSTR tempString = nullptr; LPWSTR tempString = nullptr;
if (FAILED(endpoint->GetId(&tempString))) {exit(-1);}; if (FAILED(endpoint->GetId(&tempString))) { exit(-1); };
endpointId = std::wstring(tempString); endpointId = std::wstring(tempString);
log_wdebugcpp(endpointId); log_wdebugcpp(endpointId);
CoTaskMemFree(tempString); CoTaskMemFree(tempString);
@ -265,6 +280,8 @@ Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx){
endpoint->OpenPropertyStore(STGM_READ, &properties); endpoint->OpenPropertyStore(STGM_READ, &properties);
this->updateName(); this->updateName();
this->setFlow(); this->setFlow();
reloadEndpointChannels();
} }
void Endpoint::updateName() { void Endpoint::updateName() {
@ -319,28 +336,19 @@ void Endpoint::addSession(Session* session) {
} }
void Endpoint::activateEndpointVolume() { void Endpoint::activateEndpointVolume() {
//bool extraThread = false; //If this EP is created after init, COM won't be initialized on the executing thread.
/*
* Forgive me, for MS has sinned, and now I must too.
*/
if (this->endpointVolume == nullptr){
HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (this->endpointVolume == nullptr) {
endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&this->endpointVolume); endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&this->endpointVolume);
//todo: check header //todo: check header
if(FAILED(endpoint->Activate(__uuidof(IAudioMeterInformation), if(FAILED(endpoint->Activate(__uuidof(IAudioMeterInformation),
CLSCTX_ALL, NULL, (void**)&endpointPeakMeter))) { log_debugcpp("peakbros..."); } CLSCTX_ALL, NULL, (void**)&endpointPeakMeter))) {
// log_debugcpp("peakbros...");
}
//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) if (result == S_OK)
CoUninitialize(); CoUninitialize();
}
} }
void Endpoint::reloadEndpointChannels() { void Endpoint::reloadEndpointChannels() {
@ -393,7 +401,7 @@ bool Endpoint::getMute(){
return mute; return mute;
} }
void Endpoint::setState(uint8_t state){ void Endpoint::setState(EndpointState state){
this->endpointState = state; this->endpointState = state;
if(state == EndpointState::ENDPOINT_ACTIVE) { if(state == EndpointState::ENDPOINT_ACTIVE) {
this->activateEndpointVolume(); this->activateEndpointVolume();
@ -401,7 +409,7 @@ void Endpoint::setState(uint8_t state){
} }
} }
size_t Endpoint::getState(){ EndpointState Endpoint::getState(){
return this->endpointState; return this->endpointState;
} }
@ -409,9 +417,13 @@ void Endpoint::setVolume(NGuid guid, int channel, float volume) {
//TIP: There used to be log messages here. Now, it's a ghost town. //TIP: There used to be log messages here. Now, it's a ghost town.
GUID tempMsGuid = NGuidToGUID(guid); GUID tempMsGuid = NGuidToGUID(guid);
if (channel == AudioChannel::CHANNEL_MAIN) { if (channel == AudioChannel::CHANNEL_MAIN) {
if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) {}; if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) {
log_wdebugcpp(L"Master volume failed for endpoint: " + friendlyName);
};
} else { } else {
if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) {}; if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) {
log_wdebugcpp(L"Channel " + std::to_wstring(channel) + L" volume failed for endpoint: " + friendlyName);
};
} }
} }
@ -525,9 +537,8 @@ Endpoint::~Endpoint(){
} }
void Overseer::initCOMLibrary() { void Overseer::initCOMLibrary() {
OutputDebugStringW(L"EPWidget creation\n");
if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) {
log_debugcpp("si"); }; log_debugcpp("Not even COM?"); };
//Retrieving endpoint enumerator //Retrieving endpoint enumerator
@ -535,7 +546,7 @@ void Overseer::initCOMLibrary() {
if(FAILED(CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, if(FAILED(CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL,
CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),
(void**)&deviceEnumerator)) ) (void**)&deviceEnumerator)) )
{ log_debugcpp("si"); }; { log_debugcpp("No MMDeviceEnum. Weird."); };
GUID tempGuid; GUID tempGuid;
if(FAILED(CoCreateGuid(&tempGuid))) { log_debugcpp("Failed to obtain GUID: " ); }; if(FAILED(CoCreateGuid(&tempGuid))) { log_debugcpp("Failed to obtain GUID: " ); };
@ -551,7 +562,7 @@ void Overseer::initCOMLibrary() {
//TODO: Uninitialize COM //TODO: Uninitialize COM
} }
void Overseer::reloadEndpoints(Flows flow) { void Overseer::createEndpoints(Flows flow) {
IMMDeviceCollection *deviceCollection; IMMDeviceCollection *deviceCollection;
unsigned int numEndpoints; unsigned int numEndpoints;
EDataFlow MSflow = (flow == Flows::FLOW_PLAYBACK ? EDataFlow::eRender : EDataFlow::eCapture); EDataFlow MSflow = (flow == Flows::FLOW_PLAYBACK ? EDataFlow::eRender : EDataFlow::eCapture);
@ -631,9 +642,15 @@ void Overseer::reloadEndpoints(Flows flow) {
} }
Endpoint* Overseer::addEndpoint(std::wstring endpointId, /* out */Flows* flow = nullptr) { Endpoint* Overseer::addEndpoint(std::wstring endpointId, /* out */Flows* flow = nullptr) {
//This method is only called from the new endpoint callback and its subsequent thread,
//so another STA can be safely instantiated
if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) {
log_debugcpp("EP Callback Thread failed. Sad!");
return nullptr;
}
IMMDevice* newep; IMMDevice* newep;
if(FAILED(deviceEnumerator->GetDevice((LPCWSTR)endpointId.c_str(), &newep))) if(FAILED(deviceEnumerator->GetDevice((LPCWSTR)endpointId.c_str(), &newep)))
log_debugcpp("ay caramba con la hot metida."); log_debugcpp("ay caramba con la hot metida. Sad!");
Endpoint *endpoint = new Endpoint(newep, policyConfig); Endpoint *endpoint = new Endpoint(newep, policyConfig);
@ -646,10 +663,11 @@ Endpoint* Overseer::addEndpoint(std::wstring endpointId, /* out */Flows* flow =
this->captureDevices.push_back(endpoint); this->captureDevices.push_back(endpoint);
} }
if (flow != nullptr) *flow = getFlow; if (flow != nullptr) *flow = getFlow;
CoUninitialize();
return endpoint; return endpoint;
} }
Overseer::Overseer() : epsc(this){ Overseer::Overseer() : epsc(this) {
log_debugcpp("Initializing Overseer"); log_debugcpp("Initializing Overseer");
//Storing exe path for later use (mainly "Run on startup") //Storing exe path for later use (mainly "Run on startup")
@ -669,20 +687,19 @@ Overseer::Overseer() : epsc(this){
log_debugcpp("-Initializing COM"); log_debugcpp("-Initializing COM");
initCOMLibrary(); initCOMLibrary();
//Obtaining playback endpoint collection on this point in time //Obtaining playback endpoint collection
reloadEndpoints(Flows::FLOW_PLAYBACK); createEndpoints(Flows::FLOW_PLAYBACK);
//reloadEndpoints(Flows::FLOW_CAPTURE); //reloadEndpoints(Flows::FLOW_CAPTURE);
//Registering for endpoint information callback
//this->epsc.fill(deviceEnumerator, playbackDevices, captureDevices);
//this->epsc.fill(deviceEnumerator);
if(FAILED(deviceEnumerator->RegisterEndpointNotificationCallback(((IMMNotificationClient*)&epsc)))) { log_debugcpp("when no enchufas......"); }
} }
NGuid Overseer::getGuid() { NGuid Overseer::getGuid() {
return guid; return guid;
} }
void Overseer::registerEndpointSituationCallback() {
if(FAILED(deviceEnumerator->RegisterEndpointNotificationCallback(((IMMNotificationClient*)&epsc)))) { log_debugcpp("when no enchufas......"); }
}
std::vector<Endpoint*> Overseer::getPlaybackEndpoints() { std::vector<Endpoint*> Overseer::getPlaybackEndpoints() {
return playbackDevices; return playbackDevices;
} }
@ -692,19 +709,22 @@ std::vector<Endpoint*> Overseer::getCaptureEndpoints() {
} }
void Overseer::updateEndpointInfo(std::wstring endpointId) { void Overseer::updateEndpointInfo(std::wstring endpointId) {
log_wdebugcpp(L"new name Endpoint id: " + endpointId);
//todo: reintroduce capture devices //todo: reintroduce capture devices
playbackMutex.lock();
log_wdebugcpp(L"new name Endpoint id: " + endpointId);
for(auto ep : playbackDevices) { for(auto ep : playbackDevices) {
if (ep->getId() == endpointId) { if (ep->getId() == endpointId && ep->getState() == EndpointState::ENDPOINT_ACTIVE) {
ep->updateName(); ep->updateName();
osh->updateFrontEndpointName(ep); osh->updateFrontEndpointName(ep);
break; break;
} }
} }
playbackMutex.unlock();
} }
Overseer::~Overseer(){ Overseer::~Overseer(){
log_debugcpp("cum"); //Overseer is never deleted. This is to annotate what would need to be taken care of.
log_debugcpp("jej");
deviceEnumerator->Release(); deviceEnumerator->Release();
for(unsigned long long i = 0; i < playbackDevices.size(); i++){ for(unsigned long long i = 0; i < playbackDevices.size(); i++){
delete(playbackDevices.at(i)); delete(playbackDevices.at(i));
@ -885,7 +905,6 @@ bool Environment::checkStartup(HKEY rootKeyFlags) {
} }
void Environment::updateStartupConfig(bool onStartup) { void Environment::updateStartupConfig(bool onStartup) {
DWORD typeReturned;
wchar_t regSubKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run\\"; wchar_t regSubKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run\\";
if(!onStartup) { if(!onStartup) {

View file

@ -58,8 +58,8 @@ class Endpoint {
float getVolume(int channel); float getVolume(int channel);
void setMute(NGuid guid, bool muted); void setMute(NGuid guid, bool muted);
bool getMute(); bool getMute();
void setState(uint8_t state); void setState(EndpointState state);
size_t getState(); EndpointState getState();
Roles getRoles(); Roles getRoles();
void setRoles(Roles role); void setRoles(Roles role);
void assignRoles(Roles role); void assignRoles(Roles role);
@ -101,7 +101,7 @@ class Endpoint {
std::wstring descriptionName; std::wstring descriptionName;
std::wstring deviceName; std::wstring deviceName;
std::wstring endpointId; std::wstring endpointId;
unsigned long endpointState; EndpointState endpointState;
Roles endpointRoles = (Roles)0; Roles endpointRoles = (Roles)0;
uint64_t idx; uint64_t idx;
//Not implemented in llvm-mingw. Sad! todo: mingw patch //Not implemented in llvm-mingw. Sad! todo: mingw patch
@ -118,6 +118,7 @@ class EndpointVolumeCallback : public IAudioEndpointVolumeCallback {
ULONG Release(); ULONG Release();
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface); HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
HRESULT OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA update); HRESULT OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA update);
void updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes);
//~EndpointVolumeCallback(); //~EndpointVolumeCallback();
private: private:
@ -146,15 +147,18 @@ class Overseer {
public: public:
Overseer(); Overseer();
void registerEndpointSituationCallback();
NGuid getGuid(); NGuid getGuid();
std::vector<Endpoint*> getPlaybackEndpoints(); std::vector<Endpoint*> getPlaybackEndpoints();
std::vector<Endpoint*> getCaptureEndpoints(); std::vector<Endpoint*> getCaptureEndpoints();
void updateEndpointInfo(std::wstring endpointId); void updateEndpointInfo(std::wstring endpointId);
void reloadEndpoints(Flows flow); void createEndpoints(Flows flow);
Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow); Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow);
std::mutex playbackMutex;
std::mutex captureMutex;
//void setEndpointStatusCallback(); //void setEndpointStatusCallback();
//void setEndpointStatusCallback(); //void setEndpointStatusCallback();
@ -166,8 +170,6 @@ class Overseer {
~Overseer(); ~Overseer();
private: private:
std::wstring exeAbsPath;
void initCOMLibrary(); void initCOMLibrary();
NGuid guid; NGuid guid;
@ -177,7 +179,6 @@ class Overseer {
std::vector<Endpoint*> playbackDevices; std::vector<Endpoint*> playbackDevices;
std::vector<Endpoint*> captureDevices; std::vector<Endpoint*> captureDevices;
IPolicyConfig7* policyConfig; IPolicyConfig7* policyConfig;
friend class Endpoint; friend class Endpoint;
//IMMDeviceCollection *deviceCollection; //IMMDeviceCollection *deviceCollection;
@ -222,7 +223,9 @@ namespace Environment {
bool isToRunAtStartup(); bool isToRunAtStartup();
uint32_t getAccentColor(); uint32_t getAccentColor();
//todo: binary path cache unused
static std::wstring exeAbsPath; static std::wstring exeAbsPath;
static uint32_t exeAbsPathLen;
static bool lightMode; static bool lightMode;
static bool startup = false; static bool startup = false;
static HKEY scope; static HKEY scope;

View file

@ -93,8 +93,10 @@ HRESULT SessionStateCallback::OnStateChanged(AudioSessionState NewState) {
} }
HRESULT SessionStateCallback::OnSessionDisconnected(AudioSessionDisconnectReason DisconnectReason) { HRESULT SessionStateCallback::OnSessionDisconnected(AudioSessionDisconnectReason DisconnectReason) {
if (DisconnectReason != DisconnectReasonDeviceRemoval) {
sh->setState(SessionState::DISCONNECTED); sh->setState(SessionState::DISCONNECTED);
sh->reviseSessionShowing(SessionState::DISCONNECTED); sh->reviseSessionShowing(SessionState::DISCONNECTED);
}
return S_OK; return S_OK;
} }

View file

@ -24,7 +24,6 @@ void setConfigDirToDefaults() {
} }
EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) { EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) {
//std::vector<Endpoint*> endpoints = osh->getPlaybackEndpoints().at(idx);
this->idx = idx; this->idx = idx;
this->flow = flow; this->flow = flow;
this->ep = (flow == Flows::FLOW_PLAYBACK ? osh->getPlaybackEndpoints().at(idx) : osh->getCaptureEndpoints().at(idx)); this->ep = (flow == Flows::FLOW_PLAYBACK ? osh->getPlaybackEndpoints().at(idx) : osh->getCaptureEndpoints().at(idx));
@ -62,16 +61,6 @@ Flows EndpointHandler::getFlow(){
return ep->getFlow(); return ep->getFlow();
} }
/* these two, currently unused. If I use them, I should feel bad.
* Endpoint* EndpointHandler::getEndpoint() {
* return this->ep;
* }
*
* EndpointVolumeCallback* EndpointHandler::getEndpointVolumeCallback() {
* return this->epc;
* }
*/
BackEndpointVolumeCallbackInfo* EndpointHandler::getCallbackInfo(){ BackEndpointVolumeCallbackInfo* EndpointHandler::getCallbackInfo(){
return &this->callbackInfo; return &this->callbackInfo;
} }
@ -134,12 +123,12 @@ void EndpointHandler::setBackEndpointVolumeCallbackInfoContent(uint8_t state) {
} }
} }
void EndpointHandler::setState(uint8_t state){ void EndpointHandler::setState(EndpointState state){
ep->setState(state); ep->setState(state);
this->setBackEndpointVolumeCallbackInfoContent(state); this->setBackEndpointVolumeCallbackInfoContent(state);
} }
void EndpointHandler::setState(uint8_t state, uint64_t index){ void EndpointHandler::setState(EndpointState state, uint64_t index){
ep->setState(state); ep->setState(state);
this->setFrontVisibilityInfo((EndpointState)state, index); this->setFrontVisibilityInfo((EndpointState)state, index);
this->setBackEndpointVolumeCallbackInfoContent(state); this->setBackEndpointVolumeCallbackInfoContent(state);
@ -318,7 +307,7 @@ uint64_t OverseerHandler::getCaptureEndpointsCount(){
return this->os->getCaptureEndpoints().size(); return this->os->getCaptureEndpoints().size();
} }
void OverseerHandler::reloadEndpointHandlers(){ void OverseerHandler::createEndpointHandlers(){
//todo: add capture //todo: add capture
//std::vector<EndpointHandler*>* ephs = new std::vector<EndpointHandler*>; //std::vector<EndpointHandler*>* ephs = new std::vector<EndpointHandler*>;
@ -326,9 +315,7 @@ void OverseerHandler::reloadEndpointHandlers(){
for(uint64_t i = 0; i < this->getPlaybackEndpointsCount(); i++){ for(uint64_t i = 0; i < this->getPlaybackEndpointsCount(); i++){
log_debugcpp("Creating Playback handler " + std::to_string(i)); log_debugcpp("Creating Playback handler " + std::to_string(i));
new EndpointHandler(i, Flows::FLOW_PLAYBACK);
EndpointHandler* ephexx = new EndpointHandler(i, Flows::FLOW_PLAYBACK);
//this->playbackEndpointHandlers.push_back(ephexx);
log_debugcpp("Created Playback handler " + std::to_string(i) + ", adding to vector. " + " VSize: " + std::to_string(this->playbackEndpointHandlers.size())); log_debugcpp("Created Playback handler " + std::to_string(i) + ", adding to vector. " + " VSize: " + std::to_string(this->playbackEndpointHandlers.size()));
} }
@ -336,37 +323,27 @@ void OverseerHandler::reloadEndpointHandlers(){
log_debugcpp("Capture VSize: " + log_debugcpp("Capture VSize: " +
std::to_string(this->getCaptureEndpointsCount())); std::to_string(this->getCaptureEndpointsCount()));
for(uint64_t i = 0; i < this->getCaptureEndpointsCount(); i++){ for(uint64_t i = 0; i < this->getCaptureEndpointsCount(); i++) {
log_debugcpp("Creating Capture handler " + std::to_string(i)); log_debugcpp("Creating Capture handler " + std::to_string(i));
new EndpointHandler(i, Flows::FLOW_CAPTURE);
/*
* if(i < (this->captureEndpointHandlers.size()) &&
* this->captureEndpointHandlers.at(i) != nullptr)
* delete captureEndpointHandlers.at(i);
*/
EndpointHandler* ephoo = new EndpointHandler(i, Flows::FLOW_CAPTURE);
//this->captureEndpointHandlers.push_back(ephoo);
log_debugcpp("Created Capture handler " + std::to_string(i) + ", adding to vector. " + " VSize: " + std::to_string(this->captureEndpointHandlers.size())); log_debugcpp("Created Capture handler " + std::to_string(i) + ", adding to vector. " + " VSize: " + std::to_string(this->captureEndpointHandlers.size()));
/* /*
* if (i >= this->captureEndpointHandlers.size()) * if (i >= this->captureEndpointHandlers.size())
* captureEndpointHandlers.push_back(eph); * captureEndpointHandlers.push_back(eph);
* else captureEndpointHandlers.at(i) = eph; * else captureEndpointHandlers.at(i) = eph;
*/ */
} }
//setEndpointHandlers(ephs); os->registerEndpointSituationCallback();
} }
EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId, /* out */ Flows *flow = nullptr){ EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId, /* out */ Flows *flow = nullptr) {
//This method is only called from the new endpoint callback and its subsequent thread
Flows localFlow; Flows localFlow;
Endpoint* newEp = this->os->addEndpoint(endpointId, &localFlow); Endpoint* newEp = this->os->addEndpoint(endpointId, &localFlow);
uint64_t ephIdx = (localFlow == Flows::FLOW_PLAYBACK ? this->getPlaybackEndpointsCount() : this->getCaptureEndpointsCount()) - 1; uint64_t ephIdx = (localFlow == Flows::FLOW_PLAYBACK ? this->getPlaybackEndpointsCount() : this->getCaptureEndpointsCount()) - 1;
EndpointHandler* newEph = new EndpointHandler(ephIdx, localFlow); EndpointHandler* newEph = new EndpointHandler(ephIdx, localFlow);
// std::vector<EndpointHandler*> getPlaybackEndpointHandlers();
//std::vector<EndpointHandler*> getCaptureEndpointHandlers();
if (flow != nullptr) *flow = localFlow; if (flow != nullptr) *flow = localFlow;
return newEph; return newEph;
} }
@ -403,6 +380,10 @@ void OverseerHandler::updateFrontEndpointName(Endpoint* ep) {
void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointState state) { void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointState state) {
//TODO: Race condition!!!!! //TODO: Race condition!!!!!
std::vector<EndpointHandler*> allHandlers; std::vector<EndpointHandler*> allHandlers;
handlersPlaybackMutex.lock();
handlersCaptureMutex.lock();
os->playbackMutex.lock();
os->captureMutex.lock();
allHandlers.insert(allHandlers.end(), this->captureEndpointHandlers.begin(), this->captureEndpointHandlers.end()); allHandlers.insert(allHandlers.end(), this->captureEndpointHandlers.begin(), this->captureEndpointHandlers.end());
allHandlers.insert(allHandlers.end(), this->playbackEndpointHandlers.begin(), this->playbackEndpointHandlers.end()); allHandlers.insert(allHandlers.end(), this->playbackEndpointHandlers.begin(), this->playbackEndpointHandlers.end());
EndpointHandler* eph = nullptr; EndpointHandler* eph = nullptr;
@ -425,11 +406,15 @@ void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointSta
//todo: mic done but disabled. Tab-kun will come... //todo: mic done but disabled. Tab-kun will come...
if (flow == Flows::FLOW_CAPTURE) return; if (flow == Flows::FLOW_CAPTURE) return;
if(eph && EndpointState::ENDPOINT_ACTIVE & state) { if (eph && EndpointState::ENDPOINT_ACTIVE & state) {
this->addEndpointWidget(eph); this->addEndpointWidget(eph);
} else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE){ } else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE) {
this->removeEndpointWidget(eph->getFrontVisibilityIndex()); this->removeEndpointWidget(eph->getFrontVisibilityIndex());
} }
handlersPlaybackMutex.unlock();
handlersCaptureMutex.unlock();
os->playbackMutex.unlock();
os->captureMutex.unlock();
return; return;
} }

View file

@ -58,8 +58,8 @@ public:
void setVolume(NGuid guid, int channel, int value); void setVolume(NGuid guid, int channel, int value);
void setMute(NGuid guid, bool muted); void setMute(NGuid guid, bool muted);
void setState(uint8_t state); void setState(EndpointState state);
void setState(uint8_t state, uint64_t idx); void setState(EndpointState state, uint64_t idx);
float getPeakVolume(); float getPeakVolume();
/* sessions */ /* sessions */
@ -137,10 +137,12 @@ public:
void pushBackEndpointHandler(EndpointHandler* eph, Flows flow); void pushBackEndpointHandler(EndpointHandler* eph, Flows flow);
uint64_t getPlaybackEndpointsCount(); uint64_t getPlaybackEndpointsCount();
uint64_t getCaptureEndpointsCount(); uint64_t getCaptureEndpointsCount();
void reloadEndpointHandlers(); void createEndpointHandlers();
EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow); EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow);
NGuid getGuid(); NGuid getGuid();
std::mutex handlersPlaybackMutex;
std::mutex handlersCaptureMutex;
/* /*
* void setSessionVolumeCallback(std::function<void(float)> changeSessionVolume); * void setSessionVolumeCallback(std::function<void(float)> changeSessionVolume);
* void setSessionVolume(float newValue, ); * void setSessionVolume(float newValue, );
@ -150,6 +152,7 @@ private:
Overseer *os; Overseer *os;
std::vector<EndpointHandler*> playbackEndpointHandlers; std::vector<EndpointHandler*> playbackEndpointHandlers;
std::vector<EndpointHandler*> captureEndpointHandlers; std::vector<EndpointHandler*> captureEndpointHandlers;
std::function<void(Roles, std::wstring /* endpointid */)> changeFrontDefaults; std::function<void(Roles, std::wstring /* endpointid */)> changeFrontDefaults;
std::function<void(uint64_t /* epw id */)> removeEndpointWidget; std::function<void(uint64_t /* epw id */)> removeEndpointWidget;
std::function<void(EndpointHandler*)> addEndpointWidget; std::function<void(EndpointHandler*)> addEndpointWidget;

View file

@ -1089,6 +1089,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
mainMenuBar->setMovable(false); mainMenuBar->setMovable(false);
this->addToolBar(Qt::BottomToolBarArea, mainMenuBar); this->addToolBar(Qt::BottomToolBarArea, mainMenuBar);
/*
* Create initial endpoint widgets batch
*/
reloadEndpointWidgets(); reloadEndpointWidgets();
/* /*
@ -1319,7 +1322,8 @@ void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason) {
void MainWindow::reloadEndpointWidgets() { void MainWindow::reloadEndpointWidgets() {
size_t i = 0; size_t i = 0;
ews.resize(2); ews.resize(2);
//todo: -log flag
osh->handlersPlaybackMutex.lock();
for (size_t epwIndex = 2; i < (osh->getPlaybackEndpointHandlers().size()); i++) { for (size_t epwIndex = 2; i < (osh->getPlaybackEndpointHandlers().size()); i++) {
if (osh->getPlaybackEndpointHandlers().at(i)->getState() == EndpointState::ENDPOINT_ACTIVE){ if (osh->getPlaybackEndpointHandlers().at(i)->getState() == EndpointState::ENDPOINT_ACTIVE){
log_debugcpp("EPWidget creation"); log_debugcpp("EPWidget creation");
@ -1336,6 +1340,7 @@ void MainWindow::reloadEndpointWidgets() {
{ ews.push_back(epw); epw->setIndex(ews.size() - 1); } { ews.push_back(epw); epw->setIndex(ews.size() - 1); }
} }
} }
osh->handlersPlaybackMutex.unlock();
//todo: ya no está aquí tirao como tal, y de hecho, no ha fallado de la manera arriba descrita //todo: ya no está aquí tirao como tal, y de hecho, no ha fallado de la manera arriba descrita
//pero ahora lo añado porque sí solo para garantizar que está y poder reusarlo luego lmao //pero ahora lo añado porque sí solo para garantizar que está y poder reusarlo luego lmao
widgetLayout->addItem(lastRowSpacer, i, 0); widgetLayout->addItem(lastRowSpacer, i, 0);

View file

@ -121,7 +121,7 @@ int main (int argc, char* argv[]) {
//INIT CONT //INIT CONT
log_debugcpp("main init"); log_debugcpp("main init");
osh->reloadEndpointHandlers(); osh->createEndpointHandlers();
log_debugcpp("Reloaded endpoint handlers"); log_debugcpp("Reloaded endpoint handlers");
//INIT FRONT //INIT FRONT