fixed newly arisen race cons (busywaits)
This commit is contained in:
parent
109330dbbd
commit
53f9506115
4 changed files with 59 additions and 11 deletions
|
|
@ -48,8 +48,10 @@ 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 newSessionThread(EndpointNewSessionCallback::createSessionThread, tp);
|
wait = true;
|
||||||
|
std::thread newSessionThread(&EndpointNewSessionCallback::createSessionThread, this, tp);
|
||||||
newSessionThread.detach();
|
newSessionThread.detach();
|
||||||
|
while(wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
@ -57,6 +59,7 @@ HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSe
|
||||||
|
|
||||||
void EndpointNewSessionCallback::createSessionThread(SessionThreadParams params) {
|
void EndpointNewSessionCallback::createSessionThread(SessionThreadParams params) {
|
||||||
params.eph->addSessionSendFront(params.session);
|
params.eph->addSessionSendFront(params.session);
|
||||||
|
this->wait = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EndpointVolumeCallback::EndpointVolumeCallback(Endpoint* ep){
|
EndpointVolumeCallback::EndpointVolumeCallback(Endpoint* ep){
|
||||||
|
|
@ -103,8 +106,10 @@ HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify
|
||||||
for (int i = 0; i < pNotify->nChannels; i++) {
|
for (int i = 0; i < pNotify->nChannels; i++) {
|
||||||
channelVolumes[i] = pNotify->afChannelVolumes[i];
|
channelVolumes[i] = pNotify->afChannelVolumes[i];
|
||||||
}
|
}
|
||||||
|
wait = true;
|
||||||
std::thread updateVolumeThread(&EndpointVolumeCallback::updateVolumeInfo, this, paramCopy, channelVolumes);
|
std::thread updateVolumeThread(&EndpointVolumeCallback::updateVolumeInfo, this, paramCopy, channelVolumes);
|
||||||
updateVolumeThread.detach();
|
updateVolumeThread.detach();
|
||||||
|
while(wait);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,6 +117,9 @@ void EndpointVolumeCallback::updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA new
|
||||||
//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->handlersPlaybackMutex.lock();
|
||||||
|
osh->handlersCaptureMutex.lock();
|
||||||
|
osh->lockEndpoints();
|
||||||
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data1 \
|
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data1 \
|
||||||
= newVolume.guidEventContext.Data1;
|
= newVolume.guidEventContext.Data1;
|
||||||
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \
|
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \
|
||||||
|
|
@ -146,9 +154,15 @@ void EndpointVolumeCallback::updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA new
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
free(channelVolumes);
|
free(channelVolumes);
|
||||||
|
osh->unlockEndpoints();
|
||||||
|
osh->handlersPlaybackMutex.unlock();
|
||||||
|
osh->handlersCaptureMutex.unlock();
|
||||||
|
wait = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EndpointVolumeCallback::reportFinished() {
|
||||||
|
this->wait = false;
|
||||||
|
}
|
||||||
|
|
||||||
EndpointSituationCallback::EndpointSituationCallback(Overseer* os){
|
EndpointSituationCallback::EndpointSituationCallback(Overseer* os){
|
||||||
this->os = os;
|
this->os = os;
|
||||||
|
|
@ -235,18 +249,26 @@ HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, D
|
||||||
newState = EndpointState::ENDPOINT_UNPLUGGED;
|
newState = EndpointState::ENDPOINT_UNPLUGGED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
isEpStateChanging = true;
|
||||||
std::thread newEndpointThread(&OverseerHandler::reviseEndpointShowing, osh,
|
std::thread newEndpointThread(&OverseerHandler::reviseEndpointShowing, osh,
|
||||||
endpointId, newState);
|
endpointId, newState);
|
||||||
newEndpointThread.detach();
|
newEndpointThread.detach();
|
||||||
|
while(isEpStateChanging);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
|
HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
|
||||||
|
isEpStateChanging = true;
|
||||||
std::thread propertyThread(&Overseer::updateEndpointInfo, os, std::wstring(pwstrDeviceId));
|
std::thread propertyThread(&Overseer::updateEndpointInfo, os, std::wstring(pwstrDeviceId));
|
||||||
propertyThread.detach();
|
propertyThread.detach();
|
||||||
|
while(isEpStateChanging);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EndpointSituationCallback::reportFinishedStateChange() {
|
||||||
|
this->isEpStateChanging = false;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
@ -665,6 +687,10 @@ Endpoint* Overseer::addEndpoint(std::wstring endpointId, /* out */Flows* flow =
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overseer::reportFinishedStateChange() {
|
||||||
|
epsc.reportFinishedStateChange();
|
||||||
|
}
|
||||||
|
|
||||||
Overseer::Overseer() : epsc(this) {
|
Overseer::Overseer() : epsc(this) {
|
||||||
log_debugcpp("Initializing Overseer");
|
log_debugcpp("Initializing Overseer");
|
||||||
|
|
||||||
|
|
@ -718,6 +744,7 @@ void Overseer::updateEndpointInfo(std::wstring endpointId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
playbackMutex.unlock();
|
playbackMutex.unlock();
|
||||||
|
epsc.reportFinishedStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
Overseer::~Overseer(){
|
Overseer::~Overseer(){
|
||||||
|
|
|
||||||
|
|
@ -119,11 +119,13 @@ class EndpointVolumeCallback : public IAudioEndpointVolumeCallback {
|
||||||
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);
|
void updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes);
|
||||||
|
void reportFinished();
|
||||||
//~EndpointVolumeCallback();
|
//~EndpointVolumeCallback();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ULONG ref = 1;
|
ULONG ref = 1;
|
||||||
Endpoint* ep;
|
Endpoint* ep;
|
||||||
|
bool wait = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EndpointSituationCallback : public IMMNotificationClient {
|
class EndpointSituationCallback : public IMMNotificationClient {
|
||||||
|
|
@ -137,10 +139,11 @@ class EndpointSituationCallback : public IMMNotificationClient {
|
||||||
HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId);
|
HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId);
|
||||||
HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState);
|
HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState);
|
||||||
HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key);
|
HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key);
|
||||||
|
void reportFinishedStateChange();
|
||||||
private:
|
private:
|
||||||
ULONG ref = 1;
|
ULONG ref = 1;
|
||||||
Overseer* os;
|
Overseer* os;
|
||||||
|
bool isEpStateChanging = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Overseer {
|
class Overseer {
|
||||||
|
|
@ -156,6 +159,8 @@ class Overseer {
|
||||||
|
|
||||||
void createEndpoints(Flows flow);
|
void createEndpoints(Flows flow);
|
||||||
Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow);
|
Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow);
|
||||||
|
|
||||||
|
void reportFinishedStateChange();
|
||||||
|
|
||||||
std::mutex playbackMutex;
|
std::mutex playbackMutex;
|
||||||
std::mutex captureMutex;
|
std::mutex captureMutex;
|
||||||
|
|
@ -196,9 +201,10 @@ class EndpointNewSessionCallback : public IAudioSessionNotification {
|
||||||
ULONG Release();
|
ULONG Release();
|
||||||
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
|
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
|
||||||
HRESULT OnSessionCreated(IAudioSessionControl *NewSession);
|
HRESULT OnSessionCreated(IAudioSessionControl *NewSession);
|
||||||
static void createSessionThread(SessionThreadParams params);
|
void createSessionThread(SessionThreadParams params);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool wait = false;
|
||||||
ULONG ref = 1;
|
ULONG ref = 1;
|
||||||
EndpointHandler *eph;
|
EndpointHandler *eph;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,10 @@ EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId, /* out */
|
||||||
return newEph;
|
return newEph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverseerHandler::reportFinishedStateChange() {
|
||||||
|
os->reportFinishedStateChange();
|
||||||
|
}
|
||||||
|
|
||||||
NGuid OverseerHandler::getGuid() {
|
NGuid OverseerHandler::getGuid() {
|
||||||
return this->os->getGuid();
|
return this->os->getGuid();
|
||||||
}
|
}
|
||||||
|
|
@ -397,24 +401,26 @@ void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointSta
|
||||||
//debug
|
//debug
|
||||||
Flows flow;
|
Flows flow;
|
||||||
if (!eph) {
|
if (!eph) {
|
||||||
if (state ^ EndpointState::ENDPOINT_ACTIVE) return;
|
if (state ^ EndpointState::ENDPOINT_ACTIVE) goto end;
|
||||||
//flow = Flows::FLOW_CAPTURE;
|
//flow = Flows::FLOW_CAPTURE;
|
||||||
eph = osh->addEndpoint(endpointId, &flow);
|
eph = osh->addEndpoint(endpointId, &flow);
|
||||||
} else
|
} else
|
||||||
flow = eph->getFlow();
|
flow = eph->getFlow();
|
||||||
|
|
||||||
//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) goto end;
|
||||||
|
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
handlersPlaybackMutex.unlock();
|
handlersPlaybackMutex.unlock();
|
||||||
handlersCaptureMutex.unlock();
|
handlersCaptureMutex.unlock();
|
||||||
os->playbackMutex.unlock();
|
os->playbackMutex.unlock();
|
||||||
os->captureMutex.unlock();
|
os->captureMutex.unlock();
|
||||||
|
os->reportFinishedStateChange();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -430,3 +436,13 @@ void OverseerHandler::setEndpointHandlers(std::vector<EndpointHandler*> ephs){
|
||||||
this->playbackEndpointHandlers = ephs;
|
this->playbackEndpointHandlers = ephs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverseerHandler::lockEndpoints() {
|
||||||
|
os->playbackMutex.lock();
|
||||||
|
os->captureMutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OverseerHandler::unlockEndpoints() {
|
||||||
|
os->playbackMutex.unlock();
|
||||||
|
os->captureMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,15 +138,14 @@ public:
|
||||||
uint64_t getPlaybackEndpointsCount();
|
uint64_t getPlaybackEndpointsCount();
|
||||||
uint64_t getCaptureEndpointsCount();
|
uint64_t getCaptureEndpointsCount();
|
||||||
void createEndpointHandlers();
|
void createEndpointHandlers();
|
||||||
EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow);
|
EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow);
|
||||||
|
void reportFinishedStateChange();
|
||||||
NGuid getGuid();
|
NGuid getGuid();
|
||||||
|
|
||||||
std::mutex handlersPlaybackMutex;
|
std::mutex handlersPlaybackMutex;
|
||||||
std::mutex handlersCaptureMutex;
|
std::mutex handlersCaptureMutex;
|
||||||
/*
|
void lockEndpoints();
|
||||||
* void setSessionVolumeCallback(std::function<void(float)> changeSessionVolume);
|
void unlockEndpoints();
|
||||||
* void setSessionVolume(float newValue, );
|
|
||||||
*/
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Overseer *os;
|
Overseer *os;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue