240 lines
6.6 KiB
C++
240 lines
6.6 KiB
C++
#pragma once
|
|
|
|
#include "msinclude.h"
|
|
#include "backsessionclasses.h"
|
|
#include "global.h"
|
|
#include "contclasses.h"
|
|
//#include "environment.h"
|
|
|
|
class EndpointVolumeCallback;
|
|
class Session;
|
|
|
|
// Convert a wide UTF16LE string to an UTF8 string
|
|
static inline std::string utf16ToUtf8(const wchar_t* wstr) {
|
|
if(!wstr || wstr[0] == '\0') return std::string();
|
|
int size_needed = WideCharToMultiByte(CP_UTF8,
|
|
0,
|
|
wstr,
|
|
-1,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
std::string str(size_needed, 0);
|
|
WideCharToMultiByte(CP_UTF8,
|
|
0,
|
|
wstr,
|
|
-1,
|
|
&str[0],
|
|
size_needed,
|
|
NULL,
|
|
NULL);
|
|
return str;
|
|
}
|
|
|
|
// Convert an UTF8 string to a wide UTF16LE String
|
|
/*
|
|
* std::wstring utf8_decode(const std::string &str)
|
|
* {
|
|
* if( str.empty() ) return std::wstring();
|
|
* int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
|
|
* std::wstring wstrTo( size_needed, 0 );
|
|
* MultiByteToWideChar (CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
|
|
* return wstrTo;
|
|
* }
|
|
*/
|
|
|
|
class Endpoint {
|
|
|
|
public:
|
|
Endpoint(IMMDevice* endpoint, IPolicyConfig7* policyConfig, uint64_t idx = 0);
|
|
//todo: how to forward declare delegate constructors?
|
|
//Endpoint(IMMDevice* endpoint) : Endpoint(endpoint, 0) {};
|
|
void reloadEndpointChannels();
|
|
uint64_t getIndex();
|
|
void setIndex(uint64_t idx);
|
|
void setVolume(NGuid guid, int channel, float volume);
|
|
uint32_t getChannelCount();
|
|
float getVolume(int channel);
|
|
void setMute(NGuid guid, bool muted);
|
|
bool getMute();
|
|
void setState(EndpointState state);
|
|
EndpointState getState();
|
|
Roles getRoles();
|
|
void setRoles(Roles role);
|
|
void assignRoles(Roles role);
|
|
void removeRoles(Roles role);
|
|
void setFlow();
|
|
Flows getFlow();
|
|
float getPeakVolume();
|
|
std::wstring getId();
|
|
std::wstring getName();
|
|
void updateName();
|
|
|
|
void setVolumeCallback(EndpointVolumeCallback *epc);
|
|
void removeVolumeCallback(EndpointVolumeCallback *epc);
|
|
|
|
/* sessions */
|
|
std::vector<Session*> getSessions();
|
|
size_t getSessionCount();
|
|
void addSession(Session* session);
|
|
void registerNewSessionNotification(EndpointNewSessionCallback* ensc);
|
|
void unregisterNewSessionNotification(EndpointNewSessionCallback* ensc);
|
|
void deleteSessions();
|
|
void activateEndpointSessions();
|
|
//void deleteSessionManager();
|
|
std::mutex endpointSessionsMutex;
|
|
~Endpoint();
|
|
|
|
private:
|
|
void inline activateEndpointVolume();
|
|
|
|
std::vector<Session*> endpointSessions;
|
|
uint32_t channelCount = 0;
|
|
IMMDevice *endpoint;
|
|
IAudioEndpointVolume *endpointVolume = nullptr;
|
|
IPropertyStore *properties;
|
|
IAudioMeterInformation *endpointPeakMeter = nullptr;
|
|
//IAudioClient *audioClient;
|
|
int64_t defTime, minTime;
|
|
IAudioSessionManager2 *sessionManager = nullptr;
|
|
Flows flow;
|
|
std::wstring friendlyName;
|
|
std::wstring descriptionName;
|
|
std::wstring deviceName;
|
|
std::wstring endpointId;
|
|
EndpointState endpointState;
|
|
Roles endpointRoles = (Roles)0;
|
|
uint64_t idx;
|
|
//Not implemented in llvm-mingw. Sad! todo: mingw patch
|
|
IPolicyConfig7* policyConfig;
|
|
};
|
|
|
|
class EndpointVolumeCallback : public IAudioEndpointVolumeCallback {
|
|
|
|
public:
|
|
EndpointVolumeCallback(Endpoint* ep);
|
|
|
|
ULONG AddRef();
|
|
ULONG Release();
|
|
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
|
|
HRESULT OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA update);
|
|
void updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes);
|
|
void reportFinished();
|
|
//~EndpointVolumeCallback();
|
|
|
|
private:
|
|
ULONG ref = 1;
|
|
Endpoint* ep;
|
|
std::atomic<bool> wait = false;
|
|
};
|
|
|
|
class EndpointSituationCallback : public IMMNotificationClient {
|
|
public:
|
|
EndpointSituationCallback(Overseer* os);
|
|
ULONG AddRef();
|
|
ULONG Release();
|
|
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
|
|
HRESULT OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId);
|
|
HRESULT OnDeviceAdded(LPCWSTR pwstrDeviceId);
|
|
HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId);
|
|
HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState);
|
|
HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key);
|
|
void reportFinishedStateChange();
|
|
private:
|
|
ULONG ref = 1;
|
|
Overseer* os;
|
|
std::atomic<bool> isEpStateChanging = false;
|
|
};
|
|
|
|
class Overseer {
|
|
|
|
public:
|
|
Overseer();
|
|
void registerEndpointSituationCallback();
|
|
NGuid getGuid();
|
|
|
|
std::vector<Endpoint*> getPlaybackEndpoints();
|
|
std::vector<Endpoint*> getCaptureEndpoints();
|
|
void updateEndpointInfo(std::wstring endpointId);
|
|
|
|
void createEndpoints(Flows flow);
|
|
Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow);
|
|
|
|
void reportFinishedStateChange();
|
|
|
|
std::mutex playbackMutex;
|
|
std::mutex captureMutex;
|
|
//void setEndpointStatusCallback();
|
|
//void setEndpointStatusCallback();
|
|
|
|
//~Overseer();
|
|
//int getDefaultPlaybackEndpoint(Endpoint** defaultEndpoint);
|
|
//int getDefaultCaptureEndpoint(Endpoint** defaultEndpoint);
|
|
//int getCaptureEndpoints(std::vector<Endpoint*> *captureEndpoints);
|
|
//IMMDeviceEnumerator** setOrigin();
|
|
~Overseer();
|
|
|
|
private:
|
|
void initCOMLibrary();
|
|
|
|
NGuid guid;
|
|
|
|
IMMDeviceEnumerator *deviceEnumerator;
|
|
EndpointSituationCallback epsc;
|
|
|
|
std::vector<Endpoint*> playbackDevices;
|
|
std::vector<Endpoint*> captureDevices;
|
|
IPolicyConfig7* policyConfig;
|
|
friend class Endpoint;
|
|
//IMMDeviceCollection *deviceCollection;
|
|
//int numCaptureEndpoints;
|
|
//std::vector<Endpoint*> *captureDevices;
|
|
};
|
|
|
|
class EndpointNewSessionCallback : public IAudioSessionNotification {
|
|
private:
|
|
struct SessionThreadParams;
|
|
|
|
public:
|
|
EndpointNewSessionCallback(EndpointHandler *eph);
|
|
ULONG AddRef();
|
|
ULONG Release();
|
|
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
|
|
HRESULT OnSessionCreated(IAudioSessionControl *NewSession);
|
|
void createSessionThread(SessionThreadParams params);
|
|
|
|
private:
|
|
std::atomic<bool> wait = false;
|
|
ULONG ref = 1;
|
|
EndpointHandler *eph;
|
|
|
|
struct SessionThreadParams {
|
|
EndpointHandler *eph;
|
|
Session *session;
|
|
bool isDelete;
|
|
};
|
|
};
|
|
|
|
namespace Environment {
|
|
wchar_t* getExeAbsPath(uint32_t *exeAbsPathLength);
|
|
std::string createSettingsPath(SettingsTargetDirectory target);
|
|
void populateSystemValues();
|
|
void openControlPanel();
|
|
ProcessedNativeEvent processTopLevelWindowMessage(void* msg);
|
|
ProcessedNativeEvent updateColors();
|
|
bool checkStartup(HKEY rootKeyFlags);
|
|
void updateStartupConfig(bool onStartup);
|
|
void setStartupConfig(bool onStartup);
|
|
bool isLightMode();
|
|
bool isToRunAtStartup();
|
|
uint32_t getAccentColor();
|
|
|
|
//todo: binary path cache unused
|
|
static std::wstring exeAbsPath;
|
|
static uint32_t exeAbsPathLen;
|
|
static bool lightMode;
|
|
static bool startup = false;
|
|
static HKEY scope;
|
|
static uint32_t accentColor;
|
|
};
|