fixed synch issues + memleak @ name fetching
This commit is contained in:
parent
f1b734bea6
commit
3239e60471
7 changed files with 87 additions and 43 deletions
|
|
@ -234,6 +234,7 @@ HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
|
|||
|
||||
HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
|
||||
std::wstring endpointId = std::wstring(pwstrDeviceId);
|
||||
log_wdebugcpp(L"Endpoint state change for " + endpointId);
|
||||
EndpointState newState;
|
||||
switch (dwNewState) {
|
||||
case DEVICE_STATE_ACTIVE:
|
||||
|
|
@ -249,7 +250,7 @@ HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, D
|
|||
newState = EndpointState::ENDPOINT_UNPLUGGED;
|
||||
break;
|
||||
}
|
||||
isEpStateChanging = true;
|
||||
isEpStateChanging.exchange(true);
|
||||
std::thread newEndpointThread(&OverseerHandler::reviseEndpointShowing, osh,
|
||||
endpointId, newState);
|
||||
newEndpointThread.detach();
|
||||
|
|
@ -258,7 +259,7 @@ HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, D
|
|||
}
|
||||
|
||||
HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
|
||||
isEpStateChanging = true;
|
||||
isEpStateChanging.exchange(true);
|
||||
std::thread propertyThread(&Overseer::updateEndpointInfo, os, std::wstring(pwstrDeviceId));
|
||||
propertyThread.detach();
|
||||
while(isEpStateChanging);
|
||||
|
|
@ -266,7 +267,8 @@ HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId,
|
|||
}
|
||||
|
||||
void EndpointSituationCallback::reportFinishedStateChange() {
|
||||
this->isEpStateChanging = false;
|
||||
this->isEpStateChanging.exchange(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx) {
|
||||
|
|
@ -325,23 +327,29 @@ void Endpoint::activateEndpointSessions() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!sessionManager) {
|
||||
if (FAILED(endpoint->Activate(__uuidof(IAudioSessionManager2),
|
||||
CLSCTX_ALL, NULL, (void**) &sessionManager))) {
|
||||
log_debugcpp("Couldn't open session manager2, huh");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IAudioSessionEnumerator* sessionEnumerator = nullptr;
|
||||
if (FAILED(sessionManager->GetSessionEnumerator(&sessionEnumerator))) { log_wdebugcpp(L"sesEnumeratorBros..."); return; }
|
||||
if (FAILED(sessionManager->GetSessionEnumerator(&sessionEnumerator))) { log_wdebugcpp(L"sesEnumeratorBros..."); exit(-5); return; }
|
||||
|
||||
endpointSessions.resize(1, nullptr);
|
||||
int sessionCount;
|
||||
sessionEnumerator->GetCount(&sessionCount);
|
||||
for (int i = 0; i < sessionCount; i++) {
|
||||
IAudioSessionControl* sessionControlTmp;
|
||||
sessionEnumerator->GetSession(i, (IAudioSessionControl**)&sessionControlTmp);
|
||||
if (FAILED(sessionEnumerator->GetSession(i, (IAudioSessionControl**)&sessionControlTmp))) {
|
||||
exit(-6);
|
||||
}
|
||||
IAudioSessionControl2* sessionControl;
|
||||
sessionControlTmp->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl);
|
||||
sessionControl->AddRef();
|
||||
if(FAILED(sessionControlTmp->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl))){
|
||||
exit(-7);
|
||||
}
|
||||
sessionControlTmp->Release();
|
||||
Session* session = new Session(this, sessionControl, (size_t)i);
|
||||
if (sessionControl->IsSystemSoundsSession() == S_OK) endpointSessions[0] = session;
|
||||
|
|
@ -350,6 +358,13 @@ void Endpoint::activateEndpointSessions() {
|
|||
sessionEnumerator->Release();
|
||||
}
|
||||
|
||||
/*
|
||||
* void Endpoint::deleteSessionManager() {
|
||||
* sessionManager->Release();
|
||||
* sessionManager = nullptr;
|
||||
* }
|
||||
*/
|
||||
|
||||
void Endpoint::addSession(Session* session) {
|
||||
session->setIndex(this->getSessionCount());
|
||||
endpointSessions.push_back(session);
|
||||
|
|
@ -357,9 +372,15 @@ void Endpoint::addSession(Session* session) {
|
|||
|
||||
void Endpoint::activateEndpointVolume() {
|
||||
//If this EP is created after init, COM won't be initialized on the executing thread.
|
||||
HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
HRESULT result = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
if (this->endpointVolume == nullptr) {
|
||||
endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&this->endpointVolume);
|
||||
if(FAILED(endpoint->Activate(
|
||||
IID_IAudioEndpointVolume,
|
||||
CLSCTX_ALL,
|
||||
NULL,
|
||||
(void**)&this->endpointVolume))) {
|
||||
log_debugcpp("No volume, huh");
|
||||
}
|
||||
|
||||
//todo: check header
|
||||
if(FAILED(endpoint->Activate(__uuidof(IAudioMeterInformation),
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ class Endpoint {
|
|||
void unregisterNewSessionNotification(EndpointNewSessionCallback* ensc);
|
||||
void deleteSessions();
|
||||
void activateEndpointSessions();
|
||||
//void deleteSessionManager();
|
||||
std::mutex endpointSessionsMutex;
|
||||
~Endpoint();
|
||||
|
||||
|
|
@ -91,12 +92,13 @@ class Endpoint {
|
|||
std::vector<Session*> endpointSessions;
|
||||
uint32_t channelCount = 0;
|
||||
IMMDevice *endpoint;
|
||||
IAudioClient *audioClient;
|
||||
IAudioEndpointVolume *endpointVolume = nullptr;
|
||||
IPropertyStore *properties;
|
||||
IAudioMeterInformation *endpointPeakMeter = nullptr;
|
||||
//IAudioClient *audioClient;
|
||||
int64_t defTime, minTime;
|
||||
IAudioSessionManager2 *sessionManager = nullptr;
|
||||
Flows flow;
|
||||
IAudioEndpointVolume *endpointVolume = nullptr;
|
||||
IPropertyStore *properties;
|
||||
std::wstring friendlyName;
|
||||
std::wstring descriptionName;
|
||||
std::wstring deviceName;
|
||||
|
|
@ -105,7 +107,6 @@ class Endpoint {
|
|||
Roles endpointRoles = (Roles)0;
|
||||
uint64_t idx;
|
||||
//Not implemented in llvm-mingw. Sad! todo: mingw patch
|
||||
IAudioMeterInformation *endpointPeakMeter = nullptr;
|
||||
IPolicyConfig7* policyConfig;
|
||||
};
|
||||
|
||||
|
|
@ -125,7 +126,7 @@ class EndpointVolumeCallback : public IAudioEndpointVolumeCallback {
|
|||
private:
|
||||
ULONG ref = 1;
|
||||
Endpoint* ep;
|
||||
bool wait = false;
|
||||
std::atomic<bool> wait = false;
|
||||
};
|
||||
|
||||
class EndpointSituationCallback : public IMMNotificationClient {
|
||||
|
|
@ -143,7 +144,7 @@ class EndpointSituationCallback : public IMMNotificationClient {
|
|||
private:
|
||||
ULONG ref = 1;
|
||||
Overseer* os;
|
||||
bool isEpStateChanging = false;
|
||||
std::atomic<bool> isEpStateChanging = false;
|
||||
};
|
||||
|
||||
class Overseer {
|
||||
|
|
@ -204,7 +205,7 @@ class EndpointNewSessionCallback : public IAudioSessionNotification {
|
|||
void createSessionThread(SessionThreadParams params);
|
||||
|
||||
private:
|
||||
bool wait = false;
|
||||
std::atomic<bool> wait = false;
|
||||
ULONG ref = 1;
|
||||
EndpointHandler *eph;
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ HRESULT SessionStateCallback::QueryInterface(REFIID riid, VOID **ppvInterface) {
|
|||
HRESULT SessionStateCallback::OnDisplayNameChanged(LPCWSTR NewDisplayName, LPCGUID EventContext) {
|
||||
//TODO: Preguntar
|
||||
while(sh->getVolumeInfo()->isNameChanged == true);
|
||||
|
||||
sh->setName(std::wstring(NewDisplayName));
|
||||
sh->getVolumeInfo()->isNameChanged = true;
|
||||
return S_OK;
|
||||
|
|
@ -238,13 +239,15 @@ bool Session::fetchNameViaFD(std::wstring exePath, DWORD pid, std::wstring *sess
|
|||
|
||||
void* fileVersionInfo = malloc(fileVersionInfoSize);
|
||||
if(!GetFileVersionInfoExW(FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL,
|
||||
exePath.c_str(),0,fileVersionInfoSize, fileVersionInfo))
|
||||
exePath.c_str(),0,fileVersionInfoSize, fileVersionInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT translationArrayLen = 0;
|
||||
if (!VerQueryValueW(fileVersionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&translationArray, &translationArrayLen))
|
||||
if (!VerQueryValueW(fileVersionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&translationArray, &translationArrayLen)) {
|
||||
free(fileVersionInfo);
|
||||
return false;
|
||||
|
||||
}
|
||||
//File descriptor parsing
|
||||
//TODO: https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-getuserpreferreduilanguages
|
||||
/* It is possible to retrieve user languages and try to use one of those before falling back to whatever
|
||||
|
|
@ -257,7 +260,6 @@ bool Session::fetchNameViaFD(std::wstring exePath, DWORD pid, std::wstring *sess
|
|||
int8_t syslangIdx = -1;
|
||||
wchar_t metadataStringKey[256];
|
||||
wchar_t* metadataString = NULL;
|
||||
//std::wstring name;
|
||||
for (UINT i = 0; i < availableLangs; i++) {
|
||||
LANGID defaultUILanguage = GetUserDefaultUILanguage();
|
||||
if (defaultUILanguage != translationArray[i].wLanguage)
|
||||
|
|
@ -340,8 +342,6 @@ bool Session::fetchNameViaMSIX(std::wstring exePath, DWORD pid, std::wstring *se
|
|||
if (sessionName->length() > 0)
|
||||
return true;
|
||||
else return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -419,4 +419,7 @@ Session::~Session() {
|
|||
meterInformation->Release();
|
||||
sessionControl->Release();
|
||||
sessionVolume->Release();
|
||||
meterInformation = nullptr;
|
||||
sessionControl = nullptr;
|
||||
sessionVolume = nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) {
|
|||
this->flow = flow;
|
||||
this->ep = (flow == Flows::FLOW_PLAYBACK ? osh->getPlaybackEndpoints().at(idx) : osh->getCaptureEndpoints().at(idx));
|
||||
|
||||
epc = new EndpointVolumeCallback(ep);
|
||||
this->callbackInfo.caller = osh->getGuid();
|
||||
//epName = ep->getName();
|
||||
this->setBackEndpointVolumeCallbackInfoContent(this->getState());
|
||||
|
|
@ -115,7 +114,10 @@ void EndpointHandler::setBackEndpointVolumeCallbackInfoContent(uint8_t state) {
|
|||
callbackInfo.muted = this->getMute();
|
||||
callbackInfo.mainVolume = this->getVolume(AudioChannel::CHANNEL_MAIN);
|
||||
callbackInfo.channels = this->getChannelCount();
|
||||
if (!epc) {
|
||||
epc = new EndpointVolumeCallback(ep);
|
||||
ep->setVolumeCallback(epc);
|
||||
}
|
||||
callbackInfo.channelVolumes.resize(this->callbackInfo.channels);
|
||||
for(uint32_t i = 0; i < this->getChannelCount(); i++){
|
||||
callbackInfo.channelVolumes.at(i) = this->getVolume(i);
|
||||
|
|
@ -181,13 +183,13 @@ Endpoint* EndpointHandler::getEndpoint() {
|
|||
|
||||
void EndpointHandler::addSessionSendFront(Session* session) {
|
||||
if(!ep->endpointSessionsMutex.try_lock()) return;
|
||||
sessionHandlersMutex.lock();
|
||||
|
||||
this->ep->addSession(session);
|
||||
SessionHandler* sessionHandler = new SessionHandler(this, session, (getSessionCount() - 1));
|
||||
ep->endpointSessionsMutex.unlock();
|
||||
|
||||
sessionHandlersMutex.lock();
|
||||
sessionHandlers.push_back(sessionHandler);
|
||||
ep->endpointSessionsMutex.unlock();
|
||||
sessionHandlersMutex.unlock();
|
||||
this->addSessionWidget(sessionHandler);
|
||||
}
|
||||
|
|
@ -203,11 +205,13 @@ void EndpointHandler::removeSessionFromFront(SessionHandler* sh) {
|
|||
void EndpointHandler::deleteSessions() {
|
||||
ep->unregisterNewSessionNotification(ensc);
|
||||
ensc->Release();
|
||||
ensc = nullptr;
|
||||
for (auto sh : sessionHandlers) {
|
||||
delete sh;
|
||||
}
|
||||
sessionHandlers.resize(0);
|
||||
ep->deleteSessions();
|
||||
//ep->deleteSessionManager();
|
||||
}
|
||||
|
||||
void EndpointHandler::createSessionHandlers() {
|
||||
|
|
@ -218,6 +222,9 @@ void EndpointHandler::createSessionHandlers() {
|
|||
sessionHandlers.push_back(sessionHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndpointHandler::createSessionHandlersCallback() {
|
||||
ensc = new EndpointNewSessionCallback(this);
|
||||
ep->registerNewSessionNotification(ensc);
|
||||
}
|
||||
|
|
@ -232,6 +239,12 @@ void EndpointHandler::unlockSessionCollections() {
|
|||
this->ep->endpointSessionsMutex.unlock();
|
||||
}
|
||||
|
||||
void EndpointHandler::removeVolumeCallback() {
|
||||
ep->removeVolumeCallback(epc);
|
||||
epc->Release();
|
||||
epc = nullptr;
|
||||
}
|
||||
|
||||
EndpointHandler::~EndpointHandler() {
|
||||
ep->removeVolumeCallback(epc);
|
||||
ep->unregisterNewSessionNotification(ensc);
|
||||
|
|
@ -411,10 +424,13 @@ void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointSta
|
|||
if (flow == Flows::FLOW_CAPTURE) goto end;
|
||||
|
||||
if (eph && EndpointState::ENDPOINT_ACTIVE & state) {
|
||||
eph->setState(EndpointState::ENDPOINT_ACTIVE);
|
||||
this->addEndpointWidget(eph);
|
||||
} else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE) {
|
||||
eph->removeVolumeCallback();
|
||||
this->removeEndpointWidget(eph->getFrontVisibilityIndex());
|
||||
}
|
||||
|
||||
end:
|
||||
handlersPlaybackMutex.unlock();
|
||||
handlersCaptureMutex.unlock();
|
||||
|
|
|
|||
|
|
@ -76,9 +76,11 @@ public:
|
|||
void removeSessionFromFront(SessionHandler* sh);
|
||||
void deleteSessions();
|
||||
void createSessionHandlers();
|
||||
void createSessionHandlersCallback();
|
||||
std::mutex sessionHandlersMutex;
|
||||
void lockSessionCollections();
|
||||
void unlockSessionCollections();
|
||||
void removeVolumeCallback();
|
||||
|
||||
~EndpointHandler();
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct SessionVolumeInfo {
|
|||
bool muted;
|
||||
float mainVolume;
|
||||
NGuid caller;
|
||||
bool isNameChanged = false;
|
||||
std::atomic<bool> isNameChanged = false;
|
||||
//size_t channels;
|
||||
//std::vector<float> channelVolumes;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -411,6 +411,7 @@ SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent)
|
|||
if (sh->getVolumeInfo()->isNameChanged) {
|
||||
mainLabel->setText(QString::fromStdWString(sh->getName()));
|
||||
mainLabel->setToolTip(QString::fromStdWString(sh->getName()));
|
||||
sh->getVolumeInfo()->isNameChanged = false;
|
||||
}
|
||||
const float roundingFactor = 0.005;
|
||||
mainSlider->blockSignals(true);
|
||||
|
|
@ -538,7 +539,7 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t i
|
|||
|
||||
eph->createSessionHandlers();
|
||||
//todo: sussy
|
||||
this->eph->setState(EndpointState::ENDPOINT_ACTIVE, idx);
|
||||
this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ACTIVE, idx);
|
||||
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
widgetLayout = new QGridLayout(this);
|
||||
//this->setContentsMargins(0, 0, 0, 0);
|
||||
|
|
@ -698,9 +699,9 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t i
|
|||
});
|
||||
|
||||
log_debugcpp("ENDPOINT_WIDGETED");
|
||||
eph->createSessionHandlersCallback();
|
||||
}
|
||||
|
||||
|
||||
void EndpointWidget::addSessionWidget(CustomWidgetEvent<SessionHandler*>* ev){
|
||||
this->setUpdatesEnabled(false);
|
||||
uint64_t index = this->sessionWidgets.size();
|
||||
|
|
@ -779,7 +780,7 @@ void MainWindow::customEvent(QEvent* ev) {
|
|||
}
|
||||
|
||||
//__attribute__((optimize("O0", "unroll-loops")))
|
||||
void MainWindow::removeEndpointWidget(CustomWidgetEvent<uint64_t>* ev){
|
||||
void MainWindow::removeEndpointWidget(CustomWidgetEvent<uint64_t>* ev) {
|
||||
uint64_t i = ev->payload;
|
||||
this->ews.at(i)->setParent(nullptr);
|
||||
this->widgetLayout->removeWidget(ews.at(i));
|
||||
|
|
@ -792,7 +793,7 @@ void MainWindow::removeEndpointWidget(CustomWidgetEvent<uint64_t>* ev){
|
|||
return;
|
||||
}
|
||||
|
||||
void MainWindow::addEndpointWidget(CustomWidgetEvent<EndpointHandler*>* ev){
|
||||
void MainWindow::addEndpointWidget(CustomWidgetEvent<EndpointHandler*>* ev) {
|
||||
EndpointWidget* epw = new EndpointWidget(ev->payload, containerWidget, this->ews.size());
|
||||
//epw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
epw->setParent(this);
|
||||
|
|
@ -924,9 +925,9 @@ EndpointHandler* EndpointWidget::getEndpointHandler(){
|
|||
* }
|
||||
*/
|
||||
|
||||
void EndpointWidget::setIndex(uint64_t idx){
|
||||
void EndpointWidget::setIndex(uint64_t idx) {
|
||||
this->idx = idx;
|
||||
this->eph->setState(EndpointState::ENDPOINT_ACTIVE, this->idx);
|
||||
this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ACTIVE, this->idx);
|
||||
}
|
||||
|
||||
uint64_t EndpointWidget::getIndex(){
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue