mixer/src/back/backlasses.h

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;
};