diff --git a/.gitignore b/.gitignore index a4ce7f0..fde2162 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ build *.rdbg *.pdb -*.ps1 -*.exe Makefile Makefile.Debug Makefile.Release \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index cf1a785..0000000 --- a/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Mixer - -## Build - -* Toolchain: [llvm-mingw UCRT 20220906](https://github.com/mstorsjo/llvm-mingw/releases/tag/20220906). - -* Clone [this](https://code.qt.io/cgit/qt/qt5.git/tag/?h=v6.3.2) Qt branch - -* Build Qt from sources following [this](https://wiki.qt.io/Building_Qt_6_from_Git) guide and executing `configure.bat` as such: - -``` -..\qt6\configure.bat -prefix ..\install -static -debug -opensource -confirm-license -qt-zlib -qt-libpng -qt-webp -qt-libjpeg -qt-freetype -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtlocation -skip qtlottie -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquick3d -skip qtquick3dphysics -skip qtquicktimeline -skip qtremoteobjects -skip qtscript -skip qtsensors -skip qtwayland -skip qtwebglplugin -skip qtwebview -skip webengine -nomake examples -nomake tests -``` - -* Clone this repo and execute `bueno.bat`. \ No newline at end of file diff --git a/assets.qrc b/assets.qrc deleted file mode 100644 index 2206a8a..0000000 --- a/assets.qrc +++ /dev/null @@ -1,10 +0,0 @@ - - - assets/selawk.ttf - assets/notificationAreaIcon.png - assets/style.qss - assets/logo.ico - assets/mute.svg - assets/unmute.svg - - diff --git a/assets/installer.ico b/assets/installer.ico deleted file mode 100644 index b4e6f82..0000000 Binary files a/assets/installer.ico and /dev/null differ diff --git a/assets/installer.xcf b/assets/installer.xcf deleted file mode 100644 index 96669f1..0000000 Binary files a/assets/installer.xcf and /dev/null differ diff --git a/assets/logo.ico b/assets/logo.ico deleted file mode 100644 index daac4a4..0000000 Binary files a/assets/logo.ico and /dev/null differ diff --git a/assets/logo.png b/assets/logo.png deleted file mode 100644 index 259e37b..0000000 Binary files a/assets/logo.png and /dev/null differ diff --git a/assets/logo.xcf b/assets/logo.xcf deleted file mode 100644 index 69cafac..0000000 Binary files a/assets/logo.xcf and /dev/null differ diff --git a/assets/notificationAreaIcon.png b/assets/notificationAreaIcon.png deleted file mode 100644 index 0252332..0000000 Binary files a/assets/notificationAreaIcon.png and /dev/null differ diff --git a/assets/selawk.ttf b/assets/selawk.ttf deleted file mode 100644 index 736bac3..0000000 Binary files a/assets/selawk.ttf and /dev/null differ diff --git a/assets/style.qss b/assets/style.qss deleted file mode 100644 index 4f6466c..0000000 --- a/assets/style.qss +++ /dev/null @@ -1,6 +0,0 @@ -QMainWindow { background: rgba(100,100,100,100); } - - - - -QCheckBox:hover, QCheckBox:checked { color: white } \ No newline at end of file diff --git a/assets/uninstaller.ico b/assets/uninstaller.ico deleted file mode 100644 index 24278c2..0000000 Binary files a/assets/uninstaller.ico and /dev/null differ diff --git a/bueno.bat b/bueno.bat index 540be60..67fbd6a 100644 --- a/bueno.bat +++ b/bueno.bat @@ -1,7 +1,2 @@ -taskkill /F /IM "MixerQ.exe" -taskkill /F /IM "MixerQd.exe" -qmake -o build\Makefile .\qtest.pro -REM mingw32-make.exe -C .\build -f Makefile.Release -mingw32-make.exe -C .\build -f Makefile.Debug -REM makensis /DBUILDTYPE=release install\installer.nsi -REM makensis /DBUILDTYPE=debug install\installer.nsi +qmake -o build\Makefile .\qtest.pro +mingw32-make.exe -C .\build -f Makefile diff --git a/install/installer.nsi b/install/installer.nsi deleted file mode 100644 index 7e62045..0000000 --- a/install/installer.nsi +++ /dev/null @@ -1,265 +0,0 @@ -;Auto versioning------------------------------- - - !makensis "/DBUILDTYPE=${BUILDTYPE} version.nsi" - !system "GetVersion.exe" - !include "Version.txt" - ;optional cleanup - !delfile "GetVersion.exe" - !delfile "Version.txt" - -;Includes-------------------------------- - - !include "MUI2.nsh" - !include "nsDialogs.nsh" - !include "LogicLib.nsh" - !include "${NSISDIR}\Contrib\Language files\English.nsh" - !include "${NSISDIR}\Contrib\Language files\Spanish.nsh" - ;!include "${NSISDIR}\Contrib\Language files\English.nsh" - - -;Defines---------------------------------- - !define MUI_LANGDLL_ALLLANGUAGES - !define MUI_UNICON "..\assets\uninstaller.ico" - !define MUI_ICON "..\assets\installer.ico" - - -;-------------------------------- -;General - - ;Name and file - !if ${BUILDTYPE} == "release" - Name "MixerQ" - !else - Name "MixerQd" - !endif - OutFile "..\build\bin\MixerQ-installer-${version}.exe" - - ;Get installation folder from registry if available - ;InstallDirRegKey HKCU "Software\Modern UI Test" "" - - Unicode True - Var Is_Admin - Var Install_Type - - ;Request application privileges for UAC. If admin is not available, only user-level install will be available - RequestExecutionLevel highest -;-------------------------------- -;Interface Settings - - !define MUI_ABORTWARNING - -;-------------------------------- -;Pages - !insertmacro MUI_PAGE_WELCOME - !insertmacro MUI_PAGE_LICENSE "..\LICENSE.txt" - ;!insertmacro MULTIUSER_PAGE_INSTALLMODE - Page Custom InstallTargetPage - ;!insertmacro MUI_PAGE_COMPONENTS - !define MUI_PAGE_CUSTOMFUNCTION_PRE Skip_Directory_Func - !insertmacro MUI_PAGE_DIRECTORY - !insertmacro MUI_PAGE_INSTFILES - !insertmacro MUI_PAGE_FINISH - - !insertmacro MUI_UNPAGE_WELCOME - !insertmacro MUI_UNPAGE_CONFIRM - !insertmacro MUI_UNPAGE_INSTFILES - !insertmacro MUI_UNPAGE_FINISH - -;-------------------------------- -;Languages - - !insertmacro MUI_LANGUAGE "English" - !insertmacro MUI_LANGUAGE "Spanish" - !insertmacro MUI_LANGUAGE "SpanishInternational" - - ;English---------------------------- - LangString Header_Title ${LANG_ENGLISH} "Configure Install" - LangString Header_Subtitle ${LANG_ENGLISH} "Customize install settings" - LangString Option_Scope ${LANG_ENGLISH} "Select for whom will $(^Name) be installed: " - LangString Scope_Machine ${LANG_ENGLISH} "All users" - LangString Scope_User ${LANG_ENGLISH} "Current user" - - ;Spanish/SpanishInternational---------------------------- - LangString Header_Title ${LANG_SPANISH} "Configurar instalación" - LangString Header_Subtitle ${LANG_SPANISH} "Elija los ajustes de la instalación" - LangString Option_Scope ${LANG_SPANISH} "$(^Name) será instalado para: " - LangString Scope_Machine ${LANG_SPANISH} "Todos los usuarios" - LangString Scope_User ${LANG_SPANISH} "Usuario actual" - - LangString Header_Title ${LANG_SPANISHINTERNATIONAL} "Configurar instalación" - LangString Header_Subtitle ${LANG_SPANISHINTERNATIONAL} "Elija los ajustes de la instalación" - LangString Option_Scope ${LANG_SPANISHINTERNATIONAL} "$(^Name) será instalado para: " - LangString Scope_Machine ${LANG_SPANISHINTERNATIONAL} "Todos los usuarios" - LangString Scope_User ${LANG_SPANISHINTERNATIONAL} "Usuario actual" - -;Functions------------------------------ - Function Skip_Directory_Func - ;StrCmp $Install_Type "user" dontSkip - Abort # skip the page - ;dontSkip: - FunctionEnd - - !macro ONINIT un - Function ${un}.onInit - ; The value of SetShellVarContext detetmines whether SHCTX is HKLM or HKCU - ; and whether SMPROGRAMS refers to all users or just the current - !insertmacro MUI_LANGDLL_DISPLAY - UserInfo::GetAccountType - Pop $0 - ${If} $0 == "Admin" - ; If we're an admin, default to installing to C:\Program Files - SetShellVarContext all - ; StrCpy $INSTDIR "$PROGRAMFILES64\$(^Name)" - StrCpy $Is_Admin "true" - ${Else} - ; If we're just a user, default to installing to ~\AppData\Local - SetShellVarContext current - ; StrCpy $INSTDIR "$LOCALAPPDATA\$(^Name)" - StrCpy $Is_Admin "false" - ${EndIf} - - ; ${If} $INSTDIR == "" - ; ; This only happens in the installer, because the uninstaller already knows INSTDIR - ; ReadRegStr $0 SHCTX "Software\${PRODUCT_NAME}" "" - - ; ${If} $0 != "" - ; ; If we're already installed, use the existing directory - ; StrCpy $INSTDIR "$0" - ; ${Else} - ; StrCpy $INSTDIR "$INSTDIR_BASE\${PRODUCT_NAME}" - ; ${Endif} - ; ${Endif} - FunctionEnd - !macroend - -!insertmacro ONINIT "" -!insertmacro ONINIT "un" - -;NSDialog InstallTarget Page definition--------------------------------- - -Function InstallTargetPage - !insertmacro MUI_HEADER_TEXT $(Header_Title) $(Header_Subtitle) - ;MessageBox MB_OK "Install type $Install_Type" - ;MessageBox MB_OK "Build type ${BUILDTYPE}" - nsDialogs::Create 1018 - Pop $0 - - FindWindow $0 "#32770" - GetDlgItem $1 $0 1 ;next/install button - SendMessage $1 ${WM_SETTEXT} 1 "STR:$(^InstallBtn)" - Pop $0 - - ${NSD_CreateLabel} 0 0 100% 10% $(Option_Scope) - Pop $3 - - ${NSD_CreateFirstRadioButton} 0 12% 40% 6% $(Scope_Machine) - Pop $1 - ${If} $Is_Admin == "false" - EnableWindow $1 0 - StrCpy $INSTDIR "$LOCALAPPDATA\$(^Name)" - ${Else} - SendMessage $1 ${BM_CLICK} "" "" ;Set default - StrCpy $INSTDIR "$PROGRAMFILES64\$(^Name)" - ${EndIf} - ${NSD_OnClick} $1 All_Users_Click - - ${NSD_CreateAdditionalRadioButton} 0 24% 40% 6% $(Scope_User) - Pop $2 - ${IfThen} $Is_Admin == "false" ${|} SendMessage $2 ${BM_CLICK} "" "" ${|} - ${NSD_OnClick} $2 Current_User_Click - - nsDialogs::Show -FunctionEnd - -Function All_Users_Click - Pop $0 - SetShellVarContext all - StrCpy $INSTDIR "$PROGRAMFILES64\$(^Name)" - StrCpy $Install_Type "machine" - ;${NSD_SetText} $0 "machine" - ;FindWindow $0 "#32770" - ;GetDlgItem $1 $0 1 ;next/install button - ;SendMessage $1 ${WM_SETTEXT} 1 "STR:$(^InstallBtn)" -FunctionEnd - -Function Current_User_Click - Pop $0 - SetShellVarContext current - StrCpy $INSTDIR "$LOCALAPPDATA\$(^Name)" - StrCpy $Install_Type "user" - ;${NSD_SetText} $0 "user" - ;FindWindow $0 "#32770" - ;GetDlgItem $1 $0 1 ;next/install button - ;SendMessage $1 ${WM_SETTEXT} 1 "STR:$(^NextBtn)" -FunctionEnd - -;Default section---------------------- -Section - SetRegView 64 - SetOutPath $INSTDIR - - !if ${BUILDTYPE} == "release" - File "..\build\bin\MixerQ.exe" - !else - File "..\build\bin\MixerQd.exe" - !endif - File "..\LICENSE.txt" - - ;Start menu shortcut - createDirectory "$SMPROGRAMS\$(^Name)" - createShortCut "$SMPROGRAMS\$(^Name)\$(^Name).lnk" "$INSTDIR\$(^Name).exe" - createShortCut "$SMPROGRAMS\$(^Name)\Uninstall$(^Name).lnk" "$INSTDIR\Uninstall$(^Name).exe" - - ;Store installation folder - WriteRegStr SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" "DisplayName" "$(^Name)" - WriteRegStr SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" "UninstallString" '"$INSTDIR\Uninstall$(^Name).exe"' - WriteRegDWORD SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" "NoModify" 1 - WriteRegDWORD SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" "NoRepair" 1 - WriteRegStr SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "$(^Name)" "$INSTDIR\$(^Name)" - - ;Create uninstaller - WriteUninstaller "$INSTDIR\Uninstall$(^Name).exe" - -SectionEnd - - -;-------------------------------- -;Descriptions - - ; ;Language strings - ; LangString DESC_SecDummy ${LANG_ENGLISH} "A test section." - - ; ;Assign language strings to sections - ; !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN - ; !insertmacro MUI_DESCRIPTION_TEXT ${SecDummy} $(DESC_SecDummy) - ; !insertmacro MUI_FUNCTION_DESCRIPTION_END - -;-------------------------------- -;Uninstaller Section - -Section "Uninstall" - SetRegView 64 - - SetShellVarContext current - DeleteRegValue HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "$(^Name)" - DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" - Delete "$SMPROGRAMS\$(^Name)\$(^Name).lnk" - Delete "$SMPROGRAMS\$(^Name)\Uninstall$(^Name).lnk" - RMDir "$SMPROGRAMS\$(^Name)" - - ${If} $Is_Admin == "true" - SetShellVarContext all - DeleteRegValue HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "$(^Name)" - DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" - Delete "$SMPROGRAMS\$(^Name)\$(^Name).lnk" - Delete "$SMPROGRAMS\$(^Name)\Uninstall$(^Name).lnk" - RMDir "$SMPROGRAMS\$(^Name)" - ${EndIf} - - Delete "$INSTDIR\$(^Name).exe" - Delete "$INSTDIR\LICENSE.txt" - Delete "$INSTDIR\Uninstall$(^Name).exe" - ;!define PRODUCT_UNINST_ROOT_KEY "HKLM" - RMDir "$INSTDIR" - -SectionEnd diff --git a/install/version.nsi b/install/version.nsi deleted file mode 100644 index 5e85c8c..0000000 --- a/install/version.nsi +++ /dev/null @@ -1,26 +0,0 @@ -!if ${BUILDTYPE} == "release" - !define File "..\build\bin\MixerQ.exe" -!else - !define File "..\build\bin\MixerQd.exe" -!endif - -OutFile "GetVersion.exe" -SilentInstall silent -RequestExecutionLevel user ; don't write $EXEDIR\Version.txt with admin permissions and prevent invoking UAC - -Section - - ## Get file version - GetDllVersion "${File}" $R0 $R1 - IntOp $R2 $R0 / 0x00010000 - IntOp $R3 $R0 & 0x0000FFFF - IntOp $R4 $R1 / 0x00010000 - IntOp $R5 $R1 & 0x0000FFFF - StrCpy $R1 "$R2.$R3.$R4.$R5" - - ## Write it to a !define for use in main script - FileOpen $R0 "$EXEDIR\Version.txt" w - FileWrite $R0 '!define version "$R1"' - FileClose $R0 - -SectionEnd \ No newline at end of file diff --git a/qtest.pro b/qtest.pro index 42a1165..511e78a 100644 --- a/qtest.pro +++ b/qtest.pro @@ -1,28 +1,12 @@ -TEMPLATE = app -QMAKE_CXXFLAGS += --target=x86_64-w64-mingw32 -Werror=return-type -QMAKE_LFLAGS += --target=x86_64-w64-mingw32 -v -CONFIG(release, debug|release) { - TARGET = MixerQ - DESTDIR = bin - VERSION = 0.9.0.0 - #QMAKE_CXXFLAGS += -O2 < Default. Modifying requires removing. -} else { - TARGET = MixerQd - DESTDIR = bin - VERSION = 0.9.0.1 - QMAKE_CXXFLAGS += -g -gcodeview -O0 - QMAKE_LFLAGS += -g -Wl,-pdb= -} - -LIBS += -lWinmm -lodbc32 -lodbccp32 -luuid -loleaut32 -lole32 -lshell32 -ladvapi32 -lcomdlg32 -lwinspool -lgdi32 -luser32 -lkernel32 -lpropsys -static -stdlib=libc++ -lunwind -DEFINES += QT_LOGGING_TO_CONSOLE=1 WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602 -DEFINES_DEBUG += DEBUG - -QT += widgets network svg -INCLUDEPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimpl" "$$PWD\src\cont" -VPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimpl" "$$PWD\src\cont" - -SOURCES += qtestmain.cpp qtclasses.cpp backlasses.cpp backsessionclasses.cpp contclasses.cpp contsessionclasses.cpp settings.cpp -HEADERS += qtclasses.h backlasses.h backsessionclasses.h contclasses.h contsessionclasses.h global.h debug.h backfuncs.h ipolicyconfig.h msinclude.h meterslider.h qtvisuals.h settings.h -RESOURCES = assets.qrc -RC_ICONS += assets/logo.ico +QMAKE_CXXFLAGS += --target=x86_64-w64-mingw32 -g -gcodeview +#QMAKE_LINK += clang++ +QMAKE_LFLAGS += --target=x86_64-w64-mingw32 -g -gcodeview -Wl,-pdb= -v +DEFINES += DEBUG +CONFIG += debug console +QT += widgets +INCLUDEPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont" +DESTPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont" +VPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\cont" +SOURCES += qtestmain.cpp qtclasses.cpp backlasses.cpp contclasses.cpp +HEADERS += qtclasses.h backlasses.h contclasses.h global.h debug.h backfuncs.h +#DESTDIR += "build" diff --git a/src/back/backfuncs.h b/src/back/backfuncs.h index b8e1c6c..06adc7e 100644 --- a/src/back/backfuncs.h +++ b/src/back/backfuncs.h @@ -1,10 +1,11 @@ -GUID inline NGuidToGUID(NGuid guid) { +GUID NGuidToGUID(NGuid* guid) { GUID msGuid = GUID(); - msGuid.Data1 = guid.data1; - msGuid.Data2 = guid.data2; - msGuid.Data3 = guid.data3; + msGuid.Data1 = guid->data1; + msGuid.Data2 = guid->data2; + msGuid.Data3 = guid->data3; + msGuid.Data1 = guid->data1; for (int i = 0; i < 8; i++){ - msGuid.Data4[i] = guid.data4[i]; + msGuid.Data4[i] = guid->data4[i]; //log_debugcpp("MSGUID DATA4 BYTE " << i << ": "); //log_debugcpp(print_as_binary(8, uint32_t, msGuid.Data4[i])); } @@ -15,7 +16,7 @@ GUID inline NGuidToGUID(NGuid guid) { return msGuid; } -NGuid inline GUIDToNGuid(LPGUID msGuid){ +NGuid GUIDToNGuid(LPGUID msGuid){ NGuid guid = NGuid(); guid.data1 = msGuid->Data1; guid.data2 = msGuid->Data2; diff --git a/src/back/backlasses.cpp b/src/back/backlasses.cpp index 74af6a0..5269c29 100644 --- a/src/back/backlasses.cpp +++ b/src/back/backlasses.cpp @@ -1,76 +1,15 @@ -#include "backlasses.h" -#include "backfuncs.h" +#include +#include -using namespace Environment; - -EndpointNewSessionCallback::EndpointNewSessionCallback(EndpointHandler* eph){ - this->eph = eph; -} - -ULONG EndpointNewSessionCallback::AddRef(){ - return InterlockedIncrement(&ref); -} - -ULONG EndpointNewSessionCallback::Release(){ - ULONG tempRef = InterlockedDecrement(&ref); - if (tempRef == 0) { - delete this; - } - return tempRef; -} - -HRESULT EndpointNewSessionCallback::QueryInterface(REFIID riid, VOID **ppvInterface) { - if (IID_IUnknown == riid) - { - AddRef(); - *ppvInterface = (IUnknown*)this; - } - else if (__uuidof(IAudioSessionNotification) == riid) - { - AddRef(); - *ppvInterface = (IMMNotificationClient*)this; - } - else - { - *ppvInterface = NULL; - return E_NOINTERFACE; - } - return S_OK; -} - -HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSession) { - if (eph->getFlow() == Flows::FLOW_CAPTURE) return S_OK; - - IAudioSessionControl2* sessionControl; - //ISimmpleAudioVolume* sessionVolume; - if (FAILED(NewSession->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl))) { log_wdebugcpp(L"no nueva sesion......"); }; - if (sessionControl) { - Session* newSession = new Session(this->eph->getEndpoint(), sessionControl); - - SessionThreadParams tp = { .eph = this->eph, .session = newSession, .isDelete = false }; - wait = true; - std::thread newSessionThread(&EndpointNewSessionCallback::createSessionThread, this, tp); - newSessionThread.detach(); - while(wait); - } - - return S_OK; -} - -void EndpointNewSessionCallback::createSessionThread(SessionThreadParams params) { - params.eph->addSessionSendFront(params.session); - this->wait = false; -} - -EndpointVolumeCallback::EndpointVolumeCallback(Endpoint* ep){ +EndpointCallback::EndpointCallback(Endpoint* ep){ this->ep = ep; } -ULONG EndpointVolumeCallback::AddRef(){ +ULONG EndpointCallback::AddRef(){ return InterlockedIncrement(&ref); } -ULONG EndpointVolumeCallback::Release(){ +ULONG EndpointCallback::Release(){ ULONG tempRef = InterlockedDecrement(&ref); if (tempRef == 0) { delete this; @@ -78,7 +17,7 @@ ULONG EndpointVolumeCallback::Release(){ return tempRef; } -HRESULT EndpointVolumeCallback::QueryInterface(REFIID riid, VOID **ppvInterface) { +HRESULT EndpointCallback::QueryInterface(REFIID riid, VOID **ppvInterface) { if (IID_IUnknown == riid) { AddRef(); @@ -97,305 +36,55 @@ HRESULT EndpointVolumeCallback::QueryInterface(REFIID riid, VOID **ppvInterface) return S_OK; } -HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) { +HRESULT EndpointCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) { if (pNotify == NULL) return E_INVALIDARG; - AUDIO_VOLUME_NOTIFICATION_DATA paramCopy; - memcpy(¶mCopy, 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]; + float extraChannelVol[pNotify->nChannels]; + bool multiChannel = false; + AUDIO_VOLUME_NOTIFICATION_DATA eventData = *pNotify; + if(pNotify->nChannels > 1) { + multiChannel = true; + for (UINT i = 0; i < pNotify->nChannels; i++){ + extraChannelVol[i] = pNotify->afChannelVolumes[i]; + } } - wait = true; - std::thread updateVolumeThread(&EndpointVolumeCallback::updateVolumeInfo, this, paramCopy, channelVolumes); - updateVolumeThread.detach(); - while(wait); + NGuid* guid = osh->getGuid(); + + if (memcmp(guid, &eventData, sizeof(*guid)) == 0) { + log_debugcpp("Onnanokotify says You Shall Not Update Thy Interface."); + } else { + log_debugcpp("Onnanokotify says Stored: " << guid->data1); + log_debugcpp("Onnanokotify says Grace of God: " << eventData.guidEventContext.Data1); + osh->updateMuteCallback(this->ep->getIndex(), eventData.bMuted); + osh->updateVolumeCallback(this->ep->getIndex(), AudioChannel::CHANNEL_MAIN ,eventData.fMasterVolume); + log_debugcpp("Onnanokotify says Reported Channel Qty: " << eventData.nChannels); + + if(multiChannel) + for(UINT i = 0; i < eventData.nChannels; i++) { + osh->updateVolumeCallback(this->ep->getIndex(), (uint32_t)i, extraChannelVol[i]); + } + else + osh->updateVolumeCallback(this->ep->getIndex(), (uint32_t)0, pNotify->afChannelVolumes[0]); + } + return S_OK; } -void EndpointVolumeCallback::updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes) { - //delete osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller; - //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. - osh->handlersPlaybackMutex.lock(); - osh->handlersCaptureMutex.lock(); - osh->lockEndpoints(); - osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data1 \ - = newVolume.guidEventContext.Data1; - osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \ - = newVolume.guidEventContext.Data2; - osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data3 \ - = newVolume.guidEventContext.Data3; - for(int i = 0; i < 8 /* Data4 size */; i++){ - osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data4[i] = newVolume.guidEventContext.Data4[i]; - } - - //memcpy(&osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller, &newVolume.guidEventContext,sizeof(NGuid) ); - Flows flow = this->ep->getFlow(); - EndpointHandler* eph = nullptr; - if (flow & Flows::FLOW_PLAYBACK) { - eph = osh->getPlaybackEndpointHandlers().at(this->ep->getIndex()); - } else { - eph = osh->getCaptureEndpointHandlers().at(this->ep->getIndex()); - } +/* EndpointCallback::~EndpointCallback(){ + * PAUDIO_VOLUME_NOTIFICATION_DATA->Release(); + * } */ - eph->getCallbackInfo()->muted = newVolume.bMuted; - eph->getCallbackInfo()->mainVolume = newVolume.fMasterVolume; - eph->getCallbackInfo()->channels = newVolume.nChannels; - - - UINT j = 0; - //todo: do while here caused stack corruption; sus - while(j < newVolume.nChannels) { - if (flow & Flows::FLOW_PLAYBACK) - eph->getCallbackInfo()->channelVolumes[j] = channelVolumes[j]; - else - eph->getCallbackInfo()->channelVolumes[j] = channelVolumes[j]; - j++; - } - free(channelVolumes); - osh->unlockEndpoints(); - osh->handlersPlaybackMutex.unlock(); - osh->handlersCaptureMutex.unlock(); - wait = false; -} - -void EndpointVolumeCallback::reportFinished() { - this->wait = false; -} - -EndpointSituationCallback::EndpointSituationCallback(Overseer* os){ - this->os = os; -} - - -ULONG EndpointSituationCallback::AddRef(){ - return InterlockedIncrement(&ref); -} - -ULONG EndpointSituationCallback::Release(){ - ULONG tempRef = InterlockedDecrement(&ref); - if (tempRef == 0) { - delete this; - } - return tempRef; -} - -HRESULT EndpointSituationCallback::QueryInterface(REFIID riid, VOID **ppvInterface) { - if (IID_IUnknown == riid) - { - AddRef(); - *ppvInterface = (IUnknown*)this; - } - else if (__uuidof(IMMNotificationClient) == riid) - { - AddRef(); - *ppvInterface = (IMMNotificationClient*)this; - } - else - { - *ppvInterface = NULL; - return E_NOINTERFACE; - } - return S_OK; -} - -HRESULT EndpointSituationCallback::OnDefaultDeviceChanged(EDataFlow flow, ERole role,LPCWSTR pwstrDeviceId) { - if (flow == EDataFlow::eCapture) return E_INVALIDARG; - if (!pwstrDeviceId) return E_INVALIDARG; - - Roles nRole; - switch (role) { - case ERole::eConsole: - nRole = Roles::ROLE_CONSOLE; - break; - case ERole::eMultimedia: - nRole = Roles::ROLE_MULTIMEDIA; - break; - case ERole::eCommunications: - nRole = Roles::ROLE_COMMUNICATIONS; - break; - } - std::wstring wstringEndpointId = pwstrDeviceId; - log_wdebugcpp(L"we got za defol 4 " + wstringEndpointId); - osh->roleBucketEntryCallback(nRole, wstringEndpointId); - return S_OK; -} - -HRESULT EndpointSituationCallback::OnDeviceAdded(LPCWSTR pwstrDeviceId) { - log_wdebugcpp(L"ayo we eventing za adin " + std::wstring(pwstrDeviceId)); - return S_OK; -}; - -HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) { - log_wdebugcpp(L"ayo we eventing za rmovin " + std::wstring(pwstrDeviceId)); - return S_OK; -} - -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: - newState = EndpointState::ENDPOINT_ACTIVE; - break; - case DEVICE_STATE_DISABLED: - newState = EndpointState::ENDPOINT_DISABLED; - break; - case DEVICE_STATE_NOTPRESENT: - newState = EndpointState::ENDPOINT_NOTPRESENT; - break; - case DEVICE_STATE_UNPLUGGED: - newState = EndpointState::ENDPOINT_UNPLUGGED; - break; - } - isEpStateChanging.exchange(true); - std::thread newEndpointThread(&OverseerHandler::reviseEndpointShowing, osh, - endpointId, newState); - newEndpointThread.detach(); - while(isEpStateChanging); - return S_OK; -} - -HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { - isEpStateChanging.exchange(true); - std::thread propertyThread(&Overseer::updateEndpointInfo, os, std::wstring(pwstrDeviceId)); - propertyThread.detach(); - while(isEpStateChanging); - return S_OK; -} - -void EndpointSituationCallback::reportFinishedStateChange() { - this->isEpStateChanging.exchange(false); - return; -} - -Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx) { +Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ this->endpoint = ep; this->idx = idx; - this->policyConfig = policyConfig; - /* - * It can't multiflag, it's that stupid. MS momento. - * Only shows most relevant flag according to MS, i.e. 0110 sends 0010 - */ - DWORD state; - if(FAILED(endpoint->GetState(&state))) {exit(-2);}; - this->endpointState = (EndpointState)state; - - if(this->endpointState == EndpointState::ENDPOINT_ACTIVE) { - activateEndpointVolume(); - - //if(FAILED(endpoint->Activate(__uuidof(IAudioClient), - // CLSCTX_ALL, NULL, (void**)&audioClient))) { log_debugcpp("audioclntbros..."); } - //audioClient->GetDevicePeriod(&defTime, &minTime); - - } - - //todo: atexit into exit Gather ID - LPWSTR tempString = nullptr; - if (FAILED(endpoint->GetId(&tempString))) { exit(-1); }; - endpointId = std::wstring(tempString); - log_wdebugcpp(endpointId); - CoTaskMemFree(tempString); - - endpoint->OpenPropertyStore(STGM_READ, &properties); - this->updateName(); - this->setFlow(); - - reloadEndpointChannels(); -} - -void Endpoint::updateName() { + if(FAILED(endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&endpointVolume))) { log_debugcpp("si"); }; + if (FAILED(endpointVolume->GetChannelCount(&channelCount))) log_debugcpp("get channel count fail"); + //Obtaining friendly name: IPropertyStore creates PROPVARIANT per field + // hr = endpointPtr->GetId(&endpointID); + endpoint->OpenPropertyStore(STGM_READ, &properties); PROPVARIANT pv; - #define store_name(key, propvariant, wstr) do { \ - properties->GetValue(key, &propvariant); \ - if (pv.pwszVal == nullptr) wstr = L"Unnamed Not Present Endpoint"; \ - else wstr = std::wstring(pv.pwszVal); \ - } while (0) - - store_name(PKEY_Device_FriendlyName, pv, friendlyName); - store_name(PKEY_Device_DeviceDesc, pv, descriptionName); - store_name(PKEY_DeviceInterface_FriendlyName, pv, deviceName); - #undef store_name - log_wdebugcpp(L"Endpoint name: " + friendlyName); -} - -void Endpoint::activateEndpointSessions() { - if (this->flow != Flows::FLOW_PLAYBACK) { - log_debugcpp("recording. No seshes for u :("); - 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..."); exit(-5); return; } - - endpointSessions.resize(1, nullptr); - int sessionCount; - sessionEnumerator->GetCount(&sessionCount); - for (int i = 0; i < sessionCount; i++) { - IAudioSessionControl* sessionControlTmp; - if (FAILED(sessionEnumerator->GetSession(i, (IAudioSessionControl**)&sessionControlTmp))) { - exit(-6); - } - IAudioSessionControl2* sessionControl; - 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; - else endpointSessions.push_back(session); - } - sessionEnumerator->Release(); -} - -/* - * void Endpoint::deleteSessionManager() { - * sessionManager->Release(); - * sessionManager = nullptr; - * } - */ - -void Endpoint::addSession(Session* session) { - session->setIndex(this->getSessionCount()); - endpointSessions.push_back(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_MULTITHREADED | COINIT_DISABLE_OLE1DDE); - if (this->endpointVolume == nullptr) { - 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), - CLSCTX_ALL, NULL, (void**)&endpointPeakMeter))) { - log_debugcpp("peakbros..."); - } - } - if (result == S_OK) - CoUninitialize(); -} - -void Endpoint::reloadEndpointChannels() { - if (this->endpointState == DEVICE_STATE_ACTIVE) { - if (FAILED(endpointVolume->GetChannelCount(&channelCount))) {log_debugcpp("get channel count fail");};/* */ - } + properties->GetValue(PKEY_Device_FriendlyName , &pv); + friendlyName = std::wstring(pv.pwszVal); } void Endpoint::setIndex(uint64_t idx){ @@ -406,27 +95,17 @@ uint64_t Endpoint::getIndex(){ return idx; } + std::wstring Endpoint::getName(){ return friendlyName; } -std::wstring Endpoint::getId(){ - return endpointId; -} - -float Endpoint::getPeakVolume() { - float peakVol; - if(endpointPeakMeter) endpointPeakMeter->GetPeakValue(&peakVol); - else return 0; - return peakVol; -} - float Endpoint::getVolume(int channel){ float volume; - if (channel == AudioChannel::CHANNEL_MAIN) { - if(FAILED(endpointVolume->GetMasterVolumeLevelScalar(&volume))) { /* log_debugcpp("si") */;} + if (channel == ENDPOINT_MASTER_VOLUME) { + if(FAILED(endpointVolume->GetMasterVolumeLevelScalar(&volume))) { log_debugcpp("si");} } else { - if(FAILED(endpointVolume->GetChannelVolumeLevelScalar(channel, &volume))) { /* log_debugcpp("si"); */} + if(FAILED(endpointVolume->GetChannelVolumeLevelScalar(channel, &volume))) { log_debugcpp("si");} } return volume; } @@ -435,151 +114,69 @@ uint32_t Endpoint::getChannelCount(){ return (uint32_t)channelCount; } + bool Endpoint::getMute(){ BOOL mut; - if(FAILED(endpointVolume->GetMute(&mut))) { /* TIP: Below */ } + if(FAILED(endpointVolume->GetMute(&mut))) { log_debugcpp("si"); } + log_debugcpp("back BOOL is " << mut); bool mute = (bool)mut; + log_debugcpp("translate to bool " << mute); return mute; } -void Endpoint::setState(EndpointState state){ - this->endpointState = state; - if(state == EndpointState::ENDPOINT_ACTIVE) { - this->activateEndpointVolume(); - this->reloadEndpointChannels(); - } -} +/* + * float Endpoint::getLeftChannelVolume(){ + * float volume; + * if(FAILED(endpointVolume-> GetChannelVolumeLevelScalar(0, &volume)) { log_debugcpp("si"); } ); + * return volume; + * } + * + * float Endpoint::getRightChannelVolume(){ + * float volume; + * if(FAILED(endpointVolume-> GetChannelVolumeLevelScalar(1, &volume)) { log_debugcpp("si");} + * return volume; + * } + */ -EndpointState Endpoint::getState(){ - return this->endpointState; -} -void Endpoint::setVolume(NGuid guid, int channel, float volume) { - //TIP: There used to be log messages here. Now, it's a ghost town. +void Endpoint::setVolume(NGuid* guid, int channel, float volume) { GUID tempMsGuid = NGuidToGUID(guid); if (channel == AudioChannel::CHANNEL_MAIN) { - if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) { - log_wdebugcpp(L"Master volume failed for endpoint: " + friendlyName); - }; + if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) { log_debugcpp("MASTER VOLUME FAILED"); }; } else { - if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) { - log_wdebugcpp(L"Channel " + std::to_wstring(channel) + L" volume failed for endpoint: " + friendlyName); - }; + log_debugcpp("Windows: Channel being updated: " << channel); + if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) { log_debugcpp("CHANNEL "<< channel <<" VOLUME FAILED"); }; } } -void Endpoint::setMute(NGuid guid, bool muted) { +void Endpoint::setMute(NGuid* guid, bool muted) { + //BOOL mut; + //log_debugcpp("bool mute arrives as " << mut); + //if(FAILED(endpointVolume->GetMute(&mut))) { log_debugcpp("si"); } + //log_debugcpp("translate to BOOL as " << mut); + //TODO: use new funcs GUID tempMsGuid = NGuidToGUID(guid); - if(FAILED(endpointVolume->SetMute(muted, &tempMsGuid))) { log_wdebugcpp(std::wstring(L"EndpointVolume null?")); }; + if(FAILED(endpointVolume->SetMute(muted, &tempMsGuid))) { log_debugcpp("MUTE FAILED"); }; } -void Endpoint::setVolumeCallback(EndpointVolumeCallback *epc){ - if(endpointVolume == nullptr) { - this->activateEndpointVolume(); - } +void Endpoint::setCallback(EndpointCallback *epc){ endpointVolume->RegisterControlChangeNotify((IAudioEndpointVolumeCallback*)epc); } -void Endpoint::removeVolumeCallback(EndpointVolumeCallback *epc){ +void Endpoint::removeCallback(EndpointCallback *epc){ endpointVolume->UnregisterControlChangeNotify((IAudioEndpointVolumeCallback*)epc); } -Roles Endpoint::getRoles(){ - return this->endpointRoles; -} - -void Endpoint::setRoles(Roles role){ - if (!policyConfig) return; - - bool allRoles = false; - ERole val; - switch(role) { - case Roles::ROLE_CONSOLE: - val = eConsole; - break; - case Roles::ROLE_MULTIMEDIA: - val = eMultimedia; - break; - case Roles::ROLE_COMMUNICATIONS: - val = eCommunications; - break; - default: - allRoles = true; - break; - } - if (allRoles) { - policyConfig->SetDefaultEndpoint(endpointId.c_str(), eMultimedia); - //policyConfig->SetDefaultEndpoint(endpointId.c_str(), eConsole); - policyConfig->SetDefaultEndpoint(endpointId.c_str(), eCommunications); - } else policyConfig->SetDefaultEndpoint(endpointId.c_str(), val); -} - -void Endpoint::assignRoles(Roles role){ - Roles roles = (Roles)(endpointRoles | role); - this->endpointRoles = roles; -} - -void Endpoint::removeRoles(Roles role){ - Roles roles = (Roles)(endpointRoles ^ role); - this->endpointRoles = roles; -} - -void Endpoint::setFlow() { - IMMEndpoint* flowGetter; - if(FAILED(this->endpoint->QueryInterface(__uuidof(IMMEndpoint), (void**)&flowGetter))) - { log_debugcpp("no flow..."); } - EDataFlow MSflow; - flowGetter->GetDataFlow(&MSflow); - this->flow = (MSflow == EDataFlow::eRender ? Flows::FLOW_PLAYBACK : Flows::FLOW_CAPTURE); - log_debugcpp("Endpoint flow: " + std::to_string(flow)); - flowGetter->Release(); -} - -Flows Endpoint::getFlow() { - return this->flow; -} - -/* sessions */ -std::vector Endpoint::getSessions() { - return endpointSessions; -} - -size_t Endpoint::getSessionCount() { - size_t sessionCount; - sessionCount = endpointSessions.size(); - return sessionCount; -} - -void Endpoint::registerNewSessionNotification(EndpointNewSessionCallback* ensc){ - sessionManager->RegisterSessionNotification(ensc); -} - -void Endpoint::unregisterNewSessionNotification(EndpointNewSessionCallback* ensc){ - sessionManager->UnregisterSessionNotification(ensc); -} - -void Endpoint::deleteSessions() { - for (auto session : endpointSessions) { - delete session; - } - endpointSessions.resize(0); -} - Endpoint::~Endpoint(){ - //EPs are never deleted. - log_wdebugcpp(L"murio endpoint-san uwu"); + log_debugcpp("cum"); properties->Release(); endpointVolume->Release(); endpoint->Release(); - sessionManager->Release(); - for (auto session : endpointSessions) { - delete session; - } } void Overseer::initCOMLibrary() { if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { - log_debugcpp("Not even COM?"); }; + log_debugcpp("si"); }; //Retrieving endpoint enumerator @@ -587,463 +184,74 @@ void Overseer::initCOMLibrary() { if(FAILED(CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&deviceEnumerator)) ) - { log_debugcpp("No MMDeviceEnum. Weird."); }; + { log_debugcpp("si"); }; GUID tempGuid; if(FAILED(CoCreateGuid(&tempGuid))) { log_debugcpp("Failed to obtain GUID: " ); }; - //todo: wtf? why is it working? floats are ptrs... this->guid = GUIDToNGuid(&tempGuid); - - HRESULT hre = CoCreateInstance(__uuidof(CPolicyConfigClient), - NULL, CLSCTX_ALL, - __uuidof(IPolicyConfig7), (LPVOID *)&policyConfig); - if (hre != S_OK) exit(-1); - //TODO: Release lpguid? //TODO: Uninitialize COM } -void Overseer::createEndpoints(Flows flow) { +void Overseer::reloadEndpoints() { IMMDeviceCollection *deviceCollection; - unsigned int numEndpoints; - EDataFlow MSflow = (flow == Flows::FLOW_PLAYBACK ? EDataFlow::eRender : EDataFlow::eCapture); // | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED - // NOTPRESENT shows a lot of garbage, unnamed devices. - if(FAILED(deviceEnumerator->EnumAudioEndpoints(MSflow, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED, &deviceCollection) )) + if(FAILED(deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &deviceCollection) )) { log_debugcpp("si"); }; - /* - * Counting them - */ - if(FAILED(deviceCollection->GetCount(&numEndpoints))) { log_debugcpp("si");}; - if(numEndpoints == 0) { log_debugcpp("si"); }; + + //Counting them + if(FAILED(deviceCollection->GetCount(&numPlaybackEndpoints))) { log_debugcpp("si");}; + if(numPlaybackEndpoints == 0) { log_debugcpp("si"); }; + - /* - * Retrieving actual endpoints and storing them on their own collection - */ - IMMDevice *temp; - for (unsigned int i = 0; i < numEndpoints; i++){ + //Retrieving actual endpoints and storing them on their own class + for (unsigned int i = 0; i < numPlaybackEndpoints; i++){ + IMMDevice *temp; if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); }; - Endpoint *endpoint = new Endpoint(temp, policyConfig, i); - if (flow == Flows::FLOW_PLAYBACK) - this->playbackDevices.push_back(endpoint); - else - this->captureDevices.push_back(endpoint); - //TODO: le porblemx std::cout + "ola" + std::endl; + Endpoint *endpoint = new Endpoint(temp, i); + //endpoint->setIndex(i); + this->playbackDevices.push_back(endpoint); + //TODO: le porblemx std::cout << "ola" << std::endl; } deviceCollection->Release(); - - /* - * Discerning default endpoints per role - * order: console, multimedia, communications - */ - for(int i = 0; i < ERole_enum_count; i++){ - ERole val; - switch(i) { - case 0: - val = eConsole; - break; - case 1: - val = eMultimedia; - break; - case 2: - val = eCommunications; - break; - } - deviceEnumerator->GetDefaultAudioEndpoint(MSflow, val, &temp); - if (!temp) continue; - - LPWSTR id = nullptr; - - if (flow == Flows::FLOW_PLAYBACK) { - for (unsigned int j = 0; j < numEndpoints; j++) { - std::wstring eptId = playbackDevices.at(j)->getId(); - temp->GetId(&id); - int comparison = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, eptId.c_str(), -987, id, -987, NULL, NULL, 0); - if (comparison - 2 == 0) { - log_wdebugcpp(L"ola defaul playback de " + std::to_wstring(i) + L" es " + id); - playbackDevices.at(j)->assignRoles((Roles)(1 << i)); - } - } - } else { - for (unsigned int j = 0; j < numEndpoints; j++){ - std::wstring eptId = captureDevices.at(j)->getId(); - temp->GetId(&id); - int comparison = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, eptId.c_str(), -987, id, -987, NULL, NULL, 0); - if (comparison - 2 == 0) { - log_wdebugcpp(L"ola defaul capture de " - + std::to_wstring(i) + L" es " + id); - captureDevices.at(j)->assignRoles((Roles)(1 << i)); - } - } - - } - } } -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; - if(FAILED(deviceEnumerator->GetDevice((LPCWSTR)endpointId.c_str(), &newep))) - log_debugcpp("ay caramba con la hot metida. Sad!"); - - Endpoint *endpoint = new Endpoint(newep, policyConfig); - - Flows getFlow = endpoint->getFlow(); - if (getFlow == Flows::FLOW_PLAYBACK) { - endpoint->setIndex(osh->getPlaybackEndpointsCount()); - this->playbackDevices.push_back(endpoint); - } else { - endpoint->setIndex(osh->getCaptureEndpointsCount()); - this->captureDevices.push_back(endpoint); - } - if (flow != nullptr) *flow = getFlow; - CoUninitialize(); - return endpoint; -} - -void Overseer::reportFinishedStateChange() { - epsc.reportFinishedStateChange(); -} - -Overseer::Overseer() : epsc(this) { - log_debugcpp("Initializing Overseer"); - - //Storing exe path for later use (mainly "Run on startup") - log_debugcpp("-Caching exe path"); - uint32_t cPathLen = 0; - wchar_t* cPath = getExeAbsPath(&cPathLen); - exeAbsPath = cPath; - - //Detecting install scope - wchar_t *machine = wcsstr(cPath, L"Program Files"); - if (!machine) - Environment::scope = HKEY_CURRENT_USER; - else Environment::scope = HKEY_LOCAL_MACHINE; - free(cPath); - +Overseer::Overseer(){ //Initializing COM library - log_debugcpp("-Initializing COM"); + log_debugcpp("Initializing Overseer"); initCOMLibrary(); - //Obtaining playback endpoint collection - createEndpoints(Flows::FLOW_PLAYBACK); - //reloadEndpoints(Flows::FLOW_CAPTURE); + //Obtaining playback endpoint collection on this point in time + reloadEndpoints(); } -NGuid Overseer::getGuid() { - return guid; -} +//Overseer::int getDefaultPlaybackEndpoint(Endpoint** defaultEndpoint){ +//if (FAILED(deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &endpointPtr))) +// return 1; +//return 0; +//} -void Overseer::registerEndpointSituationCallback() { - if(FAILED(deviceEnumerator->RegisterEndpointNotificationCallback(((IMMNotificationClient*)&epsc)))) { log_debugcpp("when no enchufas......"); } -} +//int Overseer::getDefaultCaptureEndpoint(Endpoint** defaultEndpoint); +//TODO guid +NGuid* Overseer::getGuid() { + return &guid; +} + std::vector Overseer::getPlaybackEndpoints() { return playbackDevices; } -std::vector Overseer::getCaptureEndpoints() { - return captureDevices; -} - -void Overseer::updateEndpointInfo(std::wstring endpointId) { - //todo: reintroduce capture devices - playbackMutex.lock(); - log_wdebugcpp(L"new name Endpoint id: " + endpointId); - for(auto ep : playbackDevices) { - if (ep->getId() == endpointId && ep->getState() == EndpointState::ENDPOINT_ACTIVE) { - ep->updateName(); - osh->updateFrontEndpointName(ep); - break; - } - } - playbackMutex.unlock(); - epsc.reportFinishedStateChange(); -} - Overseer::~Overseer(){ - //Overseer is never deleted. This is to annotate what would need to be taken care of. - log_debugcpp("jej"); + log_debugcpp("cum"); deviceEnumerator->Release(); for(unsigned long long i = 0; i < playbackDevices.size(); i++){ delete(playbackDevices.at(i)); } } -wchar_t* Environment::getExeAbsPath(uint32_t *exeAbsPathLength) { - wchar_t *exeAbsPath = (wchar_t*)calloc(UNICODE_STRING_MAX_CHARS, sizeof(wchar_t)); - *exeAbsPathLength = GetModuleFileNameW( - NULL, - exeAbsPath, - UNICODE_STRING_MAX_CHARS - ); - return exeAbsPath; -} - -std::string Environment::createSettingsPath(SettingsTargetDirectory target) { - wchar_t* settingsPath = nullptr; - wchar_t settingsFile[] = L"\\settings.ini"; - uint32_t settingsFileLen = (sizeof(settingsFile) / sizeof(wchar_t)) - 1; - wchar_t maxPathBypass[] = L"\\\\?\\"; - uint32_t exePathLength = 0; - wchar_t folderPath[] = L"\\" LAPP_NAME; - uint32_t maxPathBypassLen = (sizeof(maxPathBypass)/ sizeof(wchar_t)) - 1; - uint32_t folderPathLen = (sizeof(folderPath) / sizeof(wchar_t)) - 1; - wchar_t* roamingPath = nullptr; - - log_wdebugcpp(L"Bypass size: " + std::to_wstring((sizeof(maxPathBypass)/sizeof(maxPathBypass[0])))); - - switch(target) { - case HOME_DIR: - { - if(SHGetKnownFolderPath( - FOLDERID_RoamingAppData, - 0, - NULL, - &roamingPath) - == S_OK) { - //Retrieve path len - uint32_t pathLen = 0; - wchar_t currentChar = roamingPath[pathLen]; - while(currentChar != '\0') { - pathLen++; - currentChar = roamingPath[pathLen]; - } - - settingsPath = (wchar_t*)calloc(pathLen + - maxPathBypassLen + - folderPathLen + - settingsFileLen, - sizeof(wchar_t)); - memcpy(settingsPath, maxPathBypass, sizeof(wchar_t) * maxPathBypassLen); - memcpy(settingsPath + (maxPathBypassLen), roamingPath, sizeof(wchar_t) * pathLen); - CoTaskMemFree(roamingPath); - memcpy(settingsPath + (maxPathBypassLen + pathLen), - folderPath, sizeof(wchar_t) * folderPathLen); - log_wdebugcpp(L"Settings folder path: " + std::wstring(settingsPath)); - - if(CreateDirectoryW(settingsPath, NULL) || GetLastError() == ERROR_ALREADY_EXISTS) { - memcpy(settingsPath + (maxPathBypassLen + pathLen + folderPathLen), - settingsFile, sizeof(wchar_t) * settingsFileLen); - std::string utf8path = utf16ToUtf8(settingsPath); - free(settingsPath); - return utf8path; - } - } - } - return nullptr; - break; - case APP_PATH: - { - //Executable dir - settingsPath = getExeAbsPath(&exePathLength); - - //reverse wcsstr - while(exePathLength >= 0) { - if(settingsPath[exePathLength] == '\\') { - memset(settingsPath + exePathLength, - 0, - (UNICODE_STRING_MAX_CHARS - exePathLength) * sizeof(wchar_t)); - break; - } else exePathLength--; - } - log_wdebugcpp(L"Exe folder: " + std::wstring(settingsPath)); - if((UNICODE_STRING_MAX_CHARS - exePathLength) > (settingsFileLen + 1)) { - memcpy(settingsPath + exePathLength, settingsFile, sizeof(wchar_t) * settingsFileLen); - std::string utf8path = utf16ToUtf8(settingsPath); - free(settingsPath); - return utf8path; - } - } - return nullptr; - break; - default: - return nullptr; - break; - } - return nullptr; -} - -void Environment::populateSystemValues() { - updateColors(); - Environment::startup = checkStartup(scope); -} - -void Environment::openControlPanel() { - STARTUPINFOEXW startupConfig; - PROCESS_INFORMATION processInfo; - SecureZeroMemory(&startupConfig, sizeof(STARTUPINFOEXW)); - SecureZeroMemory(&startupConfig.StartupInfo, sizeof(STARTUPINFOW)); - startupConfig.StartupInfo.cb = sizeof(STARTUPINFOEXW); - SecureZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION)); - - std::wstring command = L"rundll32 shell32, Control_RunDLL mmsys.cpl"; - if(CreateProcessW( - NULL, - (wchar_t*)command.c_str(), - NULL, - NULL, - false, - CREATE_UNICODE_ENVIRONMENT, - NULL, - NULL, - (LPSTARTUPINFOW)&startupConfig, - &processInfo - ) == true) { - CloseHandle(processInfo.hProcess); - CloseHandle(processInfo.hThread); - } -} - -ProcessedNativeEvent Environment::processTopLevelWindowMessage(void* msg) { -#ifdef WIN32 - MSG *message = static_cast(msg); - switch(message->message) { - case WM_SETTINGCHANGE: - //TODO: This looks like a future pain point. Ex handler would come in clutch - if(message->lParam && !wcscmp(((wchar_t*)message->lParam), L"ImmersiveColorSet")) - return updateColors(); - break; - default: - return ProcessedNativeEvent::NONE; - break; - } - return ProcessedNativeEvent::NONE; - //if (message->message != WM_SETTINGCHANGE) {return false;} -#endif -} - -ProcessedNativeEvent Environment::updateColors() { - // DwmGetColorizationColor( WM_DWMCOLORIZATIONCOLORCHANGED - DWORD value = 0; - DWORD size = sizeof(DWORD); - - LSTATUS result; - - //Theme bg color - result = RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", L"AppsUseLightTheme", RRF_RT_REG_DWORD, nullptr, &value, &size); - lightMode = (bool)value; - - //Accent color - result = RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\DWM", L"ColorizationColor", RRF_RT_REG_DWORD, nullptr, &value, &size); - if (result == ERROR_SUCCESS) { - accentColor = value; - } else accentColor = 0xffffffff; - - return ProcessedNativeEvent::COLORS; -} - -bool Environment::checkStartup(HKEY rootKeyFlags) { - //LSTATUS result; - DWORD typeReturned; - - //Checking if app entry exists - if(RegGetValueW(rootKeyFlags, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", LAPP_NAME, RRF_RT_REG_SZ, &typeReturned, nullptr, nullptr) != ERROR_SUCCESS && typeReturned != REG_SZ) - return false; - else return true; -} - -void Environment::updateStartupConfig(bool onStartup) { - wchar_t regSubKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run\\"; - - if(!onStartup) { - HKEY runKey; - if (RegOpenKeyExW( - scope, - regSubKey, - 0, - KEY_SET_VALUE, - &runKey - ) - == ERROR_SUCCESS) { - RegDeleteValueW(runKey, LAPP_NAME); - RegCloseKey(runKey); - } - } else { - LSTATUS result; - uint32_t cPathLen = 0; - wchar_t* cPath = getExeAbsPath(&cPathLen); - wchar_t* regPath = (wchar_t*)calloc(UNICODE_STRING_MAX_CHARS + 2, sizeof(wchar_t)); - //char* v = 0xFF'00'00'00'00'00'00'21; - regPath[0] = L'"'; - memcpy(regPath + 1, cPath, sizeof(wchar_t) * cPathLen); - memcpy(regPath + cPathLen + 1, L"\"", sizeof(wchar_t) * 2); - - result = RegSetKeyValueW( - scope, - regSubKey, - LAPP_NAME, - REG_SZ, - (void*)regPath, - (cPathLen + 3) * sizeof(wchar_t)); - /* - * if (result != ERROR_SUCCESS) { - * wchar_t* error; - * FormatMessageW( - * FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - * nullptr, - * (DWORD)result, - * LANG_USER_DEFAULT, - * error, - * 1, - * nullptr); - * LocalFree(error); - * } - */ - free(cPath); - } - return; -} - -void Environment::setStartupConfig(bool onStartup) { - //TODO: Use the cache!!!! lol - uint32_t cPathLen = 0; - wchar_t* cPath = getExeAbsPath(&cPathLen); - wchar_t startupParam[] = L"--change-startup"; - uint32_t startupParamLen = (sizeof(startupParam) / sizeof(wchar_t)) - 1; - wchar_t* completeParam = (wchar_t*)calloc(startupParamLen + 3, sizeof(wchar_t)); - memcpy(completeParam, startupParam, sizeof(wchar_t) * startupParamLen); - if (onStartup) - memcpy(completeParam + startupParamLen, L" 1", sizeof(wchar_t) * 3); - else - memcpy(completeParam + startupParamLen, L" 0", sizeof(wchar_t) * 3); - - if(scope == HKEY_LOCAL_MACHINE) { - ShellExecuteW( - NULL, - L"runas", - cPath, - completeParam, - NULL, // default dir - SW_SHOWNORMAL - ); - } else { - Environment::updateStartupConfig(onStartup); - } - free(cPath); - free(completeParam); - return; -} - -bool Environment::isLightMode() { - return lightMode; -} - -bool Environment::isToRunAtStartup() { - return startup; -} - -uint32_t Environment::getAccentColor() { - return accentColor; -} - //int Overseer::getCaptureEndpoints(std::vector *captureEndpoints); //IMMDeviceEnumerator** Overseer::setOrigin(); diff --git a/src/back/backlasses.h b/src/back/backlasses.h index 5acedba..0e816a8 100644 --- a/src/back/backlasses.h +++ b/src/back/backlasses.h @@ -1,173 +1,79 @@ #pragma once +#define WIN32_LEAN_AND_MEAN +//done by qt by def #define UNICODE + +//#include "debug.h" +/* #include */ +/* #include */ +/* #include */ + +#include +#include +#include +#include +#include + +#include +#include +#include +//#include +//#include +#include -#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 EndpointCallback; 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(); + Endpoint(IMMDevice* endpoint, uint64_t idx); uint64_t getIndex(); void setIndex(uint64_t idx); - void setVolume(NGuid guid, int channel, float volume); + void setVolume(NGuid* guid, int channel, float volume); uint32_t getChannelCount(); float getVolume(int channel); - void setMute(NGuid guid, bool muted); + 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 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; + void setCallback(EndpointCallback *epc); + void removeCallback(EndpointCallback *epc); ~Endpoint(); private: - void inline activateEndpointVolume(); - - std::vector endpointSessions; - uint32_t channelCount = 0; - IMMDevice *endpoint; - IAudioEndpointVolume *endpointVolume = nullptr; + uint32_t channelCount; + IMMDevice* endpoint; + IAudioEndpointVolume *endpointVolume ; 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; + // LPWSTR endpointID = NULL; }; -class EndpointVolumeCallback : public IAudioEndpointVolumeCallback { +class EndpointCallback : public IAudioEndpointVolumeCallback { public: - EndpointVolumeCallback(Endpoint* ep); + EndpointCallback(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(); + //~EndpointCallback(); private: ULONG ref = 1; Endpoint* ep; - std::atomic 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 isEpStateChanging = false; }; class Overseer { - + //TODO singleton? public: Overseer(); - void registerEndpointSituationCallback(); - NGuid getGuid(); - std::vector getPlaybackEndpoints(); - std::vector 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(); - + void reloadEndpoints(); + NGuid* getGuid(); //~Overseer(); //int getDefaultPlaybackEndpoint(Endpoint** defaultEndpoint); //int getDefaultCaptureEndpoint(Endpoint** defaultEndpoint); @@ -176,65 +82,13 @@ class Overseer { ~Overseer(); private: - void initCOMLibrary(); - NGuid guid; - + unsigned int numPlaybackEndpoints; IMMDeviceEnumerator *deviceEnumerator; - EndpointSituationCallback epsc; - std::vector playbackDevices; - std::vector captureDevices; - IPolicyConfig7* policyConfig; - friend class Endpoint; + void initCOMLibrary(); //IMMDeviceCollection *deviceCollection; //int numCaptureEndpoints; //std::vector *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 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; -}; diff --git a/src/back/backsessionclasses.cpp b/src/back/backsessionclasses.cpp deleted file mode 100644 index c9aaa85..0000000 --- a/src/back/backsessionclasses.cpp +++ /dev/null @@ -1,425 +0,0 @@ -#include "backsessionclasses.h" -#include "backfuncs.h" - -SessionStateCallback::SessionStateCallback(SessionHandler *sh) { - this->sh = sh; -} - -ULONG SessionStateCallback::AddRef() { - return InterlockedIncrement(&ref); -} - -ULONG SessionStateCallback::Release() { - ULONG tempRef = InterlockedDecrement(&ref); - if (tempRef == 0) { - delete this; - } - return tempRef; -} - -HRESULT SessionStateCallback::QueryInterface(REFIID riid, VOID **ppvInterface) { - if (IID_IUnknown == riid) - { - AddRef(); - *ppvInterface = (IUnknown*)this; - } - else if (__uuidof(IAudioSessionNotification) == riid) - { - AddRef(); - *ppvInterface = (IMMNotificationClient*)this; - } - else - { - *ppvInterface = NULL; - return E_NOINTERFACE; - } - return S_OK; -} - -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; -} - -HRESULT SessionStateCallback::OnIconPathChanged(LPCWSTR NewIconPath, LPCGUID EventContex) { - return S_OK; -} - -HRESULT SessionStateCallback::OnSimpleVolumeChanged(float NewVolume, BOOL NewMute, LPCGUID EventContext) { - sh->getVolumeInfo()->muted = NewMute; - sh->getVolumeInfo()->mainVolume = NewVolume; - sh->getVolumeInfo()->caller = GUIDToNGuid((LPGUID)EventContext); - /* - * if (NewMute) - * { - * printf("MUTE\n"); - * } - * else - * { - * printf("Volume = %d percent\n", - * (UINT32)(100*NewVolume + 0.5)); - * } - */ - return S_OK; -} - -HRESULT SessionStateCallback::OnChannelVolumeChanged(DWORD ChannelCount, float NewChannelVolumeArray[], DWORD ChangedChannel, LPCGUID EventContext) { - return S_OK; -} - -HRESULT SessionStateCallback::OnGroupingParamChanged(LPCGUID NewGroupingParam, LPCGUID EventContext) { - return S_OK; -} - -HRESULT SessionStateCallback::OnStateChanged(AudioSessionState NewState) { - SessionState newState;// = sh->getState(); - switch (NewState) { - case AudioSessionStateActive: - newState = SessionState::ACTIVE; - break; - case AudioSessionStateInactive: - newState = SessionState::INACTIVE; - break; - case AudioSessionStateExpired: - newState = SessionState::EXPIRED; - break; - } - - sh->reviseSessionShowing(newState); - return S_OK; -} - -HRESULT SessionStateCallback::OnSessionDisconnected(AudioSessionDisconnectReason DisconnectReason) { - if (DisconnectReason != DisconnectReasonDeviceRemoval) { - sh->setState(SessionState::DISCONNECTED); - sh->reviseSessionShowing(SessionState::DISCONNECTED); - } - return S_OK; -} - -Session::Session(Endpoint* ep, IAudioSessionControl2* sessionControl, size_t idx) { - this->ep = ep; - this->sessionControl = sessionControl; - this->idx = idx; - //https://matthewvaneerde.wordpress.com/2012/06/08/getting-audio-peak-meter-values-for-all-active-audio-sessions/ - if (FAILED(sessionControl->QueryInterface(__uuidof(IAudioMeterInformation), (void**)&meterInformation))) { log_wdebugcpp(L"sPeakbros......"); }; - //meterInformation = (IAudioMeterInformation*)sessionControl; - - AudioSessionState msState; - sessionControl->GetState(&msState); - switch (msState) { - case AudioSessionState::AudioSessionStateActive: - this->sessionState = SessionState::ACTIVE; - break; - case AudioSessionState::AudioSessionStateInactive: - this->sessionState = SessionState::INACTIVE; - break; - case AudioSessionState::AudioSessionStateExpired: - this->sessionState = SessionState::EXPIRED; - break; - } - - sessionControl->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&sessionVolume); - DWORD pid; - sessionControl->GetProcessId(&pid); - if (sessionControl->IsSystemSoundsSession() == S_OK) - this->sessionName = std::wstring(LSTRING_SYSTEM_SOUNDS); - else { - LPWSTR sessionDisplayName; - this->sessionControl->GetDisplayName(&sessionDisplayName); - if (!wcscmp(sessionDisplayName, L"")) { - std::wstring exePath; - if (getExePath(pid, &exePath)) { - this->sessionName = exePath; - if (fetchName(exePath, pid)) goto nameFound; - } - if (fetchNameViaWindowName(pid, &this->sessionName)) goto nameFound; - } else { - this->sessionName = std::wstring(sessionDisplayName); - goto nameFound; - } - - nameFound: - CoTaskMemFree(sessionDisplayName); - } -} - -float Session::getVolume(int channel){ - float volume; - if (channel == AudioChannel::CHANNEL_MAIN) { - if(FAILED(sessionVolume->GetMasterVolume(&volume))) { /* log_debugcpp("si") */;} - } else { - return 0.0; - //if(FAILED(endpointVolume->GetChannelVolumeLevelScalar(channel, &volume))) { /* log_debugcpp("si"); */} - } - return volume; -} - -float Session::getPeakVolume() { - float peakVol; - if(meterInformation) meterInformation->GetPeakValue(&peakVol); - else return 0; - return peakVol; -} - -/* - * uint32_t Endpoint::getChannelCount(){ - * return (uint32_t)channelCount; - * } - */ - -std::wstring Session::getName() { - return sessionName; -} - -void Session::setName(std::wstring newName) { - this->sessionName = newName; -} - -bool Session::getMute() { - BOOL mut; - if(FAILED(sessionVolume->GetMute(&mut))) { /* TIP: Below */ } - bool mute = (bool)mut; - return mute; -} - -void Session::setVolume(NGuid guid, int channel, float volume) { - //TIP: There used to be log messages here. Now, it's a ghost town. - GUID tempMsGuid = NGuidToGUID(guid); - if (channel == AudioChannel::CHANNEL_MAIN) { - if(FAILED(sessionVolume->SetMasterVolume(volume, &tempMsGuid))) {}; - } else { - //if(FAILED(sessionVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) {}; - } -} - -void Session::setIndex(size_t idx) { - this->idx = idx; -} - -void Session::setMute(NGuid guid, bool muted) { - GUID tempMsGuid = NGuidToGUID(guid); - if(FAILED(sessionVolume->SetMute(muted, &tempMsGuid))) { log_wdebugcpp(std::wstring(L"SessionVolume null?")); }; -} - -bool Session::getExePath(DWORD pid, std::wstring *exePath) { - //std::wstring msixName; - HANDLE processHandle; - wchar_t fileName[UNICODE_STRING_MAX_CHARS]; - processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - if (processHandle != NULL) { - if (GetModuleFileNameEx(processHandle, NULL, fileName, UNICODE_STRING_MAX_CHARS) == 0) { - CloseHandle(processHandle); - return false; - } - } else { - log_wdebugcpp(L"aye no procname. -> " + std::to_wstring(GetLastError())); - return false; - } - - *exePath = std::wstring(fileName); - return true; -} - -bool Session::fetchNameViaFD(std::wstring exePath, DWORD pid, std::wstring *sessionName) { - /* File description retrieval: size and available lang-codepages */ - struct LANGANDCODEPAGE { - WORD wLanguage; - WORD wCodePage; - } *translationArray; - - DWORD filler; - DWORD fileVersionInfoSize = GetFileVersionInfoSizeExW - (FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL, exePath.c_str(), &filler); - if (!fileVersionInfoSize) return false; - - void* fileVersionInfo = malloc(fileVersionInfoSize); - if(!GetFileVersionInfoExW(FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL, - exePath.c_str(),0,fileVersionInfoSize, fileVersionInfo)) { - return false; - } - - UINT translationArrayLen = 0; - 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 - * is available. Also possible to hardcode en-US or any other lang-codepage combo. When an actual translation - * sysem is put in place, I'll come finish this up. - */ - uint64_t availableLangs = (translationArrayLen / sizeof(LANGANDCODEPAGE)); - if (!availableLangs) { free(fileVersionInfo); return false; } - - int8_t syslangIdx = -1; - wchar_t metadataStringKey[256]; - wchar_t* metadataString = NULL; - for (UINT i = 0; i < availableLangs; i++) { - LANGID defaultUILanguage = GetUserDefaultUILanguage(); - if (defaultUILanguage != translationArray[i].wLanguage) - continue; - - syslangIdx = i; - break; - } - - UINT metadataStringSize = 0; - swprintf(metadataStringKey, L"\\StringFileInfo\\%04x%04x\\FileDescription", - translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wLanguage, - translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wCodePage); - if (VerQueryValueW(fileVersionInfo, metadataStringKey, (LPVOID*)&metadataString, &metadataStringSize) - && metadataString[0] != '\0') { - free(fileVersionInfo); - *sessionName = std::wstring(metadataString); - return true; - } - swprintf(metadataStringKey, L"\\StringFileInfo\\%04x%04x\\ProductName", - translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wLanguage, - translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wCodePage); - if (VerQueryValueW(fileVersionInfo, metadataStringKey, (LPVOID*)&metadataString, &metadataStringSize) - && metadataString[0] != '\0') { - free(fileVersionInfo); - *sessionName = std::wstring(metadataString); - return true; - } - - if(fileVersionInfo) - free(fileVersionInfo); - - return false; -} - - -bool Session::fetchNameViaMSIX(std::wstring exePath, DWORD pid, std::wstring *sessionName) { - HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); - if(!process) return false; - - //constant missing in mingw64. TB removed when I upgrade to a mingw64 ver that has it - #define APPLICATION_USER_MODEL_ID_MAX_LENGTH 130 - uint32_t length = APPLICATION_USER_MODEL_ID_MAX_LENGTH; - PWSTR userModelId = (PWSTR)malloc(length * sizeof(wchar_t)); - if(GetApplicationUserModelId(process, &length, userModelId) != ERROR_SUCCESS) { - CloseHandle(process); - return false; - } - CloseHandle(process); - - static constexpr wchar_t* prefix = L"shell:appsfolder\\"; - uint32_t prefixLen = wcslen(prefix); - uint32_t userModelIdLen = wcslen(userModelId); - wchar_t* fullName; - fullName = (prefixLen + userModelIdLen < length) - ? (wchar_t*)malloc(length * sizeof(wchar_t)) - : (wchar_t*)malloc((length * 2) * sizeof(wchar_t)); - for (int32_t i = prefixLen - 1; i >= 0; i--) { - fullName[i] = prefix[i]; - } - for (uint32_t i = 0; i < userModelIdLen + 1; i++) { - fullName[prefixLen + i] = userModelId[i]; - } - - IShellItem* si; - HRESULT hr = SHCreateItemFromParsingName(fullName, - nullptr, - IID_IShellItem, - (void**)&si - ); - free(fullName); - LPWSTR humanName = nullptr; - si->GetDisplayName(SIGDN_NORMALDISPLAY, &humanName); - if(humanName && humanName[0] != '\0') { - *sessionName = std::wstring(humanName); - CoTaskMemFree(humanName); - } - if(si) si->Release(); - - if (sessionName->length() > 0) - return true; - else return false; -} - - -bool Session::fetchNameViaWindowName(DWORD pid, std::wstring *sessionName) { - //lParam is documented as in, so... Beware of future explosions, ig? - std::pair params = { 0, pid }; - - BOOL result = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL { - auto pParams = (std::pair*)(lParam); - - DWORD processId; - //IsWindowVisible(hwnd) &&&& GetWindow(hwnd, GW_OWNER) == 0 - if ( GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second) { - int length = GetWindowTextLength(hwnd); - if (!length) return TRUE; - - // Stop enumerating - SetLastError(-1); - pParams->first = hwnd; - return FALSE; - } - - // Continue enumerating - return TRUE; - } , (LPARAM)¶ms); - - if(!result && GetLastError() == -1 && params.first) { - //todo: double-dipping length... Not a fan - int length = GetWindowTextLength(params.first); - wchar_t* buffer = new wchar_t[length + 1]; - GetWindowTextW(params.first, buffer, length + 1); - *sessionName = buffer; - delete[] buffer; - return true; - } - return false; -} - -bool Session::fetchName(std::wstring exePath, DWORD pid) { - /* - * if(fetchNameViaWindowName(exePath, pid, &this->sessionName)) - * return; - * else if(fetchNameViaMSIX(exePath, pid, &this->sessionName)) - * return; - * else if(!fetchNameViaFD(exePath, pid, &this->sessionName)) - * this->sessionName = exePath; - */ - - if(fetchNameViaFD(exePath, pid, &this->sessionName)) - return true; - return fetchNameViaMSIX(exePath, pid, &this->sessionName); - //else if(!fetchNameViaWindowName(exePath, pid, &this->sessionName)) - /// this->sessionName = exePath; - -} - -//todo: conflicting names. change callback name -void Session::setState(SessionState state) { - sessionState = state; -} - -SessionState Session::getState() { - return sessionState; -} - -void Session::setStateCallback(SessionStateCallback *ssc){ - sessionControl->RegisterAudioSessionNotification((IAudioSessionEvents*) ssc); -} - -void Session::removeStateCallback(SessionStateCallback *ssc){ - sessionControl->UnregisterAudioSessionNotification((IAudioSessionEvents*) ssc); -} - -Session::~Session() { - meterInformation->Release(); - sessionControl->Release(); - sessionVolume->Release(); - meterInformation = nullptr; - sessionControl = nullptr; - sessionVolume = nullptr; -} diff --git a/src/back/backsessionclasses.h b/src/back/backsessionclasses.h deleted file mode 100644 index ae87f0a..0000000 --- a/src/back/backsessionclasses.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include "msinclude.h" - -#include "global.h" -#include "contclasses.h" - -class Endpoint; - -class SessionStateCallback : public IAudioSessionEvents { - public: - SessionStateCallback(SessionHandler *sh); - ULONG AddRef(); - ULONG Release(); - HRESULT QueryInterface(REFIID riid, VOID **ppvInterface); - HRESULT OnSessionCreated(IAudioSessionControl *NewSession); - HRESULT OnChannelVolumeChanged(DWORD ChannelCount, float NewChannelVolumeArray[], DWORD ChangedChannel, LPCGUID EventContext); - HRESULT OnDisplayNameChanged(LPCWSTR NewDisplayName, LPCGUID EventContext); - HRESULT OnGroupingParamChanged( LPCGUID NewGroupingParam, LPCGUID EventContext); - HRESULT OnIconPathChanged(LPCWSTR NewIconPath, LPCGUID EventContext); - HRESULT OnSessionDisconnected(AudioSessionDisconnectReason DisconnectReason); - HRESULT OnSimpleVolumeChanged(float NewVolume, BOOL NewMute, LPCGUID EventContext); - HRESULT OnStateChanged(AudioSessionState NewState); - - private: - ULONG ref = 1; - SessionHandler *sh; -}; - -class Session { - - public: - Session(Endpoint* ep, IAudioSessionControl2* sessionControl, size_t idx); - Session(Endpoint* ep, IAudioSessionControl2* sessionControl) : Session(ep, sessionControl, SIZE_MAX) {}; - void setVolume(NGuid guid, int channel, float volume); - float getVolume(int channel); - float getPeakVolume(); - void setMute(NGuid guid, bool muted); - bool getMute(); - SessionState getState(); - void setState(SessionState state); - void setIndex(size_t idx); - std::wstring getName(); - void setName(std::wstring newName); - void setStateCallback(SessionStateCallback *ssc); - void removeStateCallback(SessionStateCallback *ssc); - ~Session(); - //uint32_t getChannelCount(); - - private: - bool getExePath(DWORD pid, /*out*/ std::wstring *exePath); - bool fetchName(std::wstring exePath, DWORD pid); - bool fetchNameViaFD(std::wstring exePath, DWORD pid, /*out*/ std::wstring *sessionName); - bool fetchNameViaMSIX(std::wstring exePath, DWORD pid, /*out*/ std::wstring *sessionName); - bool fetchNameViaWindowName(DWORD pid, /*out*/ std::wstring *sessionName); - /* std::wstring fetchProcessName(DWORD pid); */ - std::wstring sessionName; - SessionState sessionState; - Endpoint* ep; - IAudioSessionControl2* sessionControl = nullptr; - IAudioMeterInformation* meterInformation = nullptr; - ISimpleAudioVolume* sessionVolume = nullptr; - size_t idx; -}; - diff --git a/src/back/ipolicyconfig.h b/src/back/ipolicyconfig.h deleted file mode 100644 index 7b474bb..0000000 --- a/src/back/ipolicyconfig.h +++ /dev/null @@ -1,311 +0,0 @@ -#pragma once - -#ifndef __IPolicyConfig7_FWD_DEFINED__ -#define __IPolicyConfig7_FWD_DEFINED__ -typedef interface IPolicyConfig7 IPolicyConfig7; -#ifdef __cplusplus -interface IPolicyConfig7; -#endif -#endif /* __IPolicyConfig7_FWD_DEFINED__ */ - -#ifndef __CPolicyConfigClient_FWD_DEFINED__ -#define __CPolicyConfigClient_FWD_DEFINED__ -typedef class CPolicyConfigClient CPolicyConfigClient; -#endif /* __CPolicyConfigClient_FWD_DEFINED__ */ - -/***************************************************************************** - * CPolicyConfigClient coclass - */ - -DEFINE_GUID(CLSID_CPolicyConfigClient, 0x870af99c, 0x171d, 0x4f9e, 0xaf,0x0d, 0xe6,0x3d,0xf4,0x0c,0x2b,0xc9); -#ifdef __cplusplus -class DECLSPEC_UUID("870af99c-171d-4f9e-af0d-e63df40c2bc9") CPolicyConfigClient; -#ifdef __CRT_UUID_DECL -__CRT_UUID_DECL(CPolicyConfigClient, 0x870af99c, 0x171d, 0x4f9e, 0xaf,0x0d, 0xe6,0x3d,0xf4,0x0c,0x2b,0xc9) -#endif -#endif - - -/***************************************************************************** - * IPolicyConfig7 interface - */ -#ifndef __IPolicyConfig7_INTERFACE_DEFINED__ -#define __IPolicyConfig7_INTERFACE_DEFINED__ -DEFINE_GUID(IID_IPolicyConfig7, 0xf8679f50, 0x850a, 0x41cf, 0x9c,0x72, 0x43,0x0f,0x29,0x02,0x90,0xc8); -#if defined(__cplusplus) && !defined(CINTERFACE) -MIDL_INTERFACE("f8679f50-850a-41cf-9c72-430f290290c8") -IPolicyConfig7 : public IUnknown { - -public: - virtual HRESULT GetMixFormat( - PCWSTR, - WAVEFORMATEX ** - ); - - virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( - PCWSTR, - INT, - WAVEFORMATEX ** - ); - - virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( - PCWSTR - ); - - virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( - PCWSTR, - WAVEFORMATEX *, - WAVEFORMATEX * - ); - - virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( - PCWSTR, - INT, - PINT64, - PINT64 - ); - - virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( - PCWSTR, - PINT64 - ); - - virtual HRESULT STDMETHODCALLTYPE GetShareMode( - PCWSTR, - struct DeviceShareMode * - ); - - virtual HRESULT STDMETHODCALLTYPE SetShareMode( - PCWSTR, - struct DeviceShareMode * - ); - - virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( - PCWSTR, - const PROPERTYKEY &, - PROPVARIANT * - ); - - virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( - PCWSTR, - const PROPERTYKEY &, - PROPVARIANT * - ); - - virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( - PCWSTR wszDeviceId, - ERole eRole - ); - - virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( - PCWSTR, - INT - ); -}; -#ifdef __CRT_UUID_DECL -__CRT_UUID_DECL(IPolicyConfig7, 0xf8679f50, 0x850a, 0x41cf, 0x9c,0x72, 0x43,0x0f,0x29,0x02,0x90,0xc8) -#endif - -#endif - - -#endif /* __IPolicyConfig7_INTERFACE_DEFINED__ */ - - - - -/* __CRT_UUID_DECL(IPolicyConfig10, 0xca286fc3, 0x91fd, 0x42c3, 0x8e,0x9b, 0xca,0xaf,0xa6,0x62,0x42,0xe3) */ -/* __CRT_UUID_DECL(CPolicyConfigClient, 0x870af99c, 0x171d, 0x4f9e, 0xaf,0x0d, 0xe6,0x3d,0xf4,0x0c,0x2b,0xc9) */ - - -/* // ---------------------------------------------------------------------------- */ -/* // PolicyConfig.h */ -/* // Undocumented COM-interface IPolicyConfig. */ -/* // Use for set default audio render endpoint */ -/* // @author EreTIk */ -/* // ---------------------------------------------------------------------------- */ - -/* #pragma once */ - -/* interface DECLSPEC_UUID("CA286FC3-91FD-42C3-8E9B-CAAFA66242E3") */ -/* IPolicyConfig10; */ - -/* interface DECLSPEC_UUID("00000000-0000-0000-C000-000000000046") */ -/* IPolicyConfig10_1; */ - -/* interface DECLSPEC_UUID("F8679F50-850A-41CF-9C72-430F290290C8") */ -/* IPolicyConfig7; */ - -/* /\* interface DECLSPEC_UUID("568B9108-44BF-40B4-9006-86AFE5B5A620") *\/ */ -/* /\* IPolicyConfigVista; *\/ */ - -/* interface DECLSPEC_UUID("f8679f50-850a-41cf-9c72-430f290290c8") */ -/* IPolicyConfig; */ - -/* class DECLSPEC_UUID("870af99c-171d-4f9e-af0d-e63df40c2bc9") */ -/* CPolicyConfigClient; */ -/* // ---------------------------------------------------------------------------- */ -/* // class CPolicyConfigClient */ -/* // {870af99c-171d-4f9e-af0d-e63df40c2bc9} */ -/* // */ -/* // interface IPolicyConfig */ -/* // {f8679f50-850a-41cf-9c72-430f290290c8} */ -/* // */ -/* // Query interface: */ -/* // CComPtr PolicyConfig; */ -/* // PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigClient)); */ -/* // */ -/* // @compatible: Windows 7 and Later */ -/* // ---------------------------------------------------------------------------- */ -/* interface IPolicyConfig : public IUnknown */ -/* { */ -/* public: */ - -/* virtual HRESULT GetMixFormat( */ -/* PCWSTR, */ -/* WAVEFORMATEX ** */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( */ -/* PCWSTR, */ -/* INT, */ -/* WAVEFORMATEX ** */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( */ -/* PCWSTR */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( */ -/* PCWSTR, */ -/* WAVEFORMATEX *, */ -/* WAVEFORMATEX * */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( */ -/* PCWSTR, */ -/* INT, */ -/* PINT64, */ -/* PINT64 */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( */ -/* PCWSTR, */ -/* PINT64 */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE GetShareMode( */ -/* PCWSTR, */ -/* struct DeviceShareMode * */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE SetShareMode( */ -/* PCWSTR, */ -/* struct DeviceShareMode * */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( */ -/* PCWSTR, */ -/* const PROPERTYKEY &, */ -/* PROPVARIANT * */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( */ -/* PCWSTR, */ -/* const PROPERTYKEY &, */ -/* PROPVARIANT * */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( */ -/* PCWSTR wszDeviceId, */ -/* ERole eRole */ -/* ); */ - -/* virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( */ -/* PCWSTR, */ -/* INT */ -/* ); */ -/* }; */ - -/* /\* interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") *\/ */ -/* /\* IPolicyConfigVista; *\/ */ -/* /\* class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") *\/ */ -/* /\* CPolicyConfigVistaClient; *\/ */ -/* /\* // ---------------------------------------------------------------------------- *\/ */ -/* /\* // class CPolicyConfigVistaClient *\/ */ -/* /\* // {294935CE-F637-4E7C-A41B-AB255460B862} *\/ */ -/* /\* // *\/ */ -/* /\* // interface IPolicyConfigVista *\/ */ -/* /\* // {568b9108-44bf-40b4-9006-86afe5b5a620} *\/ */ -/* /\* // *\/ */ -/* /\* // Query interface: *\/ */ -/* /\* // CComPtr PolicyConfig; *\/ */ -/* /\* // PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigVistaClient)); *\/ */ -/* /\* // *\/ */ -/* /\* // @compatible: Windows Vista and Later *\/ */ -/* /\* // ---------------------------------------------------------------------------- *\/ */ -/* /\* interface IPolicyConfigVista : public IUnknown *\/ */ -/* /\* { *\/ */ -/* /\* public: *\/ */ - -/* /\* virtual HRESULT GetMixFormat( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* WAVEFORMATEX ** *\/ */ -/* /\* ); // not available on Windows 7, use method from IPolicyConfig *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* INT, *\/ */ -/* /\* WAVEFORMATEX ** *\/ */ -/* /\* ); *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* WAVEFORMATEX *, *\/ */ -/* /\* WAVEFORMATEX * *\/ */ -/* /\* ); *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* INT, *\/ */ -/* /\* PINT64, *\/ */ -/* /\* PINT64 *\/ */ -/* /\* ); // not available on Windows 7, use method from IPolicyConfig *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* PINT64 *\/ */ -/* /\* ); // not available on Windows 7, use method from IPolicyConfig *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE GetShareMode( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* struct DeviceShareMode * *\/ */ -/* /\* ); // not available on Windows 7, use method from IPolicyConfig *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE SetShareMode( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* struct DeviceShareMode * *\/ */ -/* /\* ); // not available on Windows 7, use method from IPolicyConfig *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* const PROPERTYKEY &, *\/ */ -/* /\* PROPVARIANT * *\/ */ -/* /\* ); *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* const PROPERTYKEY &, *\/ */ -/* /\* PROPVARIANT * *\/ */ -/* /\* ); *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( *\/ */ -/* /\* __in PCWSTR wszDeviceId, *\/ */ -/* /\* __in ERole eRole *\/ */ -/* /\* ); *\/ */ - -/* /\* virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( *\/ */ -/* /\* PCWSTR, *\/ */ -/* /\* INT *\/ */ -/* /\* ); // not available on Windows 7, use method from IPolicyConfig *\/ */ -/* /\* }; *\/ */ diff --git a/src/back/msinclude.h b/src/back/msinclude.h deleted file mode 100644 index 52fccbd..0000000 --- a/src/back/msinclude.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include - -//done by qt by def #define UNICODE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include - -#include -#include -#include -//#include -//#include -#include -#include -#include -#include -#include - -#include "ipolicyconfig.h" -#include "audiometerinfo.h" - -// IAudioMeterInformation -/* GUID manual; */ -/* manual.Data1 = 0xc02216f6; */ -/* manual.Data2 = 0x8c67; */ -/* manual.Data3 = 0x4b5b; */ -/* manual.Data4[0] = 0x9d; */ -/* manual.Data4[1] = 0x00; */ -/* manual.Data4[2] = 0xd0; */ -/* manual.Data4[3] = 0x08; */ -/* manual.Data4[4] = 0xe7; */ -/* manual.Data4[5] = 0x3e; */ -/* manual.Data4[6] = 0x00; */ -/* manual.Data4[7] = 0x64; */ -//if(FAILED(endpoint->Activate((const _GUID) manual, - -//IMMEndpoint -/* GUID manual; */ -/* manual.Data1 = 0x1be09788; */ -/* manual.Data2 = 0x6894; */ -/* manual.Data3 = 0x4089; */ -/* manual.Data4[0] = 0x85; */ -/* manual.Data4[1] = 0x86; */ -/* manual.Data4[2] = 0x9a; */ -/* manual.Data4[3] = 0x2a; */ -/* manual.Data4[4] = 0x6c; */ -/* manual.Data4[5] = 0x26; */ -/* manual.Data4[6] = 0x5a; */ -/* manual.Data4[7] = 0xc5; */ diff --git a/src/back/reimpl/audiometerinfo.h b/src/back/reimpl/audiometerinfo.h deleted file mode 100644 index 618ad34..0000000 --- a/src/back/reimpl/audiometerinfo.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef __IAudioMeterInformation_FWD_DEFINED__ -#define __IAudioMeterInformation_FWD_DEFINED__ -typedef interface IAudioMeterInformation IAudioMeterInformation; - -#endif /* __IAudioMeterInformation_FWD_DEFINED__ */ - -#ifdef __cplusplus -extern "C"{ -#endif - -/* interface __MIDL_itf_endpointvolume_0000_0003 */ -/* [local] */ - -#ifndef __IAudioMeterInformation_INTERFACE_DEFINED__ -#define __IAudioMeterInformation_INTERFACE_DEFINED__ - -/* interface IAudioMeterInformation */ -/* [unique][helpstring][nonextensible][uuid][local][object] */ - -DEFINE_GUID(IID_IAudioMeterInformation, 0xc02216f6, 0x8c67, 0x4b5b, 0x9d,0x00, 0xd0,0x08,0xe7,0x3e,0x00,0x64); -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("c02216f6-8c67-4b5b-9d00-d008e73e0064") - IAudioMeterInformation : public IUnknown - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPeakValue( - /* [out] */ float *pfPeak) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMeteringChannelCount( - /* [annotation][out] */ - _Out_ UINT *pnChannelCount) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelsPeakValues( - /* [in] */ UINT32 u32ChannelCount, - /* [size_is][out] */ float *afPeakValues) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE QueryHardwareSupport( - /* [annotation][out] */ - _Out_ DWORD *pdwHardwareSupportMask) = 0; - - }; - -#ifdef __CRT_UUID_DECL -__CRT_UUID_DECL(IAudioMeterInformation, 0xc02216f6, 0x8c67, 0x4b5b, 0x9d,0x00, 0xd0,0x08,0xe7,0x3e,0x00,0x64) -#endif -#else /* C style interface */ - - typedef struct IAudioMeterInformationVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAudioMeterInformation * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAudioMeterInformation * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAudioMeterInformation * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPeakValue )( - IAudioMeterInformation * This, - /* [out] */ float *pfPeak); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetMeteringChannelCount )( - IAudioMeterInformation * This, - /* [annotation][out] */ - _Out_ UINT *pnChannelCount); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetChannelsPeakValues )( - IAudioMeterInformation * This, - /* [in] */ UINT32 u32ChannelCount, - /* [size_is][out] */ float *afPeakValues); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *QueryHardwareSupport )( - IAudioMeterInformation * This, - /* [annotation][out] */ - _Out_ DWORD *pdwHardwareSupportMask); - - END_INTERFACE - } IAudioMeterInformationVtbl; - - interface IAudioMeterInformation - { - CONST_VTBL struct IAudioMeterInformationVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAudioMeterInformation_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define IAudioMeterInformation_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define IAudioMeterInformation_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define IAudioMeterInformation_GetPeakValue(This,pfPeak) \ - ( (This)->lpVtbl -> GetPeakValue(This,pfPeak) ) - -#define IAudioMeterInformation_GetMeteringChannelCount(This,pnChannelCount) \ - ( (This)->lpVtbl -> GetMeteringChannelCount(This,pnChannelCount) ) - -#define IAudioMeterInformation_GetChannelsPeakValues(This,u32ChannelCount,afPeakValues) \ - ( (This)->lpVtbl -> GetChannelsPeakValues(This,u32ChannelCount,afPeakValues) ) - -#define IAudioMeterInformation_QueryHardwareSupport(This,pdwHardwareSupportMask) \ - ( (This)->lpVtbl -> QueryHardwareSupport(This,pdwHardwareSupportMask) ) - -#endif /* COBJMACROS */ - -#endif /* C style interface */ - -#endif /* __IAudioMeterInformation_INTERFACE_DEFINED__ */ - -#ifdef __cplusplus -} -#endif - - - diff --git a/src/cont/contclasses.cpp b/src/cont/contclasses.cpp index d2188f0..381550b 100644 --- a/src/cont/contclasses.cpp +++ b/src/cont/contclasses.cpp @@ -1,67 +1,16 @@ #include "backlasses.h" #include "contclasses.h" +//TODO: pragma once -void setConfigDirToDefaults() { - #define tryFileDir(dir, create) do { \ - OverseerHandler::settingsPath = Environment::createSettingsPath(dir); \ - set = ini::UserSettings::createSettings(OverseerHandler::settingsPath.c_str(), create); \ - if(set) { \ - return; \ - } else OverseerHandler::settingsPath.clear(); \ - } while(0) - #define tryOpenFileDir(dir) tryFileDir(dir, false) - #define tryCreateFileDir(dir) tryFileDir(dir, true) - - tryOpenFileDir(SettingsTargetDirectory::APP_PATH); - tryOpenFileDir(SettingsTargetDirectory::HOME_DIR); - tryCreateFileDir(SettingsTargetDirectory::HOME_DIR); - tryCreateFileDir(SettingsTargetDirectory::APP_PATH); - - return; - #undef tryOpenFileDir - #undef tryCreateFileDir - #undef tryFileDir -} +//TODO: ????? +Overseer OverseerHandler::os; -EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) { - this->idx = idx; - this->flow = flow; - this->ep = (flow == Flows::FLOW_PLAYBACK ? osh->getPlaybackEndpoints().at(idx) : osh->getCaptureEndpoints().at(idx)); - - this->callbackInfo.caller = osh->getGuid(); +EndpointHandler::EndpointHandler(uint64_t idx) { + //std::vector endpoints = osh->getPlaybackEndpoints().at(idx); + this->ep = osh->getPlaybackEndpoints().at(idx); + epc = new EndpointCallback(ep); //epName = ep->getName(); - this->setBackEndpointVolumeCallbackInfoContent(this->getState()); - osh->pushBackEndpointHandler(this, flow); -} - -void OverseerHandler::pushBackEndpointHandler(EndpointHandler* eph, Flows flow) { - if (eph == nullptr) return; - if (flow == Flows::FLOW_PLAYBACK) - this->playbackEndpointHandlers.push_back(eph); - else - this->captureEndpointHandlers.push_back(eph); - return; -} - -void EndpointHandler::setFrontVisibilityInfo(EndpointState state, uint64_t frontIdx){ - ephfv.visibility = state; - ephfv.frontIdx = frontIdx; -} - -uint64_t EndpointHandler::getFrontVisibilityIndex(){ - return ephfv.frontIdx; -} - -EndpointState EndpointHandler::getFrontVisibilityState(){ - return ephfv.visibility; -} - -Flows EndpointHandler::getFlow(){ - return ep->getFlow(); -} - -BackEndpointVolumeCallbackInfo* EndpointHandler::getCallbackInfo(){ - return &this->callbackInfo; + ep->setCallback(epc); } uint32_t EndpointHandler::getChannelCount(){ @@ -79,13 +28,15 @@ uint64_t EndpointHandler::getIndex(){ /* * -1 for master volume */ -void EndpointHandler::setVolume(NGuid guid, int channel, int value){ - if (channel == AudioChannel::CHANNEL_MAIN) +void EndpointHandler::setVolume(NGuid* guid, int channel, int value){ + if (channel == ENDPOINT_MASTER_VOLUME) ep->setVolume(guid, channel, (float)value / 100); else ep->setVolume(guid, channel, (float)value / 100); } -void EndpointHandler::setMute(NGuid guid, bool muted){ +void EndpointHandler::setMute(NGuid* guid, bool muted){ + //Qt momento, de ahi el param? + log_debugcpp("kinda handling the muting tbh"); ep->setMute(guid, muted); } @@ -93,10 +44,6 @@ std::wstring EndpointHandler::getName(){ return ep->getName(); } -std::wstring EndpointHandler::getId(){ - return ep->getId(); -} - float EndpointHandler::getVolume(int channel){ return ep->getVolume(channel); } @@ -105,360 +52,87 @@ bool EndpointHandler::getMute(){ return ep->getMute(); } -size_t EndpointHandler::getState(){ - return ep->getState(); -} - -void EndpointHandler::setBackEndpointVolumeCallbackInfoContent(uint8_t state) { - if(state == EndpointState::ENDPOINT_ACTIVE) { - 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); - } - } -} - -void EndpointHandler::setState(EndpointState state){ - ep->setState(state); - this->setBackEndpointVolumeCallbackInfoContent(state); -} - -void EndpointHandler::setState(EndpointState state, uint64_t index){ - ep->setState(state); - this->setFrontVisibilityInfo((EndpointState)state, index); - this->setBackEndpointVolumeCallbackInfoContent(state); -} - -float EndpointHandler::getPeakVolume() { - return ep->getPeakVolume(); -} - -uint8_t EndpointHandler::getRoles(){ - return ep->getRoles(); -} - -void EndpointHandler::setRoles(Roles newRole){ - ep->setRoles(newRole); -} - -void EndpointHandler::assignRoles(Roles newRole){ - ep->assignRoles(newRole); -} - -void EndpointHandler::removeRoles(Roles newRole){ - ep->removeRoles(newRole); -} - -void EndpointHandler::setAddSessionWidgetFunction(std::function addSessionWidget) { - this->addSessionWidget = addSessionWidget; -} - -void EndpointHandler::setRemoveSessionWidgetFunction(std::function removeSessionWidget) { - this->removeSessionWidget = removeSessionWidget; -} - -/* sessions */ -size_t EndpointHandler::getSessionCount() { - return ep->getSessionCount(); -} - -std::vector EndpointHandler::getSessions(){ - return ep->getSessions(); -} - -std::vector EndpointHandler::getSessionHandlers(){ - return this->sessionHandlers; -} - -Endpoint* EndpointHandler::getEndpoint() { - return this->ep; -} - -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)); - - sessionHandlers.push_back(sessionHandler); - ep->endpointSessionsMutex.unlock(); - sessionHandlersMutex.unlock(); - this->addSessionWidget(sessionHandler); -} - -void EndpointHandler::sendSessionToFront(SessionHandler* sh) { - this->addSessionWidget(sh); -} - -void EndpointHandler::removeSessionFromFront(SessionHandler* sh) { - this->removeSessionWidget(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() { - ep->activateEndpointSessions(); - if (this->flow == Flows::FLOW_PLAYBACK) { - for (int i = 0; i < this->getSessionCount(); i++) { - SessionHandler* sessionHandler = new SessionHandler(this, this->getSessions().at(i),i); - sessionHandlers.push_back(sessionHandler); - } - } -} - -void EndpointHandler::createSessionHandlersCallback() { - ensc = new EndpointNewSessionCallback(this); - ep->registerNewSessionNotification(ensc); -} - -void EndpointHandler::lockSessionCollections() { - this->sessionHandlersMutex.lock(); - this->ep->endpointSessionsMutex.lock(); -} - -void EndpointHandler::unlockSessionCollections() { - this->sessionHandlersMutex.unlock(); - this->ep->endpointSessionsMutex.unlock(); -} - -void EndpointHandler::removeVolumeCallback() { - ep->removeVolumeCallback(epc); - epc->Release(); - epc = nullptr; -} - EndpointHandler::~EndpointHandler() { - ep->removeVolumeCallback(epc); - ep->unregisterNewSessionNotification(ensc); + ep->removeCallback(epc); epc->Release(); delete ep; } -OverseerHandler::OverseerHandler() { - this->os = new Overseer(); -} - -void OverseerHandler::setSettingsPath(std::string path) { - OverseerHandler::settingsPath = path; -} - -std::string OverseerHandler::getSettingsPath(){ - return OverseerHandler::settingsPath; -} - -void OverseerHandler::updateStartupConfig(bool onStartup) { - Environment::updateStartupConfig(onStartup); -} - -void OverseerHandler::setStartupConfig(bool onStartup) { - Environment::setStartupConfig(onStartup); -} - -void OverseerHandler::populateSystemValues() { - Environment::populateSystemValues(); -} - -void OverseerHandler::openControlPanel() { - Environment::openControlPanel(); -} - -ProcessedNativeEvent OverseerHandler::processTopLevelWindowMessage(void* msg) { - return Environment::processTopLevelWindowMessage(msg); -} - -bool OverseerHandler::isLightMode() { - return Environment::isLightMode(); -} - -bool OverseerHandler::isToRunAtStartup() { - return Environment::isToRunAtStartup(); -} - -uint32_t OverseerHandler::getAccentColor() { - return Environment::getAccentColor(); -} - std::vector OverseerHandler::getPlaybackEndpoints() { - return this->os->getPlaybackEndpoints(); + return this->os.getPlaybackEndpoints(); } -std::vector OverseerHandler::getCaptureEndpoints() { - return this->os->getCaptureEndpoints(); -} -std::vector OverseerHandler::getPlaybackEndpointHandlers(){ - return playbackEndpointHandlers; -} - -std::vector OverseerHandler::getCaptureEndpointHandlers(){ - return captureEndpointHandlers; +std::vector OverseerHandler::getEndpointHandlers(){ + return endpointHandlers; } uint64_t OverseerHandler::getPlaybackEndpointsCount(){ - return this->os->getPlaybackEndpoints().size(); + return this->os.getPlaybackEndpoints().size(); } -uint64_t OverseerHandler::getCaptureEndpointsCount(){ - return this->os->getCaptureEndpoints().size(); -} - -void OverseerHandler::createEndpointHandlers(){ - //todo: add capture - +void OverseerHandler::reloadEndpointHandlers(){ //std::vector* ephs = new std::vector; - log_debugcpp("Playback VSize: " + std::to_string(this->getPlaybackEndpointsCount())); + log_debugcpp(" VSize: " << this->getPlaybackEndpointsCount()); for(uint64_t i = 0; i < this->getPlaybackEndpointsCount(); i++){ - log_debugcpp("Creating Playback handler " + std::to_string(i)); - new EndpointHandler(i, Flows::FLOW_PLAYBACK); - log_debugcpp("Created Playback handler " + std::to_string(i) + ", adding to vector. " + " VSize: " + std::to_string(this->playbackEndpointHandlers.size())); + log_debugcpp("Creating handler " << i); + if(i < (this->endpointHandlers.size()) && + this->endpointHandlers.at(i) != nullptr) + delete endpointHandlers.at(i); + + EndpointHandler* eph = new EndpointHandler(i); + log_debugcpp("Created handler " << i << ", adding to vector. " << " VSize: " << this->getPlaybackEndpointsCount()); + + if (i >= this->endpointHandlers.size()) + endpointHandlers.push_back(eph); + else endpointHandlers.at(i) = eph; } - - log_debugcpp("Capture VSize: " + - std::to_string(this->getCaptureEndpointsCount())); - - for(uint64_t i = 0; i < this->getCaptureEndpointsCount(); i++) { - log_debugcpp("Creating Capture handler " + std::to_string(i)); - new EndpointHandler(i, Flows::FLOW_CAPTURE); - log_debugcpp("Created Capture handler " + std::to_string(i) + ", adding to vector. " + " VSize: " + std::to_string(this->captureEndpointHandlers.size())); - /* - * if (i >= this->captureEndpointHandlers.size()) - * captureEndpointHandlers.push_back(eph); - * else captureEndpointHandlers.at(i) = eph; - */ - } - os->registerEndpointSituationCallback(); + //setEndpointHandlers(ephs); } -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; - Endpoint* newEp = this->os->addEndpoint(endpointId, &localFlow); - - uint64_t ephIdx = (localFlow == Flows::FLOW_PLAYBACK ? this->getPlaybackEndpointsCount() : this->getCaptureEndpointsCount()) - 1; - - EndpointHandler* newEph = new EndpointHandler(ephIdx, localFlow); - if (flow != nullptr) *flow = localFlow; - return newEph; -} - -void OverseerHandler::reportFinishedStateChange() { - os->reportFinishedStateChange(); -} - -NGuid OverseerHandler::getGuid() { - return this->os->getGuid(); -} - -/* - * void OverseerHandler::setChangeFrontDefaultsFunction(std::function changeFrontDefaults){ - * this->changeFrontDefaults = changeFrontDefaults; - * } - * - * void OverseerHandler::changeFrontDefaultsCallback(Roles role, std::wstring endpointId) { - * this->changeFrontDefaults(role, endpointId); - * } - */ - -void OverseerHandler::roleBucketEntryCallback(Roles role, std::wstring endpointId){ - this->roleBucketEntry(role, endpointId); -} - -void OverseerHandler::setRoleBucketEntryFunction(std::function roleBucketEntry) { - this->roleBucketEntry = roleBucketEntry; -} - -void OverseerHandler::updateFrontEndpointName(Endpoint* ep) { - //todo: reintroduce capture devices - for (auto eph : playbackEndpointHandlers) { - if (eph->getEndpoint() == ep) eph->getCallbackInfo()->updateName = true; - } -} - -void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointState state) { - //TODO: Race condition!!!!! - std::vector 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->playbackEndpointHandlers.begin(), this->playbackEndpointHandlers.end()); - EndpointHandler* eph = nullptr; - for (auto loopEph : allHandlers) { - if (loopEph->getId() == endpointId) { - eph = loopEph; - break; - } - } - - //debug - Flows flow; - if (!eph) { - if (state ^ EndpointState::ENDPOINT_ACTIVE) goto end; - //flow = Flows::FLOW_CAPTURE; - eph = osh->addEndpoint(endpointId, &flow); - } else - flow = eph->getFlow(); - - //todo: mic done but disabled. Tab-kun will come... - 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(); - os->playbackMutex.unlock(); - os->captureMutex.unlock(); - os->reportFinishedStateChange(); - return; -} - -void OverseerHandler::setAddEndpointWidgetFunction(std::function addEndpointWidget){ - this->addEndpointWidget = addEndpointWidget; -} - -void OverseerHandler::setRemoveEndpointWidgetFunction(std::function removeEndpointWidget){ - this->removeEndpointWidget = removeEndpointWidget; +NGuid* OverseerHandler::getGuid() { + return this->os.getGuid(); } void OverseerHandler::setEndpointHandlers(std::vector ephs){ - this->playbackEndpointHandlers = ephs; + this->endpointHandlers = ephs; } -void OverseerHandler::lockEndpoints() { - os->playbackMutex.lock(); - os->captureMutex.lock(); +void OverseerHandler::setFrontVolumeCallback(std::function f) { + this->updateFrontVolumeCallback = f; } -void OverseerHandler::unlockEndpoints() { - os->playbackMutex.unlock(); - os->captureMutex.unlock(); +void OverseerHandler::setFrontMuteCallback(std::function f) { + this->updateFrontMuteCallback = f; } +void OverseerHandler::updateMuteCallback(uint64_t idx, bool muted){ + updateFrontMuteCallback(idx, muted); +} + +/* + * void OverseerHandler::updateMainVolumeCallback(uint64_t idx, float newVal){ + * + * } + */ + +void OverseerHandler::updateVolumeCallback(uint64_t idx, uint32_t channel, float newVal){ + if (channel == (uint32_t)AudioChannel::CHANNEL_MAIN) { + log_debugcpp("mainvolcallback float: " << newVal); + updateFrontVolumeCallback(idx, AudioChannel::CHANNEL_MAIN, newVal); + return; + } + + + // convert channel to bitmask + uint32_t i = 0; + while (i < channel) + i++; + uint32_t mask = (1 << i); + + log_debugcpp("Back->Cont Channel: " << mask << " volcallback float: " << newVal); + + updateFrontVolumeCallback(idx, mask, newVal); +} diff --git a/src/cont/contclasses.h b/src/cont/contclasses.h index cd0e03e..320564f 100644 --- a/src/cont/contclasses.h +++ b/src/cont/contclasses.h @@ -1,38 +1,40 @@ #pragma once +#define invoke_mem_fn(object,ptrToMember) ((object).*(ptrToMember)) +#define pinvoke_mem_fn(object,ptrToMember) ((object)->*(ptrToMember)) -#include "global.h" -#include "settings.h" -#include "contsessionclasses.h" -//#define invoke_mem_fn(object,ptrToMember) ((object).*(ptrToMember)) -//#define pinvoke_mem_fn(object,ptrToMember) ((object)->*(ptrToMember)) +/* #ifndef QTBLESSED */ +/* //#define Q_OBJECT */ +/* class QWidget{}; */ +/* class QMainWindow{}; */ +/* #endif */ class EndpointWidget; class Endpoint; -class EndpointVolumeCallback; +class EndpointCallback; class Overseer; -class SessionHandler; -class EndpointNewSessionCallback; -struct BackEndpointVolumeCallbackInfo { - NGuid caller; - bool muted; - float mainVolume; - size_t channels; - std::vector channelVolumes; - bool updateName = false; +enum AudioChannel { + CHANNEL_LEFT = (1 << 0), + CHANNEL_RIGHT = (1 << 1), + CHANNEL_MAIN = ~0, }; -void setConfigDirToDefaults(); +struct NGuid { + uint32_t data1; + uint16_t data2; + uint16_t data3; + unsigned char data4[8]; +}; class EndpointHandler { public: - EndpointHandler(uint64_t idx, Flows flow); - void setBackEndpointVolumeCallbackInfoContent(uint8_t state); + EndpointHandler(uint64_t idx); + //TODO: get(); + Endpoint *ep = nullptr; + EndpointCallback *epc = nullptr; + //std::wstring epName; - //todo: replace all getEndpointHandler() - //todo: name refactor - BackEndpointVolumeCallbackInfo* getCallbackInfo(); uint32_t getChannelCount(); void setIndex(uint64_t idx); @@ -40,129 +42,43 @@ public: void setVolume(int channel, float volume); std::wstring getName(); - void setName(std::wstring newName); - std::wstring getId(); - - void setFrontVisibilityInfo(EndpointState state, uint64_t frontIdx); - uint64_t getFrontVisibilityIndex(); - EndpointState getFrontVisibilityState(); - - Flows getFlow(); float getVolume(int channel); bool getMute(); - size_t getState(); - uint8_t getRoles(); - void setRoles(Roles newRole); - void assignRoles(Roles newRole); - void removeRoles(Roles newRole); - - void setVolume(NGuid guid, int channel, int value); - void setMute(NGuid guid, bool muted); - void setState(EndpointState state); - void setState(EndpointState state, uint64_t idx); - float getPeakVolume(); - /* sessions */ - size_t getSessionCount(); - std::vector getSessionHandlers(); - void createNewSession(); - Endpoint* getEndpoint(); + void setVolume(NGuid* guid, int channel, int value); + void setMute(NGuid* guid, bool muted); - /*Session*/ - void addSessionSendFront(Session* session); - void setAddSessionWidgetFunction(std::function addSessionWidget); - void setRemoveSessionWidgetFunction(std::function removeSessionWidget); - void sendSessionToFront(SessionHandler* sh); - void removeSessionFromFront(SessionHandler* sh); - void deleteSessions(); - void createSessionHandlers(); - void createSessionHandlersCallback(); - std::mutex sessionHandlersMutex; - void lockSessionCollections(); - void unlockSessionCollections(); - void removeVolumeCallback(); - ~EndpointHandler(); private: - std::vector getSessions(); - uint64_t idx; - Endpoint *ep = nullptr; - EndpointVolumeCallback *epc = nullptr; - Flows flow; - BackEndpointVolumeCallbackInfo callbackInfo; - struct EndpointHandlerFrontVisibility { - EndpointState visibility = EndpointState::ENDPOINT_ALL; - uint64_t frontIdx = INT_MAX; - }; - EndpointHandlerFrontVisibility ephfv; - EndpointNewSessionCallback* ensc; - std::vector sessionHandlers; - std::function addSessionWidget; - std::function removeSessionWidget; //QSlider *slidy; + +//signals: + + }; + class OverseerHandler { public: - OverseerHandler(); - static void setSettingsPath(std::string path); - static std::string getSettingsPath(); - static inline std::string settingsPath; - void updateStartupConfig(bool onStartup); - void setStartupConfig(bool onStartup); - void populateSystemValues(); - void openControlPanel(); - ProcessedNativeEvent processTopLevelWindowMessage(void* msg); - bool isLightMode(); - bool isToRunAtStartup(); - uint32_t getAccentColor(); - - //void setChangeFrontDefaultsFunction(std::function changeFrontDefaults); - //void changeFrontDefaultsCallback(Roles role, std::wstring endpointId); - - void roleBucketEntryCallback(Roles role, std::wstring endpointId); - void setRoleBucketEntryFunction(std::function roleBucketEntry); - - void updateFrontEndpointName(Endpoint* ep); - //void setReviseEndpointShowingFunction(std::function reviseEndpointShowing); - void reviseEndpointShowing(std::wstring endpointId, EndpointState state); - void setRemoveEndpointWidgetFunction(std::function removeEndpointWidget); - void setAddEndpointWidgetFunction(std::function addEndpointWidget); - + //OverseerHandler(); void setEndpointHandlers(std::vector ephs); - std::vector getPlaybackEndpointHandlers(); - std::vector getCaptureEndpointHandlers(); + std::vector getEndpointHandlers(); std::vector getPlaybackEndpoints(); - std::vector getCaptureEndpoints(); - void pushBackEndpointHandler(EndpointHandler* eph, Flows flow); uint64_t getPlaybackEndpointsCount(); - uint64_t getCaptureEndpointsCount(); - void createEndpointHandlers(); - EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow); - void reportFinishedStateChange(); - NGuid getGuid(); - - std::mutex handlersPlaybackMutex; - std::mutex handlersCaptureMutex; - void lockEndpoints(); - void unlockEndpoints(); + void reloadEndpointHandlers(); + NGuid* getGuid(); + void updateMuteCallback(uint64_t idx, bool muted); + void setFrontMuteCallback(std::function f); + void setFrontVolumeCallback(std::function f); + //void updateMainVolumeCallback(uint64_t idx, float newVal); + void updateVolumeCallback(uint64_t idx, uint32_t channel, float newVal); private: - Overseer *os; - std::vector playbackEndpointHandlers; - std::vector captureEndpointHandlers; - - std::function changeFrontDefaults; - std::function removeEndpointWidget; - std::function addEndpointWidget; - std::function roleBucketEntry; - - /* Session's */ - std::function changeSessionVolume; - - //std::function updateFrontVolumeCallback; - //std::function updateFrontMuteCallback; + static Overseer os; + std::vector endpointHandlers; + std::function updateFrontVolumeCallback; + std::function updateFrontMuteCallback; }; diff --git a/src/cont/contsessionclasses.cpp b/src/cont/contsessionclasses.cpp deleted file mode 100644 index 0f6caaf..0000000 --- a/src/cont/contsessionclasses.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "contsessionclasses.h" -#include "backsessionclasses.h" - -SessionHandler::SessionHandler(EndpointHandler* eph, Session* session, size_t idx) { - this->eph = eph; - this->idx = idx; - this->session = session; - - this->svi.mainVolume = session->getVolume(AudioChannel::CHANNEL_MAIN); - this->svi.muted = session->getMute(); - this->svi.caller = osh->getGuid(); - - ssc = new SessionStateCallback(this); - this->session->setStateCallback(ssc); -} - -void SessionHandler::setVolume(NGuid guid, int channel, int value){ - if (channel == AudioChannel::CHANNEL_MAIN) - session->setVolume(guid, channel, (float)value / 100); - else session->setVolume(guid, channel, (float)value / 100); -} - -float SessionHandler::getVolume(int channel){ - return session->getVolume(channel); -} - -void SessionHandler::setMute(NGuid guid, bool muted){ - session->setMute(guid, muted); -} - -std::wstring SessionHandler::getName(){ - return session->getName(); -} - -void SessionHandler::setName(std::wstring newName){ - session->setName(newName); -} - -float SessionHandler::getPeakVolume(){ - return session->getPeakVolume(); -} - -bool SessionHandler::getMute(){ - return session->getMute(); -} - -void SessionHandler::setFrontIndex(uint64_t frontIdx) { - this->frontIdx = frontIdx; -} - -uint64_t SessionHandler::getFrontIndex() { - return frontIdx; -} - -SessionVolumeInfo* SessionHandler::getVolumeInfo() { - return &svi; -} - -SessionState SessionHandler::getState() { - return session->getState(); -} - -void SessionHandler::setState(SessionState state) { - session->setState(state); -} - -void SessionHandler::reviseSessionShowing(SessionState state) { - SessionState currentState = this->getState(); - switch (currentState) { - case SessionState::ACTIVE: - case SessionState::INACTIVE: - if (state == SessionState::EXPIRED) { - eph->removeSessionFromFront(this); - } - break; - case SessionState::EXPIRED: - if (state == SessionState::ACTIVE || INACTIVE) { - eph->sendSessionToFront(this); - } - break; - case SessionState::DISCONNECTED: - if (frontIdx != INT_MAX) - eph->removeSessionFromFront(this); - break; - } -} - -SessionHandler::~SessionHandler() { - session->removeStateCallback(ssc); - ssc->Release(); -} diff --git a/src/cont/contsessionclasses.h b/src/cont/contsessionclasses.h deleted file mode 100644 index 24c0ba7..0000000 --- a/src/cont/contsessionclasses.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "global.h" -//#include "contclasses.h" - -class EndpointHandler; -class Session; -class SessionStateCallback; - -struct SessionVolumeInfo { - //SessionVolumeInfo(bool muted, float mainVolume); - bool muted; - float mainVolume; - NGuid caller; - std::atomic isNameChanged = false; - //size_t channels; - //std::vector channelVolumes; -}; - -class SessionHandler { - public: - SessionHandler(EndpointHandler* eph, Session* session, size_t idx); - void setVolume(NGuid guid, int channel, int value); - float getVolume(int channel); - void setMute(NGuid guid, bool muted); - bool getMute(); - void setFrontIndex(uint64_t frontIdx); - SessionState getState(); - void setState(SessionState state); - uint64_t getFrontIndex(); - std::wstring getName(); - float getPeakVolume(); - void setName(std::wstring newName); - void reviseSessionShowing(SessionState state); - SessionVolumeInfo* getVolumeInfo(); - ~SessionHandler(); - private: - SessionVolumeInfo svi; - EndpointHandler* eph; - Session* session; - SessionStateCallback* ssc; - size_t idx; - uint64_t frontIdx = INT_MAX; -}; diff --git a/src/debug.h b/src/debug.h index 61855c1..e80893f 100644 --- a/src/debug.h +++ b/src/debug.h @@ -2,85 +2,28 @@ #if defined (QT_DEBUG) || defined (DEBUG) || defined (_DEBUG) -#define PIPE_NAME "Mixerq-dev" - -#ifdef INIT_FILELOG - std::wstring_convert, wchar_t> converter; - FILE* fileLog; - errno_t lfResult; - bool writable = false; - - void inline initializeFileLogging() { - lfResult = fopen_s(&fileLog, "log.txt", "w"); - if (!lfResult) writable = true; - else writable = false; - } - -#else - extern std::wstring_convert, wchar_t> converter; - extern errno_t lfResult; - extern FILE* fileLog; - extern bool writable; - extern bool initializeFileLogging(); -#endif - -#define initialize_file_log() initializeFileLogging() - -template -std::bitset varToBitset(T info) { - std::bitset content(info); +template +std::bitset varToBitset(T info) { + std::bitset content(info); return content; -} +} -#define print_as_binary(info) varToBitset(info).to_string() - -#ifndef _WIN32 #define log_debugcpp(str) do { \ std::cout << "[DEBUG]" << "(" << __FILE__ << ":" << __LINE__ << "): " << str << std::endl; \ } while (0) -#define log_wdebugcpp(str) do { \ - std::wcout << "[DEBUG]" << "(" << __FILE__ << ":" << __LINE__ << "): " << str << std::endl; \ - } while (0) - -#else - -#include -#include -#define WIDE2(x) L##x -#define WIDE1(x) WIDE2(x) -#define WFILE WIDE1(__FILE__) -#define log_debugcpp(str) { \ - OutputDebugStringA(std::string("[DEBUG] (" + std::string(__FILE__) + ":" + std::to_string(__LINE__) + "): " + std::string(str) + "\n").c_str()); \ - } while (0) - -#define log_wdebugcpp(str) do { \ - OutputDebugStringW(std::wstring(L"[DEBUG] (" + std::wstring(WFILE) + L":" + std::to_wstring(__LINE__) + L"): " + std::wstring(str) +L"\n").c_str()); \ - } while (0) - -#endif //_WIN32 - -#define log_to_file(fmt, cnt...) do { \ - if(writable) fprintf_s(fileLog, fmt,##cnt); \ -} while (0) - -#define close_file_log_buffer() do { \ - if(writable) { fflush(fileLog); fclose(fileLog); } \ -} while (0) +#define print_as_binary(len, type, info) varToBitset(info) #else #define log_debugcpp(str) -#define log_wdebugcpp(str) -#define print_as_binary(info) -#define log_to_file(fmt, cnt...) -#define initialize_file_log() false -#define close_file_log_buffer() -#define PIPE_NAME "Mixerq" -#endif //DEBUG +#define print_as_binary(len, type, info) +#endif /* Here as a quick reference, in case smthn similar is needed again */ /* typedef void (EndpointWidget::*epwMuteFunc)(bool muted); */ -/* Typedef void (EndpointWidget::*epwMainVolumeFunc)(float newValue); */ +/* typedef void (EndpointWidget::*epwMainVolumeFunc)(float newValue); */ /* typedef void (EndpointWidget::*epwChannelVolumeFunc)(uint32_t channel, float newValue); */ /* typedef void (EndpointWidget::*epwToggleFrontFunc)(bool active); */ + + diff --git a/src/global.h b/src/global.h index 8799892..c4cf2af 100644 --- a/src/global.h +++ b/src/global.h @@ -1,117 +1,20 @@ #pragma once -#define __STDC_WANT_LIB_EXT1__ 1 -#include -#include -#include -#include #include #include #include #include -#include -#include -#include -#include #include "debug.h" -//#include "settings.h" -//TODO: Use tr();? QTranslator -#define APP_NAME "MixerQ" -#define LAPP_NAME L"MixerQ" +#define ENDPOINT_MASTER_VOLUME -1 +/* #define ENDPOINT_LEFT_CHANNEL_VOLUME 0 */ +/* #define ENDPOINT_RIGHT_CHANNEL_VOLUME 1 */ #define STRING_MUTE "Mute" #define STRING_UNMUTE "Unmute" -#define STRING_QUIT "Quit" -#define STRING_TITLE "Mixer Fachero" - -#define STRING_ROLE_CONSOLE "Console" -#define STRING_ROLE_MULTIMEDIA "Multimedia" -#define STRING_ROLE_COMMUNICATIONS "Communications" -#define STRING_ROLE_ALL "All" - -#define STRING_SYSTEM_SOUNDS "System Sounds" -#define LSTRING_SYSTEM_SOUNDS L"System Sounds" - -#define STRING_CP "Open Control Panel" -#define STRING_ABOUT "About" -#define STRING_STARTUP "Run at startup" -#define STRING_CHANNELS "Show endpoint channels" - -#define STRING_NOENDPOINT "No active endpoints" - -#define LSTRING_UNNAMED_SESSION L"Unnamed session" - //INIT BACK -enum SettingsTargetDirectory { - HOME_DIR = 0, - APP_PATH = (1 << 0), - CUSTOM = (1 << 1), -}; - -enum ProcessedNativeEvent { - NONE = 0, - COLORS = (1 << 0), -}; - -enum AudioChannel { - CHANNEL_LEFT = (1 << 0), - CHANNEL_RIGHT = (1 << 1), - CHANNEL_MAIN = ~0, -}; - -enum EndpointState { - ENDPOINT_ACTIVE = (1 << 0), - ENDPOINT_DISABLED = (1 << 1), - ENDPOINT_NOTPRESENT = (1 << 2), - ENDPOINT_UNPLUGGED = (1 << 3), - ENDPOINT_ALL = 0x0F -}; - -enum SessionState { - ACTIVE = (1 << 0), - INACTIVE = (1 << 1), - EXPIRED = (1 << 2), - DISCONNECTED = (1 << 3), - ALL = 0x0F -}; - -enum Flows { - FLOW_PLAYBACK = (1 << 0), - FLOW_CAPTURE = (1 << 1), - FLOW_BOTH = (1 << 2), -}; - -enum Roles { - ROLE_CONSOLE = (1 << 0), - ROLE_MULTIMEDIA = (1 << 1), - ROLE_COMMUNICATIONS = (1 << 2), - ROLE_ALL = 0x07, -}; - -struct NGuid { - //todo: still leaking? - uint32_t data1; - uint16_t data2; - uint16_t data3; - unsigned char data4[8]; - - - /* void freeData4(){ */ - /* int i = 0; */ - /* do{ */ - /* if(this->data4 + i != nullptr) free(data4 + i); */ - /* i++; */ - /* }while (i < 8); */ - /* } */ -}; -namespace ini { - class UserSettings; -} - -extern ini::UserSettings *set; class OverseerHandler; extern OverseerHandler *osh; diff --git a/src/qt/meterslider.h b/src/qt/meterslider.h deleted file mode 100644 index a59e16e..0000000 --- a/src/qt/meterslider.h +++ /dev/null @@ -1,19 +0,0 @@ -#include - -class MeterSlider : public QSlider { - Q_OBJECT -private: - ~MeterSlider(); - float peakValue; - - friend class MixerStyle; -protected: - bool event(QEvent* ev) override; - void paintEvent(QPaintEvent *event) override; - -public: - //MeterSlider(Qt::Orientation orientation, QWidget *parent = nullptr); - //MeterSlider(QWidget* parent = nullptr) : MeterSlider(Qt::Vertical, parent){}; - void setPeakValue(float peakValue); - using QSlider::QSlider; -}; diff --git a/src/qt/qtclasses.cpp b/src/qt/qtclasses.cpp index a9148b9..155cd90 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -1,1401 +1,202 @@ #include "qtclasses.h" -#include "meterslider.h" - -#define POLLING_RATE 2 - -bool DarkModeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) { - if (eventType == "windows_generic_MSG") { - ProcessedNativeEvent event = osh->processTopLevelWindowMessage(message); - switch(event) { - case COLORS: - StylingHelper::setBackgroundColor(osh->isLightMode()); - - //Update accent color across entire app - { - uint32_t color = osh->getAccentColor(); - uint8_t r, g, b, a; - if (StylingHelper::argbToDiscreteValues(osh->getAccentColor(), &r, &g, &b, &a)) { - const QWidgetList topLevelWidgets = QApplication::topLevelWidgets(); - for (QWidget *widget : topLevelWidgets) { - if(qobject_cast(widget)) { - ((MainWindow*)widget)->updateColor(r, g, b, a); - } - } - } - } - return true; - break; - default: - break; - } - } - return false; -} - -template -CustomWidgetEvent::CustomWidgetEvent(QEvent::Type type, T payload) : QEvent(type){ - this->payload = payload; -} /* - * MeterSlider::MeterSlider(Qt::Orientation orientation, QWidget* parent) { - * //style = new MixerStyle(); - * //this->setStyle(style); + * ToggleButton::ToggleButton(QWidget *parent) : QAbstractButton(parent) { + * this->setCheckable(true); + * } + * + * ToggleButton::~ToggleButton(){ + * + * } + * + * void ToggleButton::checkStateSet(){ } + * + * bool hitButton(const QPoint &pos) { + * * } */ - -MeterSlider::~MeterSlider() { - //delete style; -} - -void MeterSlider::setPeakValue(float peakValue) { - this->peakValue = peakValue; -} - -bool MeterSlider::event(QEvent* ev) { - if (ev->type() == QEvent::Wheel) { - ev->setAccepted(false); - return false; - } - return QSlider::event(ev); -} - -void MeterSlider::paintEvent(QPaintEvent *event) { - QStyleOptionSlider sliderComplex = QStyleOptionSlider(); - sliderComplex.initFrom(this); - - /* - * sliderComplex.initFrom(this); - * sliderComplex.subControls = QStyle::SC_None; - * sliderComplex.activeSubControls = QStyle::SC_None; - * sliderComplex.orientation = this->orientation(); - * sliderComplex.maximum = this->maximum(); - * sliderComplex.minimum = this->minimum(); - * sliderComplex.tickPosition = (QSlider::TickPosition)this->tickPosition(); - * sliderComplex.tickInterval = this->tickInterval(); - * sliderComplex.upsideDown = (this->orientation() == Qt::Horizontal) ? - * (this->invertedAppearance() != (sliderComplex.direction == Qt::RightToLeft)) - * : (!this->invertedAppearance()); - * sliderComplex.direction = Qt::LeftToRight; // we use the upsideDown option instead - * sliderComplex.sliderPosition = this->sliderPosition(); - * sliderComplex.sliderValue = this->value(); - * sliderComplex.singleStep = this->singleStep(); - * sliderComplex.pageStep = this->pageStep(); - * if (this->orientation() == Qt::Horizontal) - * sliderComplex.state |= QStyle::State_Horizontal; - * - * if (this->isSliderDown()) { - * sliderComplex.activeSubControls = QStyle::SC_SliderHandle; - * sliderComplex.state |= QStyle::State_Sunken; - * } else { - * sliderComplex.activeSubControls = QStyle::SC_SliderHandle; - * } - * - * //sliderComplex.subControls = QStyle::SC_SliderGroove; - * if (this->tickPosition() != NoTicks) sliderComplex.subControls |= QStyle::SC_SliderTickmarks; - * QStylePainter p(this); - */ - //p.drawComplexControl(QStyle::CC_Slider, sliderComplex); - - - - QStyleOptionSlider sliderComplex2 = QStyleOptionSlider(); - sliderComplex2.initFrom(this); - sliderComplex2.orientation = this->orientation(); - sliderComplex2.maximum = this->maximum(); - sliderComplex2.minimum = this->minimum(); - sliderComplex2.tickPosition = (QSlider::TickPosition)this->tickPosition(); - sliderComplex2.tickInterval = this->tickInterval(); - sliderComplex2.upsideDown = (this->orientation() == Qt::Horizontal) ? - (this->invertedAppearance() != (sliderComplex2.direction == Qt::RightToLeft)) - : (!this->invertedAppearance()); - sliderComplex2.subControls = QStyle::SC_SliderHandle; - sliderComplex2.direction = Qt::LeftToRight; // we use the upsideDown option instead - sliderComplex2.sliderPosition = this->sliderPosition(); - sliderComplex2.sliderValue = this->value(); - sliderComplex2.singleStep = this->singleStep(); - sliderComplex2.pageStep = this->pageStep(); - if (this->orientation() == Qt::Horizontal) - sliderComplex2.state |= QStyle::State_Horizontal; - - if (this->isSliderDown()) { - sliderComplex2.activeSubControls = QStyle::SC_SliderHandle; - sliderComplex2.state |= QStyle::State_Sunken; - } else { - sliderComplex2.activeSubControls = QStyle::SC_SliderHandle; - } - - sliderComplex2.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle; - if ((QSlider::TickPosition)this->tickPosition() != NoTicks) - sliderComplex2.subControls |= QStyle::SC_SliderTickmarks; - - QPainter painter(this); - QStyle* style = QApplication::style(); - style->drawComplexControl((QStyle::ComplexControl)CC_MeterSlider, &sliderComplex2, &painter, this); - - - //Q_D(QSlider); - /* - * QStylePainter p(this); - * QStyleOptionSlider opt; - * initStyleOption(&opt); - * - * opt.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle; - * //if (d->tickPosition != NoTicks) - * // opt.subControls |= QStyle::SC_SliderTickmarks; - * - * //p.drawComplexControl(QStyle::CC_Slider, opt); - */ - //QSlider::paintEvent(event); - - //IL CODE WENO lbockomet - /* - * int left = 0, top = 0, right = 0, bottom = 0; - * ((QWidget*)parent())->layout()->getContentsMargins(&left, &top, &right, &bottom); - * - * QStyle *style = QApplication::style(); - * //int lol = style->pixelMetric(QStyle::PM_SliderSpaceAvailable); - * QPainter painter(this); - * //painter.setPen(Qt::blue); - * painter.setOpacity(1.0); - * painter.setClipping(false); - * painter.setCompositionMode(QPainter::CompositionMode::CompositionMode_Source); - * float peakLength = (this->width() * (this->peakValue)); - * double stepWidth = (double)this->width() * ((double)this->singleStep() / (this->maximum() - this->minimum())); - * //Fusion seems to fuck around with bar's height and width - * //const qreal dpr = painter->device()->devicePixelRatio(); - * //QStyleOptionSlider sliderComplex = QStyleOptionSlider(); //slider.initFrom(this); - * QRect sliderSize = style->subControlRect(QStyle::CC_Slider, (QStyleOptionComplex*)&sliderComplex, QStyle::SC_SliderHandle); - * int handleCenterPos = QStyle::sliderPositionFromValue(this->minimum(), this->maximum(), this->value(), this->width()); - * int unattenuatedPeakMeter = ((this->width() * this->peakValue) >= handleCenterPos - (sliderSize.width() / 2)) - * ? this->width() - (sliderSize.width() / 2) - * : this->width() * this->peakValue; - * //QApplication::style()->subControlRect(QStyle::CC_Slider, (QStyleOptionComplex*)&slider, QStyle::SC_SliderHandle); - * painter.fillRect(0, (this->height() / 2) - 3, this->width(), - * 4, Qt::white); - * painter.fillRect(0, (this->height() / 2) - 3, this->width() * this->peakValue, - * 4, Qt::gray); - * painter.fillRect(0, (this->height() / 2) - 3, (this->width() - ((this->maximum() - this->value()) * stepWidth)) * this->peakValue, - * 4, Qt::green); - * // - ((this->maximum() - this->value()) * stepWidth)) - * //double ratio = ; - * double handleShift = (double)((sliderSize.width() * ((double)(this->maximum() - this->value()) / 100))); - * painter.fillRect((this->width() - ((this->maximum() - this->value()) * stepWidth)) - (sliderSize.width()) + handleShift, top / 2, sliderSize.width(), sliderSize.height() - bottom, Qt::magenta); - * //sliderComplex.subControls = QStyle::SC_SliderHandle; - * //p.drawComplexControl(QStyle::CC_Slider, sliderComplex); - */ -} - -void ExtendedCheckBox::customEvent(QEvent* ev) { - //QEvent::Type tipo = ev->type(); - if (ev->type() == (QEvent::Type)CustomQEvent::EndpointDefaultChange) { - //todo: still prone to bugs; whack-a-mole to come - ev->setAccepted(true); - this->blockSignals(true); - if (this->isEnabled()) { - this->setCheckState(Qt::Checked); - this->setDisabled(true); - } else { - this->setDisabled(false); - this->setCheckState(Qt::Unchecked); - } - this->blockSignals(false); - return; - } - // Make sure the rest of events are handled - QCheckBox::customEvent(ev); -} - -void ExtendedCheckBox::paintEvent(QPaintEvent *event) { - QStylePainter p(this); - QStyleOptionButton opt; - initStyleOption(&opt); - opt.icon = this->icons; - p.drawControl((QStyle::ControlElement)CustomControlElement::CE_ExtendedCheckBox, opt); - //QStyle* style = QApplication::style(); - //style->drawComplexControl((QStyle::ComplexControl)CC_MeterSlider, &sliderComplex2, &painter, this); -} - -void ExtendedCheckBox::addIcon(char* const path, QIcon::State state) { - QString str(path); - QSvgRenderer rr(str); - QPixmap pixmap(64, 64); - pixmap.fill(Qt::transparent); - QPainter painter(&pixmap); - rr.render(&painter); - painter.setCompositionMode(QPainter::CompositionMode_SourceIn); - uint8_t a, r, g, b; - if (StylingHelper::argbToDiscreteValues(osh->getAccentColor(), &r, &g, &b, &a)) { - QColor color(r, g, b, a); - painter.fillRect(pixmap.rect(), color); - } - painter.end(); - icons.addPixmap(pixmap, QIcon::Normal, state); - //this->setIcon(icons); - //icons.addFile(":/Icons/images/second.svg",QSize(32,32),QIcon::Normal,QIcon::Off); -} - - -QRect MainWindow::setSizePosition(QScreen* screen, int width, int height) { - //setGeometry ignores decoration size, theres others for that - QRect trayIconPos = this->trayIcon->geometry(); - int tix1, tix2, tiy1, tiy2; - trayIconPos.getCoords(&tix1, &tiy1, &tix2, &tiy2); - log_debugcpp("Tray Icon Pos: " + std::to_string(tix1) + " " + std::to_string(tix2)+" " + std::to_string(tiy1) + " " + std::to_string(tiy2)); - - this->setScreen(screen); - - QRect screenRes = screen->geometry(); - int srx1, srx2, sry1, sry2; - screenRes.getCoords(&srx1, &sry1, &srx2, &sry2); - log_debugcpp("Screen Res: " + std::to_string(srx1) + " " + std::to_string(srx2)+" " + std::to_string(sry1) + " " + std::to_string(sry2)); - - QRect availableRes = screen->availableGeometry(); - int arx1, arx2, ary1, ary2; - availableRes.getCoords(&arx1, &ary1, &arx2, &ary2); - log_debugcpp("Available res: " + std::to_string(arx1) + " " + std::to_string(arx2)+" " + std::to_string(ary1) + " " + std::to_string(ary2)); - - if(height > (ary2 - ary1)) height = (ary2 - ary1); - log_debugcpp("Height res: " + std::to_string(height)); - - uint8_t pos = 0; - int leftDistance = std::abs(srx1 - tix1); - int rightDistance = std::abs(srx2 - tix1); - int upDistance = std::abs(sry1 - tiy1); - int downDistance = std::abs(sry2 - tiy1); - - pos = (upDistance < downDistance) ? SpawnPos::UP : SpawnPos::DOWN; - pos = (leftDistance < rightDistance) ? pos | SpawnPos::LEFT : pos | SpawnPos::RIGHT; - - switch (pos) { - case SpawnPos::UP | SpawnPos::RIGHT: - this->addToolBar(Qt::BottomToolBarArea, mainMenuBar); - return QRect((arx2 - width + 1), ary1, width, height); - break; - case SpawnPos::DOWN | SpawnPos::LEFT: - this->addToolBar(Qt::TopToolBarArea, mainMenuBar); - return QRect(arx1, (ary2 - height + 1), width, height); - break; - case SpawnPos::DOWN | SpawnPos::RIGHT: - this->addToolBar(Qt::TopToolBarArea, mainMenuBar); - return QRect((arx2 - width + 1), (ary2 - height + 1), width, height); - break; - default: - this->addToolBar(Qt::BottomToolBarArea, mainMenuBar); - log_debugcpp("Failed positioning window"); - return QRect(500, 400, width, height); - break; - } -} - -void MainWindow::updateColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - QColor color(r, g, b, a); - QPalette pal = QPalette(color); - pal.setColor(QPalette::Highlight, color); - scrollArea->verticalScrollBar()->setPalette(pal); -} - -void MainWindow::compose(bool isVisible) { - //We need dynamically added child widgets to expand so that we know their height - this->setUpdatesEnabled(false); - uint64_t windowWidth; - uint64_t screenHeight; - uint64_t windowHeight; - /* - * Setting correct widget widths and heights - */ - log_to_file("[Compose]\n"); - screen = StylingHelper::getCurrentScreen(); - log_debugcpp("Screen: " + screen->model().toStdString() + " " + screen->name().toStdString()); - - QRect screenRes = screen->geometry(); - int srx1, srx2, sry1, sry2; - screenRes.getCoords(&srx1, &sry1, &srx2, &sry2); - log_debugcpp("(for Percentage) Screen Res: " + std::to_string(srx1) + " " + std::to_string(srx2)+" " + std::to_string(sry1) + " " + std::to_string(sry2)); - - windowWidth = (((uint64_t)std::abs(screenRes.width())) * widthRatio); - screenHeight = (uint64_t)std::abs(screenRes.height()); - log_debugcpp("Window Width: " + std::to_string(windowWidth)); - log_to_file("Window Width: %d \n", windowWidth); - this->scrollArea->setMaximumWidth((int)windowWidth); - this->scrollArea->setMinimumWidth((int)windowWidth); - this->mainMenuBar->setMinimumWidth((int)windowWidth); - this->mainMenuBar->setMaximumWidth((int)windowWidth); - - this->createLayout(new QGridLayout()); - for (auto *epw : ews) { - if (!epw) continue; - epw->updateChannelsVisibility(); - epw->calculateSize(windowWidth - scrollArea->verticalScrollBar()->sizeHint().width() - - widgetLayout->contentsMargins().left() - , screenHeight); - log_debugcpp("epw loop"); - log_debugcpp("epw roles: " + print_as_binary((epw->getEndpointHandler()->getRoles()))); - //std::bitset content = - //content); - //varToBitset(epw->getEndpointHandler()->getRoles()); - } - - /* - * Calculating window height - */ - windowHeight = 0; - int left = 0, top = 0, right = 0, bottom = 0; - for (int i = 0; i < 2; i++) { - if (!ews[i]) continue; - ews[i]->layout()->getContentsMargins(&left, &top, &right, &bottom); - windowHeight += ews[i]->sizeHint().height(); - windowHeight += top * 3; - log_debugcpp("windowHeight loop: " + std::to_string(windowHeight)); - } - windowHeight += mainMenuBar->sizeHint().height(); - log_debugcpp("windowHeight final value: " + std::to_string(windowHeight)); - - this->setUpdatesEnabled(true); - if (!isVisible) { - /* - * Undoing scrolling - */ - scrollArea->verticalScrollBar()->setValue(0); - /* - * Establishing initial window size and position - */ - setGeometry(setSizePosition(screen, windowWidth, windowHeight)); - } -} - -QScreen* MainWindow::getCurrentScreen() { - //note: Using cursor pos as screen detector. Flawed. - QPoint cursorPos = QCursor::pos(); - log_debugcpp("Cursor pos: " + std::to_string(cursorPos.ry()) + " " + std::to_string(cursorPos.rx())); - - for (QScreen *screen : QGuiApplication::screens()) { - QRect screenRect = screen->geometry(); - if (screenRect.contains(cursorPos)) { - return screen; - } - } - - return QGuiApplication::primaryScreen(); -} - -SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent) : QWidget(parent) { - //todo: based on qgridlayout, name+mute should be its own widget, same with channels - this->idx = idx; - this->sh = sh; - - this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - widgetLayout = new QHBoxLayout(this); - //widgetLayout->setSizeConstraint(QLayout::SetFixedSize); - widgetLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); - int left = 0, top = 0, right = 0, bottom = 0; - widgetLayout->getContentsMargins(&left, &top, &right, &bottom); - widgetLayout->setContentsMargins(0, top, 0, bottom); - - muteButton = new ExtendedCheckBox(this); - muteButton->addIcon(":/assets/mute.svg", QIcon::On); - muteButton->addIcon(":/assets/unmute.svg", QIcon::Off); - mainLabel = new QLabel(QString::fromStdWString(sh->getName()), this); - mainLabel->setToolTip(QString::fromStdWString(sh->getName())); - mainSlider = new MeterSlider(Qt::Horizontal, this); - - //mainLabel->setMaximumWidth(150 /*1/16ish 1080p*/); - //mainLabel->setMinimumWidth(150 /*1/16ish 1080p*/); - mainLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - - mainSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - //mainSlider->setMinimumWidth(120 /*1/16 1080p*/); - mainSlider->setFocusPolicy(Qt::StrongFocus); - //mainSlider->setTickPosition(QSlider::TicksBothSides); - //mainSlider->setTickInterval(5); - mainSlider->setSingleStep(1); - mainSlider->setRange(0,100); - - muteButton->setCheckState((sh->getMute() == false ? Qt::Unchecked : Qt::Checked)); - muteButton->setText(sh->getMute() ? STRING_UNMUTE : STRING_MUTE); - //muteButton->setMaximumWidth(60 /*1/32th 1080p*/); - //muteButton->setMinimumWidth(60 /*1/32th 1080p*/); - float volume = sh->getVolume(AudioChannel::CHANNEL_MAIN) * 100; - mainSlider->setValue((int)volume); - log_debugcpp("SESSION SET WITH VOLUME " + std::to_string(volume)); - - //tip: would need to be new widget with layout in it - widthSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum); - widgetLayout->addItem(widthSpacer); - widgetLayout->addWidget(mainLabel, Qt::AlignLeft | Qt::AlignBottom); - widgetLayout->addWidget(muteButton, Qt::AlignRight | Qt::AlignBottom); - widgetLayout->addWidget(mainSlider, Qt::AlignRight | Qt::AlignBottom); - - //widgetLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); - - //TODO:0 = mute and muted, change volume = unmuted are client side tricks = 2 callbacks, one for volume, one for mute state. Implement as an user selectable option? - connect(mainSlider, &QSlider::valueChanged, this,&SessionWidget::updateMainVolume); - connect(muteButton, &QCheckBox::stateChanged, this, (&SessionWidget::updateMute)); - - /* - * Session Volume Polling - */ - volumePoller = new QTimer(this); - connect(volumePoller, &QTimer::timeout, [this, sh](){ - //if (memcmp(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)) == 0) return; CHECK IF THIS PROGRAM GENERATED THE FUNSIES IS NO LONGER IN USE FOR NOW. - //todo: global + constexpr + ratio - 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); - muteButton->blockSignals(true); - mainSlider->setValue((int)((sh->getVolumeInfo()->mainVolume + roundingFactor) * 100)); - mainSlider->setPeakValue(sh->getPeakVolume()); - mainSlider->update(); - //log_wdebugcpp(L"Session: " + sh->getName() + L" peak value: " + std::to_wstring(sh->getPeakVolume())); - muteButton->setCheckState((sh->getVolumeInfo()->muted == false ? Qt::Unchecked : Qt::Checked)); - muteButton->setText(sh->getVolumeInfo()->muted ? STRING_UNMUTE : STRING_MUTE); - //memcpy(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)); - - //TODO: el default = objcopy frees? - //Todo: like fr pregunta - sh->getVolumeInfo()->caller = osh->getGuid(); - mainSlider->blockSignals(false); - muteButton->blockSignals(false); - }); - volumePoller->start(POLLING_RATE); -} - -void SessionWidget::calculateSize(uint64_t width, uint64_t height) { - /* og 1080p 120% testing values */ - this->mainLabel->setMaximumWidth((int)(width * 0.30) /*1/16ish 1080p*/); - this->mainLabel->setMinimumWidth((int)(width * 0.30) /*1/16ish 1080p*/); - //this->mainLabel->setMaximumHeight((int)(height * 0.02)); - this->mainLabel->setMinimumHeight((int)(height * 0.02)); - this->muteButton->setMaximumWidth((int)(width * 0.10) /*1/32th 1080p*/); - this->muteButton->setMinimumWidth((int)(width * 0.10) /*1/32th 1080p*/); - //this->muteButton->setMinimumWidth((int)(width * 0.10) /*1/16 1080p*/); - this->mainSlider->setMinimumWidth((int)(width * 0.30) /*1/16 1080p*/); - widthSpacer->changeSize((int)(width * 0.20), 1, QSizePolicy::Expanding, QSizePolicy::Minimum /*200*/); - - log_to_file("\t[Session %s sizes]\n", converter.to_bytes(this->getName()).c_str()); - log_to_file("\tMain label Maximum size: %d, %d \n", mainLabel->maximumWidth(), mainLabel->maximumHeight()); - log_to_file("\tMain label Minimum size: %d, %d \n", mainLabel->minimumWidth(), mainLabel->minimumHeight()); - log_to_file("\tMute btn Maximum width: %d \n", muteButton->maximumWidth()); - log_to_file("\tMute btn Minimum width: %d \n", muteButton->minimumWidth()); - log_to_file("\tSlider Minimum width: %d \n", mainSlider->minimumWidth()); - log_to_file("\tSlider Maximum width: %d \n", mainSlider->maximumWidth()); - log_to_file("\tSpacer Minimum width: %d \n", widthSpacer->minimumSize().width()); - log_to_file("\tSpacer Maximum width: %d \n\n", widthSpacer->maximumSize().width()); -} - -std::wstring SessionWidget::getName() { - return sh->getName(); -} - -void SessionWidget::updateMute(int checked){ - bool muted = (checked == 2 ? true : false); - this->sh->setMute(osh->getGuid(), muted); - this->muteButton->setText(this->sh->getMute() ? STRING_UNMUTE : STRING_MUTE); -} - -void SessionWidget::updateMainVolume(int newValue){ - this->sh->setVolume(osh->getGuid(), AudioChannel::CHANNEL_MAIN, newValue); -} - -SessionWidget::~SessionWidget() { - volumePoller->stop(); - // volumePoller; -} - -ChannelWidget::ChannelWidget(uint32_t channelCount, EndpointHandler* eph, QWidget *parent) : QWidget(parent){ +EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent) : QWidget(parent){ this->eph = eph; - this->channelCount = channelCount; - this->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); - widgetLayout = new QGridLayout(this); - float volume = 100; - int left = 0, top = 0, right = 0, bottom = 0; - widgetLayout->getContentsMargins(&left, &top, &right, &bottom); - widgetLayout->setContentsMargins(0, top, 0, bottom); - - /* - * Channel sliders setup - */ - //uint32_t epChannelCount = eph->getChannelCount(); - for(uint64_t channel = 0, col = 0, row = 0; channel < channelCount && channelCount > 1; channel++){ - MeterSlider* tmp = new MeterSlider(Qt::Horizontal); - QLabel* tmpLb = new QLabel(""); - //tmp->setTickInterval(5); - tmp->setSingleStep(1); - tmp->setRange(0,100); + layout = new QGridLayout(); + this->setLayout(layout); + log_debugcpp("olaW"); + if (parent == nullptr) { log_debugcpp("owo?"); } - volume = eph->getVolume(channel) * 100; - tmp->setValue((int) volume); - tmpLb->setText(QString::number(volume)); - //tmpLb->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - //tmp->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - //mainSlider->setFocusPolicy(Qt::StrongFocus); - tmpLb->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - this->channelSliders.push_back(tmp); - this->channelLabels.push_back(tmpLb); - widgetLayout->addWidget(tmp, row , col); - widgetLayout->addWidget(tmpLb, row + 1, col++); - if(channel % 2 != 0) { row += 2; col = 0; } - - //TODO: check if there's a need to prevent deadlocks; probably this will eventually turn into its own func - //this causes channel bar desync when back -> front. blocksignals below fix it. huh. - connect(tmp, &QSlider::valueChanged, [this, channel](int newValue){ - this->eph->setVolume(osh->getGuid(), channel, newValue); - this->channelLabels.at(channel)->setText(QString::number(newValue)); - }); - } - this->setLayout(widgetLayout); -} - -void ChannelWidget::updateChannel(int channel) { - this->channelSliders.at(channel)->blockSignals(true); - this->channelSliders.at(channel)->setValue((int)((eph->getCallbackInfo()->channelVolumes[channel] + roundingFactor) * 100)); - this->channelLabels.at(channel)->setText(QString::number((int)((eph->getCallbackInfo()->channelVolumes[channel] + roundingFactor) * 100))); - this->channelSliders.at(channel)->blockSignals(false); -} - -uint32_t ChannelWidget::getChannelCount() const { - return channelCount; -} - -EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t idx) : QWidget(parent) { - //todo: based on qgridlayout, name+mute should be its own widget, same with channels - row = 0; - this->idx = idx; - this->eph = eph; - - eph->createSessionHandlers(); - //todo: sussy - this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ACTIVE, idx); - this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - widgetLayout = new QGridLayout(this); - //this->setContentsMargins(0, 0, 0, 0); - //this->setLayout(widgetLayout); - log_debugcpp("epw main layout parent: " + std::to_string((intptr_t)(widgetLayout->parent()))); - if (parent == nullptr) { log_debugcpp("ayooooo?"); } - - defaultRolesCheckBoxes = { - {Roles::ROLE_ALL, new ExtendedCheckBox(this)}, - {Roles::ROLE_CONSOLE, new ExtendedCheckBox(this)}, - {Roles::ROLE_MULTIMEDIA, new ExtendedCheckBox(this)}, - {Roles::ROLE_COMMUNICATIONS, new ExtendedCheckBox(this)} - }; - - /* - * Mute, main slider and label setup - */ - muteButton = new QCheckBox(this); - mainLabel = new QLabel(QString::fromStdWString(eph->getName()), this); - mainSlider = new MeterSlider(Qt::Horizontal, this); - mainVolumeLabel = new QLabel(this); - - if (this->eph->getState() != EndpointState::ENDPOINT_ACTIVE) { - widgetLayout->addWidget(mainLabel, row, 0); - //widgetLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 1, 0); - return; - } - - //mainLabel->setMaximumWidth(350 /* 1080p 120%*/); - //mainLabel->setMinimumWidth(350 /* 1080p 120%*/); - mainLabel->setWordWrap(true); - mainLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); - //mainLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + muteButton = new QCheckBox(); + mainLabel = new QLabel(QString::fromStdWString(eph->getName())); + mainSlider = new QSlider(Qt::Horizontal); //muteButton->setStyleSheet("background-color: #A3C1DA; color: red"); - mainSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mainSlider->setFocusPolicy(Qt::StrongFocus); - //mainSlider->setTickPosition(QSlider::TicksBothSides); - //mainSlider->setTickInterval(5); + mainSlider->setTickPosition(QSlider::TicksBothSides); + mainSlider->setTickInterval(5); mainSlider->setSingleStep(1); mainSlider->setRange(0,100); - - muteButton->setCheckState((eph->getMute() == false ? Qt::Unchecked : Qt::Checked)); + + muteButton->setCheckState((eph->getMute() == false ? Qt::Unchecked : Qt::Checked)); muteButton->setText(eph->getMute() ? STRING_UNMUTE : STRING_MUTE); - float volume = eph->getVolume(AudioChannel::CHANNEL_MAIN) * 100; + float volume = eph->getVolume(ENDPOINT_MASTER_VOLUME) * 100; mainSlider->setValue((int)volume); - mainVolumeLabel->setText(QString::number(volume)); - log_debugcpp("ENDPOINT SET WITH VOLUME " + std::to_string(volume)); + log_debugcpp("ENDPOINT SET WITH VOLUME " << volume); - //mainMuteLayout = new QGridLayout(); - widgetLayout->addWidget(mainLabel, row, 0, 1, 2, Qt::AlignLeft | Qt::AlignVCenter); - widgetLayout->addWidget(muteButton, row, 2, Qt::AlignRight | Qt::AlignVCenter); - widgetLayout->addWidget(mainVolumeLabel, row, 3, Qt::AlignRight | Qt::AlignVCenter); - row++; - - widgetLayout->addWidget(mainSlider, row, 0, 1, 4, Qt::AlignVCenter); - //widgetLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); - row++; - - //TODO:0 = mute and muted, change volume = unmuted are client side tricks = 2 callbacks, one for volume, one for mute state. Implement as an user selectable option? + mainMuteLayout = new QGridLayout(); + layout->addLayout(mainMuteLayout, 0, 0); + mainMuteLayout->addWidget(mainLabel, 0, 0); + mainMuteLayout->addWidget(muteButton, 0, 1); + layout->addWidget(mainSlider, 0, 1); + connect(mainSlider, &QSlider::valueChanged, this,&EndpointWidget::updateMainVolume); connect(muteButton, &QCheckBox::stateChanged, this, (&EndpointWidget::updateMute)); - - - /* - * Channel sliders setup - */ - uint32_t epChannelCount = eph->getChannelCount(); - if(epChannelCount > 1) { - cw = new ChannelWidget(epChannelCount, eph, nullptr); - cw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - widgetLayout->addWidget(cw, row++, 0, 1, 4 /*colmax*/, Qt::AlignTop); - cw->setVisible(false); - char* const channelSettings = set->getValue("show_channels"); - if(channelSettings && !(strcmp(channelSettings, "true"))){ - cw->setVisible(true); - } - } - - /* - * Role ExtendedCheckBoxes setup - */ - - defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - uint8_t assignedRoles = eph->getRoles(); - uint8_t col = 0; - #define checkbox_setup(role, optor) do { \ - defaultRolesCheckBoxes.at(role)->setCheckState(assignedRoles optor role ? Qt::Checked : Qt::Unchecked); \ - defaultRolesCheckBoxes.at(role)->setDisabled(assignedRoles optor role ? true : false); \ - defaultRolesCheckBoxes.at(role)->setText(STRING_##role); \ - connect(defaultRolesCheckBoxes.at(role), &QCheckBox::stateChanged,[this] { \ - defaultRolesCheckBoxes.at(role)->setChecked(!(defaultRolesCheckBoxes.at(role)->isChecked())); \ - this->eph->setRoles(role); \ - }); \ - widgetLayout->addWidget(defaultRolesCheckBoxes.at(role), row, col++); \ - } while(0) - - checkbox_setup(ROLE_ALL, ==); - checkbox_setup(ROLE_CONSOLE, &); - checkbox_setup(ROLE_MULTIMEDIA, &); - checkbox_setup(ROLE_COMMUNICATIONS, &); - #undef checkbox_setup - row++; - - /* - * EndpointVolume Polling time - */ - - timer = new QTimer(); - connect(timer, &QTimer::timeout, [this, eph](){ - //if (memcmp(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)) == 0) return; CHECK IF THIS PROGRAM GENERATED THE FUNSIES IS NO LONGER IN USE FOR NOW. - //todo: global + constexpr + ratio - const float roundingFactor = 0.005; - if (eph->getCallbackInfo()->updateName) { - eph->getCallbackInfo()->updateName = false; - mainLabel->setText(QString::fromStdWString(eph->getName())); - mainLabel->setMinimumHeight(mainLabel->sizeHint().height()); - } - mainSlider->blockSignals(true); - muteButton->blockSignals(true); - mainSlider->setValue((int)((eph->getCallbackInfo()->mainVolume + roundingFactor) * 100)); - mainSlider->setPeakValue(eph->getPeakVolume()); - mainSlider->update(); - mainVolumeLabel->setText(QString::number(mainSlider->value())); - muteButton->setCheckState((eph->getCallbackInfo()->muted == false ? Qt::Unchecked : Qt::Checked)); - muteButton->setText(eph->getCallbackInfo()->muted ? STRING_UNMUTE : STRING_MUTE); - for(uint32_t i = 0; i < eph->getCallbackInfo()->channels && eph->getChannelCount() > 1; i++){ - cw->updateChannel(i); - } - //memcpy(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)); - - //TODO: el default = objcopy frees? - //Todo: like fr pregunta - eph->getCallbackInfo()->caller = osh->getGuid(); - mainSlider->blockSignals(false); - muteButton->blockSignals(false); - }); - timer->start(POLLING_RATE); - - /* First Widget batch */ - for (size_t i = 0; i < eph->getSessionCount(); i++) { - SessionWidget* sessionWidget = new SessionWidget(i, eph->getSessionHandlers().at(i), this); - widgetLayout->addWidget(sessionWidget, row, 0, 1, 4 /* colmax */); - row++; - sessionWidgets.push_back(sessionWidget); - eph->getSessionHandlers().at(i)->setFrontIndex(i); + for(uint32_t i = 0; i < eph->getChannelCount(); i++){ + QSlider* tmp = new QSlider(Qt::Horizontal); + QLabel* tmpLb = new QLabel(""); + tmp->setTickInterval(5); + tmp->setSingleStep(1); + tmp->setRange(0,100); + volume = eph->getVolume(i) * 100; + tmp->setValue((int) volume); + tmpLb->setText(QString::number(volume)); + this->channelSliders.push_back(tmp); + this->channelLabels.push_back(tmpLb); + layout->addWidget(tmp, 1, i); + layout->addWidget(tmpLb, 2, i); + //TODO: check if there's a need to prevent deadlocks; probably this will eventually turn into its own func + connect(tmp, &QSlider::valueChanged, [this, i](int newValue){ this->eph->setVolume(osh->getGuid(), i, newValue); this->channelLabels.at(i)->setText(QString::number(newValue)); }); } - /* Add/Remove SessionWidget callback */ - eph->setAddSessionWidgetFunction([this](SessionHandler* sessionHandler) { - QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent((QEvent::Type)CustomQEvent::SessionWidgetCreated, sessionHandler)); - }); - - eph->setRemoveSessionWidgetFunction([this](SessionHandler* sessionHandler) { - QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent((QEvent::Type)CustomQEvent::SessionWidgetObsolete, sessionHandler)); - }); - + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 3, 0); + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 3, 1); log_debugcpp("ENDPOINT_WIDGETED"); - eph->createSessionHandlersCallback(); } -void EndpointWidget::addSessionWidget(CustomWidgetEvent* ev){ - this->setUpdatesEnabled(false); - uint64_t index = this->sessionWidgets.size(); - SessionWidget* sw = new SessionWidget(index, ev->payload, this); - ev->payload->setFrontIndex(index); - //MainWindow* mw = dynamic_cast(parent()); - //TODO: change mainwindow's widget name and subclass qwidget - const QWidgetList topLevelWidgets = QApplication::topLevelWidgets(); - for (QWidget *widget : topLevelWidgets) { - if (qobject_cast(widget)) { - QCoreApplication::instance()->postEvent - (widget, new QEvent((QEvent::Type)CustomQEvent::RecomposeMainWindow)); - } - } - this->widgetLayout->addWidget(sw, row, 0, 1, 4); - row++; - sessionWidgets.push_back(sw); - this->setUpdatesEnabled(true); - return; -} - -void EndpointWidget::removeSessionWidget(CustomWidgetEvent* ev){ - this->setUpdatesEnabled(false); - uint64_t i = ev->payload->getFrontIndex(); - SessionWidget* deceased = sessionWidgets.at(i); - deceased->setParent(nullptr); - deceased->hide(); - this->widgetLayout->removeWidget(deceased); - delete deceased; - sessionWidgets.at(i) = nullptr; - //row--; - ev->payload->setFrontIndex(INT_MAX); - this->setUpdatesEnabled(true); - //this->sessionWidgetsUpdateTimer->start(); - return; -} - -void EndpointWidget::customEvent(QEvent* ev) { - if (ev->type() == (QEvent::Type)CustomQEvent::SessionWidgetCreated) { - ev->setAccepted(true); - this->addSessionWidget((CustomWidgetEvent*) ev); - } else if (ev->type() == (QEvent::Type)CustomQEvent::SessionWidgetObsolete) { - ev->setAccepted(true); - this->removeSessionWidget((CustomWidgetEvent*) ev); - } - QWidget::customEvent(ev); -} - -EndpointWidget::~EndpointWidget() { - timer->stop(); - delete timer; - this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ALL, INT_MAX); - this->eph->lockSessionCollections(); - this->eph->deleteSessions(); - this->eph->unlockSessionCollections(); - for(auto sw : sessionWidgets) { - delete sw; - } -} - -void MainWindow::customEvent(QEvent* ev) { - if (ev->type() == (QEvent::Type)CustomQEvent::EndpointWidgetObsolete) { - ev->setAccepted(true); - this->removeEndpointWidget((CustomWidgetEvent*)ev); - } else if (ev->type() == (QEvent::Type)CustomQEvent::EndpointWidgetCreated) { - ev->setAccepted(true); - this->addEndpointWidget((CustomWidgetEvent*)ev); - } else if (ev->type() == (QEvent::Type)CustomQEvent::RecomposeMainWindow) { - ev->setAccepted(true); - if (this->isVisible()) this->compose(true); - } else if (ev->type() == (QEvent::Type)CustomQEvent::EndpointRoleChange) { - ev->setAccepted(true); - this->flushRoleChanges(); - } - QMainWindow::customEvent(ev); -} - -//__attribute__((optimize("O0", "unroll-loops"))) -void MainWindow::removeEndpointWidget(CustomWidgetEvent* ev) { - uint64_t i = ev->payload; - this->ews.at(i)->setParent(nullptr); - this->widgetLayout->removeWidget(ews.at(i)); - //uint64_t saisu = ews.size(); - //delete ews.at(index); - delete ews.at(i); - ews.at(i) = nullptr; - //TODO: is a flattener really necessary? - //this->ewsUpdateTimer->start(); - return; -} - -void MainWindow::addEndpointWidget(CustomWidgetEvent* ev) { - EndpointWidget* epw = new EndpointWidget(ev->payload, containerWidget, this->ews.size()); - //epw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - epw->setParent(this); - if(this->widgetLayout) - this->widgetLayout->addWidget(epw); - ews.push_back(epw); - return; -} - -void MainWindow::reorderEndpointWidgetCollection() { - /* Flatten */ - size_t firstNullPosition = 0; - size_t ewsSize = ews.size(); - bool breakSorting = false; - - //todo: is all of gui really atomic by definition? im afraid of cutting through amazing add momentos, but I think I did my homework. Must check back. - for (size_t i = 0; i < ewsSize; i++) { - if (ews.at(i) == nullptr) { - for (size_t j = (i + 1); j < ewsSize; j++) { - - if (ews.at(j) != nullptr) { - ews.at(i) = ews.at(j); - ews.at(i)->setIndex(i); - ews.at(j) = nullptr; - break; - } - if (j == ewsSize - 1) { - firstNullPosition = i; - breakSorting = true; - } - - } - if (breakSorting) break; - } - } - ews.resize(firstNullPosition + 1); -} - -void EndpointWidget::calculateSize(uint64_t width, uint64_t height) { - /* og 1080p 120% testing values */ - log_to_file("[EndpointWidget %s sizes]\n", converter.to_bytes(this->getEndpointHandler()->getName()).c_str()); - log_to_file("Params: {WWidth: %u SHeight: %u}\n", width, height); - //this->setMaximumWidth(width); - /* - * this->mainLabel->setMaximumWidth((int)(width * 0.50) /\* 1080p 120%*\/); - * this->mainLabel->setMinimumWidth((int)(width * 0.50) /\* 1080p 120%*\/); - */ - this->mainLabel->setMaximumSize((int)(width * 0.50), height /* 1080p 120%*/); - this->mainLabel->setMinimumSize((int)(width * 0.50), 1 /* 1080p 120%*/); - this->muteButton->setMaximumSize((int)(width * 0.10), height /* 1080p 120%*/); - this->mainVolumeLabel->setMaximumSize((int)(width * 0.10), height /* 1080p 120%*/); - for (auto roleCheckbox : defaultRolesCheckBoxes) { - roleCheckbox.second->setMaximumWidth((int)(width * 0.20) /* 1080p 120%*/); - log_to_file("Role %d width: %d \n", roleCheckbox.first, roleCheckbox.second->maximumWidth()); - } - log_to_file("Main label width: %d \n", this->mainLabel->maximumWidth()); - log_to_file("Mute button width: %d \n", this->muteButton->maximumWidth()); - log_to_file("Volume label width: %d \n", this->mainVolumeLabel->maximumWidth()); - - if (cw) { - this->cw->setMinimumSize(QSize(1, (height * 0.06) * (int)((cw->getChannelCount() / 2) + 0.5))); - //this->cw->setMaximumSize(QSize(width, (height * 0.06) * (int)((cw->getChannelCount() / 2) + 0.5))); - log_to_file("Channels Maximum size: %d, %d \n", cw->maximumWidth(), cw->maximumHeight()); - log_to_file("Channels Minimum size: %d, %d \n", cw->minimumWidth(), cw->minimumHeight()); - } - for (auto sw : sessionWidgets){ - if (sw) sw->calculateSize(width, height); - } +void EndpointWidget::updateMute(bool muted){ + log_debugcpp("cliqui callboqui cloqui"); + //TIP: Blocksignals here to diagnose slider visuals locking when playing DJ with external volume bar. Functionality is restored when mute checkbox is clicked. + //this->blockSignals(true); + //this->muteButton->blockSignals(true); + + //this->eph->setMute(osh->getGuid(), muted); + this->muteButton->setChecked(muted); + this->muteButton->setText(this->eph->getMute() ? STRING_UNMUTE : STRING_MUTE); + //this->muteButton->blockSignals(false); + //this->blockSignals(false); } void EndpointWidget::updateMute(int checked){ + log_debugcpp("cliqui slOtty cloqui"); bool muted = (checked == 2 ? true : false); + log_debugcpp("int: " << checked << " bool: " << muted); this->eph->setMute(osh->getGuid(), muted); + //this->muteButton->setCheckState(); this->muteButton->setText(this->eph->getMute() ? STRING_UNMUTE : STRING_MUTE); } void EndpointWidget::updateMainVolume(int newValue){ - mainVolumeLabel->setText(QString::number(newValue)); - this->eph->setVolume(osh->getGuid(), AudioChannel::CHANNEL_MAIN, newValue); + log_debugcpp("updateMainVolume slot."); + this->eph->setVolume(osh->getGuid(), ENDPOINT_MASTER_VOLUME, newValue); } -/* - * void EndpointWidget::updateVolume(uint32_t channel, float newValue){ - * //this->blockSignals(true); - * int newVal = newValue * 100; - * if (channel == (uint32_t)AudioChannel::CHANNEL_MAIN) { - * //TIP: Above - * //this->mainSlider->blockSignals(true); - * - * if(this->mainSlider->value() != newVal) { - * this->mainSlider->blockSignals(true); - * this->mainSlider->setValue(newVal); - * this->mainSlider->blockSignals(false); - * } - * return; - * } - * - * for (size_t i = 0; i < sizeof(uint32_t) * 8 && i < channelSliders.size(); ++i) { - * if (((channel >> i) & 1) && this->channelSliders.at(i)->value() != newVal) { - * //this->channelSliders.at(i)->blockSignals(true); - * - * this->channelSliders.at(i)->setValue(newVal); - * this->channelLabels.at(i)->setText(QString::number((int)(newValue * 100))); - * - * //this->channelSliders.at(i)->blockSignals(false); - * } - * } - * - * //this->blockSignals(false); - * } - */ - -void EndpointWidget::updateChannelsVisibility() { - if (!cw) return; +void EndpointWidget::updateVolume(uint32_t channel, float newValue){ + //this->blockSignals(true); + int newVal = newValue * 100; + if (channel == (uint32_t)AudioChannel::CHANNEL_MAIN) { + log_debugcpp("mainvolcallback int: " << newVal); + //this->mainSlider->blockSignals(true); - char* const channelSettings = set->getValue("show_channels"); - if(channelSettings && !(strcmp(channelSettings, "true"))){ - cw->setVisible(true); - } else cw->setVisible(false); -} + if(this->mainSlider->value() != newVal) { + this->mainSlider->setValue(newVal); + } + return; + } + + log_debugcpp("Cont->Front Channel:: " << channel << " volcallback int: " << newVal); -EndpointHandler* EndpointWidget::getEndpointHandler(){ - return this->eph; + for (size_t i = 0; i < sizeof(uint32_t) * 8 && i < channelSliders.size(); ++i) { + if (((channel >> i) & 1) && this->channelSliders.at(i)->value() != newVal) { + //this->channelSliders.at(i)->blockSignals(true); + + this->channelSliders.at(i)->setValue(newVal); + this->channelLabels.at(i)->setText(QString::number((int)(newValue * 100))); + + //this->channelSliders.at(i)->blockSignals(false); + } + } + + //this->blockSignals(false); } /* - * void EndpointWidget::updateFrontIndex(uint64_t index){ - * this->idx = index; + * void EndpointWidget::toggleFrontEvents(bool active){ + * this->muteButton->blockSignals(active); + * this->mainSlider->blockSignals(active); + * for(uint32_t i = 0; i < this->channelSliders.size(); i++){ + * this->channelSliders.at(i)->blockSignals(active); + * } * } */ -void EndpointWidget::setIndex(uint64_t idx) { + +void EndpointWidget::setIndex(uint64_t idx){ this->idx = idx; - this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ACTIVE, this->idx); } uint64_t EndpointWidget::getIndex(){ return idx; } -std::map EndpointWidget::getDefaultRolesWidgets() { - return defaultRolesCheckBoxes; -} - -HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) { - widgetLayout = new QGridLayout(this); +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { + // setWindowState(Qt::WindowFullScreen); + // setCentralWidget(centralWidget); + widget = new QWidget(); + layout = new QGridLayout(); - QString text; //= "&" STRING_ABOUT; - //about = new QPushButton(text, this); - #ifdef WIN32 - text = "&" STRING_CP; - openCP = new QPushButton(text, this); - connect(openCP, &QPushButton::clicked, [](){ osh->openControlPanel(); }); + widget->setLayout(layout); + setCentralWidget(widget); + //layout->addWidget(pintas, 0, 0); - text = "&" STRING_CHANNELS; - channels = new QCheckBox(text, this); - char* const channelSettings = set->getValue("show_channels"); - if(channelSettings && !(strcmp(channelSettings, "true"))){ - channels->setChecked(true); - } - connect(channels, &QCheckBox::stateChanged, [this, parent](){ - //TODO: Find a better way to auto no-op when there's no settings file - if(set) { - set->setValue("show_channels", channels->isChecked(), sizeof("show_channels")); - if(!OverseerHandler::settingsPath.empty()){ - set->save(OverseerHandler::settingsPath.c_str()); - } - } - if(parent) { - QEvent explosion = QEvent((QEvent::Type)CustomQEvent::RecomposeMainWindow); - QCoreApplication::instance()->sendEvent - (parent, &explosion); - } - - }); - - text = "&" STRING_STARTUP; - startup = new QCheckBox(text, this); - if(osh->isToRunAtStartup()) { - startup->setChecked(true); - } - connect(startup, &QCheckBox::stateChanged, [this](){ - osh->setStartupConfig(startup->isChecked()); - }); - - widgetLayout->addWidget(openCP , 0, 0, 2, 2); - widgetLayout->addWidget(channels, 0, 2, 1, 2); - widgetLayout->addWidget(startup , 1, 2, 1, 2); - #endif - //widgetLayout->addWidget(about , 0, 2); - this->setLayout(widgetLayout); -} - -void MainWindow::createLayout(QGridLayout *newLayout) { - log_debugcpp("createLayout"); - widgetLayout->removeItem(lastRowSpacer); - QGridLayout *tempStore = this->widgetLayout; - this->widgetLayout = 0; - delete tempStore; - containerWidget->setLayout(newLayout); - this->widgetLayout = newLayout; - - bool areEndpoints = false; - uint64_t i = 0; - for (EndpointWidget *epw : ews) { - if (!epw) continue; - else areEndpoints = true; - log_wdebugcpp(L"epw name: " + epw->getEndpointHandler()->getName()); - //epw->setIndex(i); - this->widgetLayout->addWidget(epw, i++, 0); - } - if(areEndpoints) { - if (noEndpoints) { delete noEndpoints; noEndpoints = nullptr; } - widgetLayout->addItem(lastRowSpacer, i, 0); - } else { - if (!noEndpoints) noEndpoints = new QLabel(STRING_NOENDPOINT, this); - widgetLayout->addWidget(noEndpoints, i, 0); - } -} - -MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { - //setWindowState(Qt::WindowFullScreen); - //setCentralWidget(centralWidget); - //todo: ratio - setWindowFlags(Qt::Window | Qt::MSWindowsFixedSizeDialogHint); - setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip); - //setAttribute(Qt::WA_TranslucentBackground); - //setStyleSheet("background: transparent; "); - //setStyleSheet("background-color: rgba(255,182,193);"); - setWindowTitle(STRING_TITLE); - /* - * Font setup - */ - int id = QFontDatabase::addApplicationFont(":/assets/selawk.ttf"); - QString family = QFontDatabase::applicationFontFamilies(id).at(0); - font = QFont(family); - font.setKerning(true); - font.setPointSize(12); - this->setFont(font); - //qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1"); + setWindowTitle("slidea resbala nu c"); - /* - * Registering needed custom events - */ - //| Qt::FramelessWindowHint - QEvent::registerEventType(CustomQEvent::EndpointWidgetObsolete); - QEvent::registerEventType(CustomQEvent::EndpointWidgetCreated); - QEvent::registerEventType(CustomQEvent::EndpointDefaultChange); - QEvent::registerEventType(CustomQEvent::SessionWidgetObsolete); - QEvent::registerEventType(CustomQEvent::SessionWidgetCreated); - QEvent::registerEventType(CustomQEvent::RecomposeMainWindow); - QEvent::registerEventType(CustomQEvent::EndpointRoleChange); - - /* This spacer provides proper spacing when window vertically > widgets. */ - lastRowSpacer = new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); - - ewsUpdateTimer = new QTimer(this); - recentlyClosedTimer = new QTimer(this); - containerWidget = new QWidget(); - //widget->setContentsMargins(0, 0, 0, 0); - widgetLayout = new QGridLayout(); - trayIcon = new QSystemTrayIcon(); - trayIconMenu = new QMenu(); - trayIconMenuQuit = new QAction(STRING_QUIT); - trayIconMenuOpenCP = new QAction(STRING_CP); - - ewsUpdateTimer->setSingleShot(true); - ewsUpdateTimer->setInterval(ewsUpdateTimerFrequency); - connect(ewsUpdateTimer, &QTimer::timeout, this, &MainWindow::reorderEndpointWidgetCollection); - - recentlyClosedTimer->setSingleShot(true); - recentlyClosedTimer->setInterval(recentlyClosedTimerFrequency); - connect(recentlyClosedTimer, &QTimer::timeout, this, [=]() { this->recentlyClosed = false; }); - //widget->setMinimumSize(QSize(300,300)); - //widget->setLayout(widgetLayout); - /* - * Scroll bar code - */ - scrollArea = new QScrollArea(this); - //widget->setAttribute(Qt::WA_TranslucentBackground); - scrollArea->setWidget(containerWidget); - scrollArea->setWidgetResizable(true); - scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - scrollArea->setContentsMargins(QMargins(0, 0, 0, 0)); - - //ScrollBarFocusFilter focusFilter = new ScrollBarFocusFilter(this); - scrollArea->verticalScrollBar()->installEventFilter(this); - scrollArea->horizontalScrollBar()->installEventFilter(this); - //scrollArea->verticalScrollBar()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); - //scrollArea->verticalScrollBar()->setSingleStep(1); - - setCentralWidget(scrollArea); - - /* - * Menu bar code - */ - mainMenuBar = new QToolBar(this); - hw = new HeaderWidget(this); - mainMenuBar->addWidget(hw); - mainMenuBar->setMovable(false); - this->addToolBar(Qt::BottomToolBarArea, mainMenuBar); - - /* - * Create initial endpoint widgets batch - */ reloadEndpointWidgets(); - - /* - * Tray Icon code - */ - //trayIconMenu->addSeparator(); - trayIconMenu->addAction(trayIconMenuOpenCP); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(trayIconMenuQuit); - connect(trayIconMenuOpenCP, &QAction::triggered, ([]() {osh->openControlPanel();}) ); - connect(trayIconMenuQuit, &QAction::triggered, qApp, &QCoreApplication::quit); - trayIcon->setIcon(QIcon(":/assets/notificationAreaIcon.png")); - setWindowIcon(QIcon(":/assets/notificationAreaIcon.png")); - //TODO: Extend qsystemtrayicon to change mouse click? - //show before setting tooltip required; smells like bug to me! - trayIcon->show(); - trayIcon->setToolTip(STRING_TITLE); - trayIcon->setContextMenu(trayIconMenu); - connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::trayIconActivated); - connect(qApp, &QGuiApplication::applicationStateChanged, this, [=](Qt::ApplicationState state){ - if(state == Qt::ApplicationState::ApplicationInactive) { - this->hide(); - //This recentlyClosed... kinda campy. - this->recentlyClosed = true; - this->recentlyClosedTimer->start(); - } - }); - - /* - * Set accent color - */ - uint8_t a, r, g, b; - if (StylingHelper::argbToDiscreteValues(osh->getAccentColor(), &r, &g, &b, &a)) - this->updateColor(r, g, b, a); - - /* - * Set of function callback definitons for EndpointSituationCallback - */ - osh->setRoleBucketEntryFunction([this](Roles role, std::wstring endpointId) { - std::pair entry = { role, endpointId }; - this->roleBucketList.push_back(entry); - QCoreApplication::instance()->postEvent(this, new QEvent((QEvent::Type)CustomQEvent::EndpointRoleChange),Qt::LowEventPriority); - }); - - osh->setRemoveEndpointWidgetFunction([this](uint64_t index) { - QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent((QEvent::Type)CustomQEvent::EndpointWidgetObsolete, index)); - }); - - osh->setAddEndpointWidgetFunction([this](EndpointHandler* eph) { - QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent((QEvent::Type)CustomQEvent::EndpointWidgetCreated, eph)); - }); - -} - -bool MainWindow::eventFilter(QObject *object, QEvent *event) { - //QScrollBar* widgetCast = qobject_cast(object); - if (object == scrollArea->verticalScrollBar()) { - [[maybe_unused]] QEvent::Type tipo = event->type(); - if (event->type() == QHoverEvent::HoverEnter) { - log_debugcpp("Hover event: "); - log_debugcpp("\tGlobal pos: " - + std::to_string(((QHoverEvent*)event)->globalPosition().x()) - + ", " - + std::to_string(((QHoverEvent*)event)->globalPosition().y())); - log_debugcpp("\tNewWid pos: " - + std::to_string(((QHoverEvent*)event)->position().x()) - + ", " - + std::to_string(((QHoverEvent*)event)->position().y())); - log_debugcpp("\tOldWid pos: " - + std::to_string(((QHoverEvent*)event)->oldPos().x()) - + ", " - + std::to_string(((QHoverEvent*)event)->oldPos().y())); - - } - if (event->type() == QScrollEvent::ScrollFinished) { - QHoverEvent* hoverEvent = new QHoverEvent(QEvent::HoverEnter, - scrollArea->verticalScrollBar()->mapFromGlobal(QCursor::pos()), - QCursor::pos(), - scrollArea->verticalScrollBar()->mapFromGlobal(QCursor::pos())); - log_debugcpp("ScrollFinished event: "); - log_debugcpp("\tGlobal pos: " - + std::to_string(QCursor::pos().x()) - + ", " - + std::to_string(QCursor::pos().y())); - log_debugcpp("\tWidget pos: " - + std::to_string(scrollArea->verticalScrollBar()->mapFromGlobal(QCursor::pos()).x()) - + ", " - + std::to_string(scrollArea->verticalScrollBar()->mapFromGlobal(QCursor::pos()).y())); - QCoreApplication::instance()->postEvent(scrollArea->verticalScrollBar(), hoverEvent); - /* - * QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent((QEvent::Type)CustomQEvent::SessionWidgetObsolete, sessionHandler)); - */ - //scrollArea->setFocus(Qt::MouseFocusReason); - return false; - }} - return false; -} - -void MainWindow::flushRoleChanges() { - std::pair change = roleBucketList.front(); - roleBucketList.pop_front(); - - EndpointWidget *newDef = nullptr, *oldDef = nullptr; - for (uint64_t i = 0; i < ews.size(); i++) { - if(newDef && oldDef) break; - auto epw = this->ews.at(i); - if (!epw) continue; - if (epw->getEndpointHandler()->getId() == change.second) { - newDef = epw; - ews.at(i) = nullptr; - continue; - } - if (epw->getEndpointHandler()->getRoles() & change.first) { - oldDef = epw; - ews.at(i) = nullptr; - continue; - } - } - - this->changeFrontDefaults(change.first, newDef, oldDef); -} - -void MainWindow::changeFrontDefaults(Roles role, EndpointWidget* newDef, EndpointWidget* oldDef) { - //Sigh... MS's naive (non)API didn't help, but... - //Since widgets are removed previously, they must be added back. - //This produces unneeded vector size increases. - //Also, there's no freaking way this must be this illegible. - //TODO: Rewrite this method. Seriously. You'll have to get to, someday. - if (newDef && !oldDef) { - newDef->getDefaultRolesWidgets().at(role)->blockSignals(true); - uint8_t newDefCurRolesReversed = ~(newDef->getEndpointHandler()->getRoles()); - if(newDefCurRolesReversed & role) { - newDef->getEndpointHandler()->assignRoles(role); - QCoreApplication::instance()->sendEvent(newDef->getDefaultRolesWidgets().at(role), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); - } - uint8_t newDefIdx = newDef->getIndex(); - uint8_t newDefRoles = newDef->getEndpointHandler()->getRoles(); - if (newDefRoles == Roles::ROLE_ALL) { - newDef->setIndex(0); - this->ews[0] = newDef; - if(newDefCurRolesReversed & role) { - newDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL)->blockSignals(true); - QCoreApplication::instance()->sendEvent(newDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); - newDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL)->blockSignals(false); - } - } else if ((newDefRoles & Roles::ROLE_MULTIMEDIA) || - (newDefRoles & Roles::ROLE_CONSOLE)){ - newDef->setIndex(0); - this->ews[0] = newDef; - } else if (newDefRoles & Roles::ROLE_COMMUNICATIONS) { - newDef->setIndex(1); - this->ews[1] = newDef; - } - log_debugcpp("newDef new idx: " + std::to_string(newDef->getIndex())); - newDef->getDefaultRolesWidgets().at(role)->blockSignals(false); - } - else if (oldDef && newDef) { - newDef->getDefaultRolesWidgets().at(role)->blockSignals(true); - newDef->getEndpointHandler()->assignRoles(role); - QCoreApplication::instance()->sendEvent(newDef->getDefaultRolesWidgets().at(role), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); - uint8_t newDefIdx = newDef->getIndex(); - uint8_t newDefRoles = newDef->getEndpointHandler()->getRoles(); - if (newDefRoles == Roles::ROLE_ALL) { - newDef->setIndex(0); - this->ews[0] = newDef; - newDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL)->blockSignals(true); - QCoreApplication::instance()->sendEvent(newDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); - newDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL)->blockSignals(false); - } else if ((newDefRoles & Roles::ROLE_MULTIMEDIA) || - (newDefRoles & Roles::ROLE_CONSOLE)){ - newDef->setIndex(0); - this->ews[0] = newDef; - } else if (newDefRoles & Roles::ROLE_COMMUNICATIONS) { - newDef->setIndex(1); - this->ews[1] = newDef; - } - log_debugcpp("newDef new idx: " + std::to_string(newDef->getIndex())); - newDef->getDefaultRolesWidgets().at(role)->blockSignals(false); - - oldDef->getDefaultRolesWidgets().at(role)->blockSignals(true); - uint8_t oldDefRoles = oldDef->getEndpointHandler()->getRoles(); - if (oldDefRoles == Roles::ROLE_ALL) { - oldDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL)->blockSignals(true); - QCoreApplication::instance()->sendEvent(oldDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); - oldDef->getDefaultRolesWidgets().at(Roles::ROLE_ALL)->blockSignals(false); - } - oldDef->getEndpointHandler()->removeRoles(role); - QCoreApplication::instance()->sendEvent(oldDef->getDefaultRolesWidgets().at(role), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); - oldDefRoles = oldDef->getEndpointHandler()->getRoles(); - //this->ews[oldDef->getIndex()] = nullptr; - if ((oldDefRoles & Roles::ROLE_MULTIMEDIA) && - (oldDefRoles & Roles::ROLE_CONSOLE)) { - this-> ews[0] = oldDef; - oldDef->setIndex(0); - } else if (oldDefRoles & Roles::ROLE_COMMUNICATIONS) { - this-> ews[1] = oldDef; - oldDef->setIndex(1); - } else { - if (newDefIdx > 1) { - this->ews[newDefIdx] = oldDef; - oldDef->setIndex(newDefIdx); - } else { - this->ews.push_back(oldDef); - oldDef->setIndex(this->ews.size() - 1); - } - } - log_debugcpp("oldDef new idx: " + std::to_string(oldDef->getIndex())); - oldDef->getDefaultRolesWidgets().at(role)->blockSignals(false); - } - QCoreApplication::instance()->sendEvent - (this, new QEvent((QEvent::Type)CustomQEvent::RecomposeMainWindow)); -} - -void MainWindow::closeEvent(QCloseEvent *event) { - if (!event->spontaneous() || !isVisible()) return; - - if (trayIcon->isVisible()) { - //todo: would be nice to show this to 1st time users; ini-san will come... - //this->trayIcon->showMessage("ini file calling","primerita vez", QSystemTrayIcon::Information); - - hide(); - event->ignore(); - } -} - -void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason) { - switch (reason) { - case QSystemTrayIcon::Trigger: - if (!this->isVisible() && !recentlyClosed) { - log_to_file("Recently Closed: %d \n", recentlyClosed); - this->compose(false); - this->showNormal(); - this->activateWindow(); - } - break; - default: - break; - } } void MainWindow::reloadEndpointWidgets() { - size_t i = 0; - ews.resize(2); - - osh->handlersPlaybackMutex.lock(); - for (size_t epwIndex = 2; i < (osh->getPlaybackEndpointHandlers().size()); i++) { - if (osh->getPlaybackEndpointHandlers().at(i)->getState() == EndpointState::ENDPOINT_ACTIVE){ - log_debugcpp("EPWidget creation"); - //osh->getPlaybackEndpointHandlers().at(i)->getCallbackInfo()->caller = osh->getGuid(); - EndpointWidget *epw = new EndpointWidget(osh->getPlaybackEndpointHandlers().at(i), containerWidget); - - log_wdebugcpp(L"epw name: " + epw->getEndpointHandler()->getName()); - if ((epw->getEndpointHandler()->getRoles() == Roles::ROLE_ALL) || - (epw->getEndpointHandler()->getRoles() & Roles::ROLE_MULTIMEDIA)) - { ews[0] = epw; epw->setIndex(0); } - else if (epw->getEndpointHandler()->getRoles() & Roles::ROLE_COMMUNICATIONS) - { ews[1] = epw; epw->setIndex(1); } - else - { ews.push_back(epw); epw->setIndex(ews.size() - 1); } - } + unsigned int i = 0; + for (; i < (osh->getEndpointHandlers().size()); i++) { + log_debugcpp("EPWidget creation"); + EndpointWidget *epw = new EndpointWidget(osh->getEndpointHandlers().at(i), widget); + ews.push_back(epw); + layout->addWidget(epw, i, 0); } - osh->handlersPlaybackMutex.unlock(); - //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 - widgetLayout->addItem(lastRowSpacer, i, 0); + + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), i, 0); + + osh->setFrontVolumeCallback([this](uint64_t device, uint32_t channel, float value) { + if (device < ews.size()) + ews[device]->updateVolume(channel, value); + }); + osh->setFrontMuteCallback([this](uint64_t device, bool muted) { + if (device < ews.size()) + ews[device]->updateMute(muted); + }); } +/* + * void MainWindow::setPlotButton() { + * button = new QPushButton("push"), + * button->setCheckable(true); + * connect(button, SIGNAL(toggled(bool)), this, SLOT(toggled(bool))) + * QHBoxLayout *plotsLayout = new QHBoxLayout; + * plotsLayout->setSpacing(10); + * plotsLayout->addWidget(funPlot); + * QHBoxLayout *buttonsLayout = new QHBoxLayout ; + * buttonsLayout->addWidget(button); + * QVBoxLayout *widgetLayout = new QVBoxLayout; + * widgetLayout->addLayout(plotsLayout); + * widgetLayout->addLayout(buttonsLayout); + * setLayout(widgetLayout); + * ... + */ + + diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index 1b2658b..c5eee14 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -1,162 +1,87 @@ #pragma once -#include "qtcommon.h" +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +/* + * #else + * class QSlider; + * class QLabel; + * class QGridLayout; + * class QPushButton; + * class QWidget; + * class QMainWindow; + * #endif + */ + +#include "global.h" #include "contclasses.h" -#include "settings.h" +//class EndpointHandler; -class MeterSlider; - -enum SpawnPos { - LEFT = (1 << 1), - RIGHT = (0 << 1), - UP = (1 << 0), - DOWN = (0 << 0) -}; - -enum CustomQEvent { - EndpointWidgetObsolete = 1001, - EndpointWidgetCreated = 1002, - EndpointDefaultChange = 1003, - SessionWidgetCreated = 1004, - SessionWidgetObsolete = 1005, - RecomposeMainWindow = 1006, - EndpointRoleChange = 1007 -}; - -class DarkModeEventFilter : public QAbstractNativeEventFilter { - -public: - bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override; -}; - -template -class CustomWidgetEvent : public QEvent { - -public: - CustomWidgetEvent(QEvent::Type type, T payload); - T payload; -}; -//Q_DECLARE_METATYPE(EndpointWidgetEvent) - -class ExtendedCheckBox : public QCheckBox { - Q_OBJECT -private: - QIcon icons; - -protected: - void customEvent(QEvent* ev) override; - void paintEvent(QPaintEvent* event) override; - -public: - //c++11: this inherits all parent's constructors unconditionally - using QCheckBox::QCheckBox; - void addIcon(char* const path, QIcon::State state); - //alternative being calling parent ctor directly after declaring child ctor: - //B(int x) : A(x) { } -}; - -class SessionWidget : public QWidget { -Q_OBJECT - -public: - SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent /* = nullptr */); - ~SessionWidget(); - void calculateSize(uint64_t width, uint64_t height); - std::wstring getName(); - -public slots: - void updateMainVolume(int newValue); - void updateMute(int checked); - -private: - QLabel *mainLabel = nullptr; - MeterSlider *mainSlider = nullptr; - uint64_t idx; - QHBoxLayout *widgetLayout = nullptr; - ExtendedCheckBox *muteButton = nullptr; - SessionHandler* sh; - QTimer* volumePoller = nullptr; - QSpacerItem* widthSpacer; -}; - -class ChannelWidget : public QWidget { -Q_OBJECT - -public: - ChannelWidget(uint32_t channelCount, EndpointHandler* eph, QWidget *parent = nullptr); - //QSize minimumSizeHint() const override; - //void setMinimum(QSize minimum); - void updateChannel(int channel); - uint32_t getChannelCount() const; - -private: - const double roundingFactor = 0.005; - EndpointHandler* eph; - uint32_t channelCount; - std::vector channelSliders; - std::vector channelLabels; - QGridLayout *widgetLayout; - QSize minimum; -}; +/* + * class ToggleButton : public QAbstractButton { + * Q_OBJECT + * + * public: + * ToggleButton(QWidget *parent = nullptr); + * void checkStateSet(); + * bool hitButton(const QPoint &pos) const; + * void nextCheckState(); + * void changeEvent(QEvent *e) override; + * bool event(QEvent *e) override; + * void focusInEvent(QFocusEvent *e) override; + * void focusOutEvent(QFocusEvent *e) override; + * void keyPressEvent(QKeyEvent *e) override; + * void keyReleaseEvent(QKeyEvent *e) override; + * void mouseMoveEvent(QMouseEvent *e) override; + * void mousePressEvent(QMouseEvent *e) override; + * void mouseReleaseEvent(QMouseEvent *e) override; + * void paintEvent(QPaintEvent *e) override = 0; + * void timerEvent(QTimerEvent *e) override; + * ToggleButton(QWidget *parent = nullptr); + * }; + */ class EndpointWidget : public QWidget { -Q_OBJECT + Q_OBJECT public: - EndpointWidget(EndpointHandler* eph, QWidget *parent = nullptr, uint64_t idx = INT_MAX); - //QSize minimumSizeHint() const override; - //void setMinimum(uint64_t height, double heightRatio); - void updateChannelsVisibility(); - EndpointHandler* getEndpointHandler(); - std::map getDefaultRolesWidgets(); - + EndpointWidget(EndpointHandler* eph, QWidget *parent = nullptr); + //TODO: get(); + EndpointHandler* eph; void setIndex(uint64_t idx); uint64_t getIndex(); - //void setVolume(int channel, float volume); - void calculateSize(uint64_t width, uint64_t height); - ~EndpointWidget(); + void setVolume(int channel, float volume); + + QCheckBox *muteButton = nullptr; + QLabel *mainLabel = nullptr, *leftChannelLabel = nullptr, *rightChannelLabel = nullptr; + QSlider *mainSlider = nullptr; + std::vector channelSliders; + std::vector channelLabels; + QGridLayout *layout = nullptr; + QGridLayout *mainMuteLayout = nullptr; //void updateMainVolume(float newValue); - //void updateVolume(uint32_t channel, float newValue); - //void updateMute(bool muted); + void updateVolume(uint32_t channel, float newValue); + void updateMute(bool muted); + //void toggleFrontEvents(bool active); //void populateEndpointWidget(EndpointHandler *eph); //void setEndpointHandlers(std::vector *ephs); - -//protected: - //bool event(QEvent* ev) override; - + public slots: void updateMainVolume(int newValue); void updateMute(int checked); - -protected: - void customEvent(QEvent* ev) override; - -private slots: - void addSessionWidget(CustomWidgetEvent* ev); - void removeSessionWidget(CustomWidgetEvent* ev); - -private: - int row; - const int sessionCol = 2; - QCheckBox *muteButton = nullptr; - QLabel *mainLabel = nullptr; - QLabel *mainVolumeLabel = nullptr; - MeterSlider *mainSlider = nullptr; - std::vector channelSliders; - std::vector channelLabels; - QGridLayout *widgetLayout = nullptr; - QGridLayout *mainMuteLayout = nullptr; - std::map defaultRolesCheckBoxes; - EndpointHandler* eph; - size_t defaultRolesVectorSize = 4; - QTimer* timer = nullptr; +private: uint64_t idx; - ChannelWidget* cw = nullptr; - std::vector sessionWidgets; - QSize minimum; //std::vector *ephs; //std::vector *sliders; @@ -165,22 +90,6 @@ private: }; -class HeaderWidget : public QWidget { -Q_OBJECT - -public: - HeaderWidget(QWidget *parent = nullptr); - -private: - QGridLayout *widgetLayout; - //QPushButton *about; - #ifdef WIN32 - QPushButton *openCP; - QCheckBox *startup; - QCheckBox *channels; - #endif -}; - class MainWindow : public QMainWindow { Q_OBJECT //QWidget *centralWidget; @@ -188,57 +97,17 @@ class MainWindow : public QMainWindow { public: MainWindow(QWidget *parent = nullptr); void reloadEndpointWidgets(); - void compose(bool isVisible); - void updateColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a); -protected: - void closeEvent(QCloseEvent *event) override; - void customEvent(QEvent* ev) override; - QRect setSizePosition(QScreen* screen, int width, int height); - QScreen* getCurrentScreen(); - void createLayout(QGridLayout *newLayout); - -private slots: - void trayIconActivated(QSystemTrayIcon::ActivationReason reason); - void removeEndpointWidget(CustomWidgetEvent* ev); - void addEndpointWidget(CustomWidgetEvent* ev); - void reorderEndpointWidgetCollection(); //TODO: destroy/empty existing EndpointWidgets //void setEndpointHandlers(std::vector *ephs); private: //std::vector *ephs; - bool eventFilter(QObject *object, QEvent *event) override; - void flushRoleChanges(); - void changeFrontDefaults(Roles role, EndpointWidget* newDef, EndpointWidget* oldDef); - std::vector ews; - std::deque> roleBucketList; - std::mutex roleBucketMutex; - QWidget *containerWidget; - QGridLayout *widgetLayout; + QWidget *widget; + QGridLayout *layout; + //QLabel *pintas; - QSystemTrayIcon *trayIcon; - QMenu *trayIconMenu; - QAction *trayIconMenuQuit; - QAction *trayIconMenuOpenCP; - QTimer *ewsUpdateTimer; - static constexpr uint64_t ewsUpdateTimerFrequency = 500; - double widthRatio = 0.28; - double dpr = 1.0; - bool recentlyClosed = false; - uint8_t recentlyClosedTimerFrequency = 1000; - QTimer *recentlyClosedTimer; - - QScrollArea *scrollArea; - HeaderWidget* hw; - QToolBar *mainMenuBar; - QScreen *screen; - QSpacerItem* lastRowSpacer; - QLabel* noEndpoints = nullptr; - - QFont font; - friend class EndpointWidget; //public slots: // void setEndpointHandlers(std::vector *ephs); @@ -246,3 +115,5 @@ private: //void valueChanged(int value); }; + +#endif diff --git a/src/qt/qtcommon.h b/src/qt/qtcommon.h deleted file mode 100644 index 61873eb..0000000 --- a/src/qt/qtcommon.h +++ /dev/null @@ -1,254 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -//#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -//#include -/* - * #else - * class QSlider; - * class QLabel; - * class QGridLayout; - * class QPushButton; - * class QWidget; - * class QMainWindow; - * #endif - */ - -#include "global.h" - -enum CustomComplexControl { - CC_MeterSlider = 0xf0000001 -}; - -enum CustomControlElement { - CE_ExtendedCheckBox = 0xf0000001 -}; - -namespace StylingHelper { - - static inline void setBackgroundColor(bool lightMode) { - //QApplication* app = (QApplication*)QApplication::instance(); - QPalette pal = QGuiApplication::palette(); - if(lightMode) { - pal.setColor(QPalette::Window, Qt::white); - pal.setColor(QPalette::WindowText, Qt::black); - } else { - pal.setColor(QPalette::Window, Qt::black); - pal.setColor(QPalette::WindowText, Qt::white); - } - QGuiApplication::setPalette(pal); - } - - static inline void setAccentColor(bool lightMode) { - //QApplication* app = (QApplication*)QApplication::instance(); - QPalette pal = QGuiApplication::palette(); - if(lightMode) { - pal.setColor(QPalette::Window, Qt::white); - pal.setColor(QPalette::WindowText, Qt::black); - } else { - pal.setColor(QPalette::Window, Qt::black); - pal.setColor(QPalette::WindowText, Qt::white); - } - QGuiApplication::setPalette(pal); - } - - static inline bool argbToDiscreteValues(uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *a) { - if(!r || !g || !b || !a) return false; - - *a = (color >> 24) & 0xFF; - *r = (color >> 16) & 0xFF; - *g = (color >> 8) & 0xFF; - *b = color & 0xFF; - return true; - } - - static inline QLatin1String operator""_L1(const char* ch, uint64_t) { - return QLatin1String(ch); - } - - static inline qreal calculateDpi(const QStyleOption *option) { - #ifndef Q_OS_DARWIN - // Prioritize the application override, except for on macOS where - // we have historically not supported the AA_Use96Dpi flag. - if (QCoreApplication::testAttribute(Qt::AA_Use96Dpi)) - return 96; - #endif - - // Expect that QStyleOption::QFontMetrics::QFont has the correct DPI set - if (option) - return option->fontMetrics.fontDpi(); - - // Fall back to historical Qt behavior: hardcoded 72 DPI on mac, - // primary screen DPI on other platforms. - #ifdef Q_OS_DARWIN - return qstyleBaseDpi; - #else - return QGuiApplication::primaryScreen()->physicalDotsPerInch(); - #endif - } - - static inline qreal calculateDpi() { - return QFontMetrics(QApplication::font()).fontDpi(); - } - - /* - * #ifdef Q_OS_DARWIN - * static const qreal qstyleBaseDpi = 72; - * #else - * static const qreal qstyleBaseDpi = 96; - * #endif - */ - - //Q_GUI_EXPORT int qt_defaultDpiX() const; - - - static inline qreal dpiScaled(qreal value, qreal dpi) { - static const qreal qstyleBaseDpi = 96; - return value * dpi / qstyleBaseDpi; - } - - static inline qreal dpiScaled(qreal value, const QPaintDevice *device) { - return dpiScaled(value, device->logicalDpiX()); - } - - static inline qreal dpiScaled(qreal value, const QStyleOption *option) { - return dpiScaled(value, calculateDpi(option)); - } - - static inline bool isMacSystemPalette(const QPalette &pal) { - Q_UNUSED(pal); -#if defined(Q_OS_MACOS) - const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette(); - if (themePalette && themePalette->color(QPalette::Normal, QPalette::Highlight) == - pal.color(QPalette::Normal, QPalette::Highlight) && - themePalette->color(QPalette::Normal, QPalette::HighlightedText) == - pal.color(QPalette::Normal, QPalette::HighlightedText)) - return true; -#endif - return false; - } - - static inline QColor highlight(const QPalette &pal) { - if (isMacSystemPalette(pal)) - return QColor(60, 140, 230); - return pal.color(QPalette::Highlight); - } - - static inline QColor highlightedOutline(const QPalette &pal) { - QColor highlightedOutline = highlight(pal).darker(125); - if (highlightedOutline.value() > 160) - highlightedOutline.setHsl(highlightedOutline.hue(), highlightedOutline.saturation(), 160); - return highlightedOutline; - } - - static inline QColor getOutline(const QPalette &pal) { - if (pal.window().style() == Qt::TexturePattern) - return QColor(0, 0, 0, 160); - return pal.window().color().darker(140); - } - - static inline QColor getButtonColor(const QPalette &pal) { - QColor buttonColor = pal.button().color(); - int val = qGray(buttonColor.rgb()); - buttonColor = buttonColor.lighter(100 + qMax(1, (180 - val)/6)); - buttonColor.setHsv(buttonColor.hue(), buttonColor.saturation() * 0.75, buttonColor.value()); - return buttonColor; - } - - static inline QColor innerContrastLine() { - return QColor(255, 255, 255, 30); - } - - static inline QPixmap styleCachePixmap(const QSize &size, qreal pixelRatio) { - //not api - QPixmap cachePixmap = QPixmap(size * pixelRatio); - cachePixmap.setDevicePixelRatio(pixelRatio); - cachePixmap.fill(Qt::transparent); - return cachePixmap; - } - - static inline QColor backgroundColor(const QPalette &pal, const QWidget* widget) - { - #if QT_CONFIG(scrollarea) - if (qobject_cast(widget) && widget->parent() && - qobject_cast(widget->parent()->parent())) - return widget->parentWidget()->parentWidget()->palette().color(QPalette::Base); - #else - Q_UNUSED(widget); - #endif - return pal.color(QPalette::Base); - } - - static inline QPixmap svg2Pixmap(const QString& svgContent, - const QSize& size, - QPainter::CompositionMode mode = QPainter::CompositionMode_SourceOver) - { - QSvgRenderer rr(svgContent); - QImage image(size.width(), size.height(), QImage::Format_ARGB32); - QPainter painter(&image); - painter.setCompositionMode(mode); - image.fill(Qt::transparent); - rr.render(&painter); - return QPixmap::fromImage(image); - } - - static inline QScreen* getCurrentScreen() { - //note: Using cursor pos as screen detector. Flawed. - QPoint cursorPos = QCursor::pos(); - - for (QScreen *screen : QGuiApplication::screens()) { - QRect screenRect = screen->geometry(); - if (screenRect.contains(cursorPos)) { - return screen; - } - } - - return QGuiApplication::primaryScreen(); - } - -} - diff --git a/src/qt/qtvisuals.h b/src/qt/qtvisuals.h deleted file mode 100644 index 8902ed1..0000000 --- a/src/qt/qtvisuals.h +++ /dev/null @@ -1,903 +0,0 @@ -#pragma once - -#include "qtcommon.h" -#include "meterslider.h" - -using namespace StylingHelper; - -class MixerStyle : public QProxyStyle { - -public: - using QProxyStyle::QProxyStyle; - - //void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, - // QPainter *painter, const QWidget *widget) const override; - //Click on slider = move handle to click pos - int styleHint(QStyle::StyleHint hint, const QStyleOption* option = 0, const QWidget* widget = 0, - QStyleHintReturn* returnData = 0) const { - if (hint == QStyle::SH_Slider_AbsoluteSetButtons) - return (Qt::LeftButton | Qt::MiddleButton | Qt::RightButton); - return baseStyle()->styleHint(hint, option, widget, returnData); - } - - QRect subControlRect(ComplexControl control, - const QStyleOptionComplex *option, - SubControl subControl, - const QWidget *widget) const { - QRect rect = QCommonStyle::subControlRect(CC_Slider, option, subControl, widget); - - switch (control) { -#if QT_CONFIG(slider) - case CC_MeterSlider: - if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { - int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); - switch (subControl) { - case SC_SliderHandle: { - const bool bothTicks = (slider->tickPosition & QSlider::TicksBothSides) == QSlider::TicksBothSides; - if (slider->orientation == Qt::Horizontal) { - rect.setHeight(baseStyle()->pixelMetric(PM_SliderThickness, option, widget)); - rect.setWidth(baseStyle()->pixelMetric(PM_SliderLength, option, widget)); - int centerY = slider->rect.center().y() - rect.height() / 2; - if (!bothTicks) { - if (slider->tickPosition & QSlider::TicksAbove) - centerY += tickSize; - if (slider->tickPosition & QSlider::TicksBelow) - centerY -= tickSize - 1; - } - rect.moveTop(centerY); - } else { - rect.setWidth(baseStyle()->pixelMetric(PM_SliderThickness, option, widget)); - rect.setHeight(baseStyle()->pixelMetric(PM_SliderLength, option, widget)); - int centerX = slider->rect.center().x() - rect.width() / 2; - if (!bothTicks) { - if (slider->tickPosition & QSlider::TicksAbove) - centerX += tickSize; - if (slider->tickPosition & QSlider::TicksBelow) - centerX -= tickSize - 1; - } - rect.moveLeft(centerX); - } - } - break; - case SC_SliderGroove: { - QPoint grooveCenter = slider->rect.center(); - //rect.setWidth(std::abs(grooveCenter.x()) * 2); - const int grooveThickness = dpiScaled(7, option); //QStyleHelper::dpiScaled(7, option); - const bool bothTicks = (slider->tickPosition & QSlider::TicksBothSides) == QSlider::TicksBothSides; - if (slider->orientation == Qt::Horizontal) { - rect.setHeight(grooveThickness); - if (!bothTicks) { - if (slider->tickPosition & QSlider::TicksAbove) - grooveCenter.ry() += tickSize; - if (slider->tickPosition & QSlider::TicksBelow) - grooveCenter.ry() -= tickSize - 1; - } - } else { - rect.setWidth(grooveThickness); - if (!bothTicks) { - if (slider->tickPosition & QSlider::TicksAbove) - grooveCenter.rx() += tickSize; - if (slider->tickPosition & QSlider::TicksBelow) - grooveCenter.rx() -= tickSize - 1; - } - } - rect.moveCenter(grooveCenter); - break; - } - default: - break; - } - } - return rect; - break; -#endif // QT_CONFIG(slider) -#if QT_CONFIG(scrollbar) - case CC_ScrollBar: - if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(option)) { - QRect scrollBarRect = scrollbar->rect; - const uint64_t offset = 7; - scrollBarRect.setWidth(scrollBarRect.width() / 2); - scrollBarRect.setHeight(scrollBarRect.height() - 15); - int maxlen = ((scrollbar->orientation == Qt::Horizontal) ? - scrollBarRect.width() : scrollBarRect.height()); - int sliderlen; - - // calculate slider length - if (scrollbar->maximum != scrollbar->minimum) { - uint range = scrollbar->maximum - scrollbar->minimum; - sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep); - - int slidermin = baseStyle()->pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget); - if (sliderlen < slidermin || range > INT_MAX / 2) - sliderlen = slidermin; - if (sliderlen > maxlen) - sliderlen = maxlen; - } else { - sliderlen = maxlen; - } - - int sliderstart = sliderPositionFromValue(scrollbar->minimum, - scrollbar->maximum, - scrollbar->sliderPosition, - maxlen - sliderlen, - scrollbar->upsideDown); - - switch (subControl) { - /* - * case SC_ScrollBarSubLine: // top/left button - * if (scrollbar->orientation == Qt::Horizontal) { - * int buttonWidth = qMin(scrollBarRect.width() / 2, sbextent); - * rect.setRect(0, 0, buttonWidth, scrollBarRect.height()); - * } else { - * int buttonHeight = qMin(scrollBarRect.height() / 2, sbextent); - * rect.setRect(0, 0, scrollBarRect.width(), buttonHeight); - * } - * break; - * case SC_ScrollBarAddLine: // bottom/right button - * if (scrollbar->orientation == Qt::Horizontal) { - * int buttonWidth = qMin(scrollBarRect.width()/2, sbextent); - * rect.setRect(scrollBarRect.width() - buttonWidth, 0, buttonWidth, scrollBarRect.height()); - * } else { - * int buttonHeight = qMin(scrollBarRect.height()/2, sbextent); - * rect.setRect(0, scrollBarRect.height() - buttonHeight, scrollBarRect.width(), buttonHeight); - * } - * break; - */ - case SC_ScrollBarSubPage: // between top/left button and slider - if (scrollbar->orientation == Qt::Horizontal) - rect.setRect(0, 0, sliderstart, scrollBarRect.height()); - else - rect.setRect(0, 0, scrollBarRect.width(), sliderstart); - break; - case SC_ScrollBarAddPage: // between bottom/right button and slider - if (scrollbar->orientation == Qt::Horizontal) - rect.setRect(sliderstart + sliderlen, 0, - maxlen - sliderstart - sliderlen, scrollBarRect.height()); - else - rect.setRect(0, sliderstart + sliderlen, scrollBarRect.width(), - maxlen - sliderstart - sliderlen); - break; - case SC_ScrollBarGroove: - if (scrollbar->orientation == Qt::Horizontal) - rect.setRect(offset, 0, scrollBarRect.width(), - scrollBarRect.height()); - else - rect.setRect(0, offset, scrollBarRect.width(), - scrollBarRect.height() ); - break; - case SC_ScrollBarSlider: - if (scrollbar->orientation == Qt::Horizontal) - rect.setRect(sliderstart + offset, 0, sliderlen, scrollBarRect.height()); - else - rect.setRect(0, sliderstart + offset, scrollBarRect.width(), sliderlen); - break; - default: - break; - } - rect = visualRect(scrollbar->direction, scrollBarRect, rect); - return rect; - } - break; -#endif // QT_CONFIG(scrollbar) - default: - return baseStyle()->subControlRect(control, option, subControl, widget); - break; - } - - return QRect(); - - } - - void drawControl(ControlElement element, const QStyleOption *opt, - QPainter *p, const QWidget *widget) const - { - switch(element) { - case CE_ExtendedCheckBox: - if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { - QStyleOptionButton subopt = *btn; - subopt.rect = subElementRect(SE_CheckBoxIndicator, btn, widget); - //proxy()->drawPrimitive(PE_IndicatorCheckBox, &subopt, p, widget); - subopt.rect = subElementRect(SE_CheckBoxContents, btn, widget); - - //proxy()->drawControl(CE_CheckBoxLabel, &subopt, p, widget); - int alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter); - - if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget)) - alignment |= Qt::TextHideMnemonic; - QPixmap pix; - QRect textRect = btn->rect; - if (!btn->icon.isNull()) { - pix = btn->icon.pixmap(btn->iconSize, StylingHelper::getCurrentScreen()->devicePixelRatio(), - QIcon::Mode::Normal, btn->state & State_On ? QIcon::On : QIcon::Off); - proxy()->drawItemPixmap(p, btn->rect, alignment, pix); - if (btn->direction == Qt::RightToLeft) - textRect.setRight(textRect.right() - btn->iconSize.width() - 4); - else - textRect.setLeft(textRect.left() + btn->iconSize.width() + 4); - } - if (!btn->text.isEmpty()){ - proxy()->drawItemText(p, textRect, alignment | Qt::TextShowMnemonic, - btn->palette, btn->state & State_Enabled, btn->text, QPalette::WindowText); - } - // - if (btn->state & State_HasFocus) { - QStyleOptionFocusRect fropt; - fropt.QStyleOption::operator=(*btn); - fropt.rect = subElementRect(SE_CheckBoxFocusRect, btn, widget); - proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); - } - } - default: - baseStyle()->drawControl(element, opt, p, widget); - break; - } - } - - void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, - QPainter *painter, const QWidget *widget) const { - QColor outline; - switch (cc) { - #if QT_CONFIG(slider) - case CC_MeterSlider: - if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { - const qreal dpr = painter->device()->devicePixelRatio(); - const QColor buttonColor = getButtonColor(option->palette); - QRect groove = this->subControlRect(static_cast(CC_MeterSlider), option, SC_SliderGroove, widget); - QRect handle = this->subControlRect(static_cast(CC_MeterSlider), option, SC_SliderHandle, widget); - - bool horizontal = slider->orientation == Qt::Horizontal; - bool ticksAbove = slider->tickPosition & QSlider::TicksAbove; - bool ticksBelow = slider->tickPosition & QSlider::TicksBelow; - QColor activeHighlight = highlight(option->palette); - QPixmap cache; - QBrush oldBrush = painter->brush(); - QPen oldPen = painter->pen(); - QColor shadowAlpha(Qt::black); - shadowAlpha.setAlpha(10); - - if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) - outline = highlightedOutline(option->palette); - - if ((option->subControls & SC_SliderGroove) && groove.isValid()) { - QColor grooveColor; - grooveColor.setHsv(buttonColor.hue(), - qMin(255, (int)(buttonColor.saturation())), - qMin(255, (int)(buttonColor.value()*0.9))); - QString groovePixmapName = "slider_groove" + QString::number(groove.width());//QStyleHelper::uniqueName("slider_groove"_L1, option, groove.size(), dpr); - QRect pixmapRect(0, 0, groove.width(), groove.height()); - - // draw background groove - if (!QPixmapCache::find(groovePixmapName, &cache)) { - cache = styleCachePixmap(pixmapRect.size(), dpr); - QPainter groovePainter(&cache); - groovePainter.setRenderHint(QPainter::Antialiasing, true); - groovePainter.translate(0.5, 0.5); - QLinearGradient gradient; - if (horizontal) { - gradient.setStart(pixmapRect.center().x(), pixmapRect.top()); - gradient.setFinalStop(pixmapRect.center().x(), pixmapRect.bottom()); - } - else { - gradient.setStart(pixmapRect.left(), pixmapRect.center().y()); - gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y()); - } - groovePainter.setPen(QPen(outline)); - gradient.setColorAt(0, grooveColor.darker(110)); - gradient.setColorAt(1, grooveColor.lighter(110));//palette.button().color().darker(115)); - groovePainter.setBrush(gradient); - groovePainter.drawRoundedRect(pixmapRect.adjusted(1, 1, -2, -2), 1, 1); - groovePainter.end(); - QPixmapCache::insert(groovePixmapName, cache); - } - painter->drawPixmap(groove.topLeft(), cache); - - // draw groove lines (vol + unattenuated vol) - const MeterSlider* widgetCast = qobject_cast(widget); - if (widgetCast) { - QRect clipRect; - //if (!groovePixmapName.isEmpty()) groovePixmapName += QLatin1String("_unattenuated"); - //groovePixmapName += "_unattenuated"_L1; - //lf (!QPixmapCache::find(groovePixmapName, &cache)) { - cache = styleCachePixmap(pixmapRect.size(), dpr); - QPainter groovePainter(&cache); - QLinearGradient gradient; - if (horizontal) { - gradient.setStart(pixmapRect.center().x(), pixmapRect.top()); - gradient.setFinalStop(pixmapRect.center().x(), pixmapRect.bottom()); - } - else { - gradient.setStart(pixmapRect.left(), pixmapRect.center().y()); - gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y()); - } - QColor highlight = QColor(30,30,30,100); //this->highlight(option->palette); - QColor highlightedoutline = highlight.darker(140); - QColor grooveOutline = outline; - if (qGray(grooveOutline.rgb()) > qGray(highlightedoutline.rgb())) - grooveOutline = highlightedoutline; - - float peakValue = ((MeterSlider*)widget)->peakValue; - groovePainter.setRenderHint(QPainter::Antialiasing, true); - groovePainter.translate(0.5, 0.5); - groovePainter.setPen(QPen(grooveOutline)); - gradient.setColorAt(0, highlight); - gradient.setColorAt(1, highlight.lighter(130)); - groovePainter.setBrush(gradient); - groovePainter.drawRoundedRect(pixmapRect.adjusted( - 1, 1, - -pixmapRect.width() + (pixmapRect.width() * peakValue), - -2), 1, 1); - groovePainter.setPen(innerContrastLine()); - groovePainter.setBrush(Qt::green); - double stepWidth = (double)widgetCast->width() * ((double)widgetCast->singleStep() / (widgetCast->maximum() - widgetCast->minimum())); - groovePainter.drawRoundedRect(pixmapRect.adjusted( - 1, 1, - -pixmapRect.width() + ((widgetCast->width() - ((widgetCast->maximum() - widgetCast->value()) * stepWidth)) * peakValue), - -2), 1, 1); - - groovePainter.end(); - //QPixmapCache::insert(groovePixmapName, cache); - //} - //} - if (horizontal) { - if (slider->upsideDown) - clipRect = QRect(handle.right(), groove.top(), groove.right() - handle.right(), groove.height()); - else - clipRect = QRect(groove.left() + 2, groove.top() + 2, - groove.right() - 2, 2); - } else { - if (slider->upsideDown) - clipRect = QRect(groove.left(), handle.bottom(), groove.width(), groove.height() - (handle.bottom() - slider->rect.top())); - else - clipRect = QRect(groove.left(), groove.top(), groove.width(), handle.top() - groove.top()); - } - painter->save(); - painter->setClipRect(clipRect.adjusted(0, 0, 1, 1), Qt::IntersectClip); - painter->drawPixmap(groove.topLeft(), cache); - painter->restore(); - } - } - if (option->subControls & SC_SliderTickmarks) { - painter->save(); - painter->translate(slider->rect.x(), slider->rect.y()); - painter->setPen(outline); - int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); - int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); - int interval = slider->tickInterval; - if (interval <= 0) { - interval = slider->singleStep; - if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, - available) - - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, - 0, available) < 3) - interval = slider->pageStep; - } - if (interval <= 0) - interval = 1; - - int v = slider->minimum; - int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); - QVector lines; - while (v <= slider->maximum + 1) { - if (v == slider->maximum + 1 && interval == 1) - break; - const int v_ = qMin(v, slider->maximum); - int pos = sliderPositionFromValue(slider->minimum, slider->maximum, - v_, (horizontal - ? slider->rect.width() - : slider->rect.height()) - len, - slider->upsideDown) + len / 2; - int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0); - - if (horizontal) { - if (ticksAbove) { - lines += QLine(pos, slider->rect.top() + extra, - pos, slider->rect.top() + tickSize); - } - if (ticksBelow) { - lines += QLine(pos, slider->rect.bottom() - extra, - pos, slider->rect.bottom() - tickSize); - } - } else { - if (ticksAbove) { - lines += QLine(slider->rect.left() + extra, pos, - slider->rect.left() + tickSize, pos); - } - if (ticksBelow) { - lines += QLine(slider->rect.right() - extra, pos, - slider->rect.right() - tickSize, pos); - } - } - // in the case where maximum is max int - int nextInterval = v + interval; - if (nextInterval < v) - break; - v = nextInterval; - } - painter->drawLines(lines); - painter->restore(); - } - // draw handle - if ((option->subControls & SC_SliderHandle) ) { - QString handlePixmapName = "slider_handle" + QString::number(handle.height());//QStyleHelper::uniqueName("slider_handle"_L1, option,//handle.size(), dpr); - if (!QPixmapCache::find(handlePixmapName, &cache)) { - cache = styleCachePixmap(handle.size(), dpr); - QRect pixmapRect(0, 0, handle.width(), handle.height()); - QPainter handlePainter(&cache); - QRect gradRect = pixmapRect.adjusted(2, 2, -2, -2); - - // gradient fill - QRect r = pixmapRect.adjusted(1, 1, -2, -2); - QLinearGradient gradient = qt_fusion_gradient(gradRect, getButtonColor(option->palette),horizontal ? TopDown : FromLeft); - - handlePainter.setRenderHint(QPainter::Antialiasing, true); - handlePainter.translate(0.5, 0.5); - - handlePainter.setPen(Qt::NoPen); - handlePainter.setBrush(QColor(0, 0, 0, 40)); - handlePainter.drawRect(horizontal ? r.adjusted(-1, 2, 1, -2) : r.adjusted(2, -1, -2, 1)); - - handlePainter.setPen(QPen(getOutline(option->palette))); - if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) - handlePainter.setPen(QPen(highlightedOutline(option->palette))); - - handlePainter.setBrush(gradient); - handlePainter.drawRoundedRect(r, 2, 2); - handlePainter.setBrush(Qt::NoBrush); - handlePainter.setPen(innerContrastLine()); - handlePainter.drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2); - - QColor cornerAlpha = outline.darker(120); - cornerAlpha.setAlpha(80); - - //handle shadow - handlePainter.setPen(shadowAlpha); - handlePainter.drawLine(QPoint(r.left() + 2, r.bottom() + 1), QPoint(r.right() - 2, r.bottom() + 1)); - handlePainter.drawLine(QPoint(r.right() + 1, r.bottom() - 3), QPoint(r.right() + 1, r.top() + 4)); - handlePainter.drawLine(QPoint(r.right() - 1, r.bottom()), QPoint(r.right() + 1, r.bottom() - 2)); - - handlePainter.end(); - QPixmapCache::insert(handlePixmapName, cache); - } - - painter->drawPixmap(handle.topLeft(), cache); - - } - painter->setBrush(oldBrush); - painter->setPen(oldPen); - } - break; - case CC_ScrollBar: - painter->save(); - if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { - bool wasActive = false; - qreal expandScale = 1.0; - qreal expandOffset = -1.0; - QObject *styleObject = option->styleObject; - - QColor buttonColor = calculateButtonColor(option->palette); - QColor gradientStartColor = buttonColor.lighter(104); - QColor gradientStopColor = buttonColor.darker(102); - - bool transient = styleHint(SH_ScrollBar_Transient, option, widget); - bool horizontal = scrollBar->orientation == Qt::Horizontal; - bool sunken = scrollBar->state & State_Sunken; - - QRect scrollBarSubLine = subControlRect(cc, scrollBar, SC_ScrollBarSubLine, widget); - QRect scrollBarAddLine = subControlRect(cc, scrollBar, SC_ScrollBarAddLine, widget); - QRect scrollBarSlider = subControlRect(cc, scrollBar, SC_ScrollBarSlider, widget); - QRect scrollBarGroove = subControlRect(cc, scrollBar, SC_ScrollBarGroove, widget); - - QRect rect = option->rect; - outline = highlightedOutline(option->palette); - QColor alphaOutline = outline; - alphaOutline.setAlpha(180); - - QColor arrowColor = option->palette.windowText().color(); - //QColor arrowColor = QColor(188,143,143,100); - arrowColor.setAlpha(160); - - const QColor appBgColor = QGuiApplication::palette().window().color(); - const bool isDarkBg = appBgColor.red() < 128 && appBgColor.green() < 128 && appBgColor.blue() < 128; - - if (transient) { - if (horizontal) { - rect.setY(rect.y() + 4.5 - expandOffset); - scrollBarSlider.setY(scrollBarSlider.y() + 4.5 - expandOffset); - scrollBarGroove.setY(scrollBarGroove.y() + 4.5 - expandOffset); - - rect.setHeight(rect.height() * expandScale); - scrollBarGroove.setHeight(scrollBarGroove.height() * expandScale); - } else { - rect.setX(rect.x() + 4.5 - expandOffset); - scrollBarSlider.setX(scrollBarSlider.x() + 4.5 - expandOffset); - scrollBarGroove.setX(scrollBarGroove.x() + 4.5 - expandOffset); - - rect.setWidth(rect.width() * expandScale); - scrollBarGroove.setWidth(scrollBarGroove.width() * expandScale); - } - } - - // Paint groove - if ((!transient || scrollBar->activeSubControls || wasActive) && scrollBar->subControls & SC_ScrollBarGroove) { - QLinearGradient gradient(rect.center().x(), rect.top(), - rect.center().x(), rect.bottom()); - if (!horizontal) - gradient = QLinearGradient(rect.left(), rect.center().y(), - rect.right(), rect.center().y()); - if (!transient || !isDarkBg) { - gradient.setColorAt(0, buttonColor.darker(107)); - gradient.setColorAt(0.1, buttonColor.darker(105)); - gradient.setColorAt(0.9, buttonColor.darker(105)); - gradient.setColorAt(1, buttonColor.darker(107)); - } else { - gradient.setColorAt(0, appBgColor.lighter(157)); - gradient.setColorAt(0.1, appBgColor.lighter(155)); - gradient.setColorAt(0.9, appBgColor.lighter(155)); - gradient.setColorAt(1, appBgColor.lighter(157)); - } - - painter->save(); - //painter->fillRect(rect, gradient); - painter->setPen(Qt::NoPen); - painter->setPen(alphaOutline); - - QColor subtleEdge = alphaOutline; - subtleEdge.setAlpha(40); - painter->setPen(subtleEdge); - //painter->setBrush(Qt::NoBrush); - painter->setOpacity(0.3); - painter->setBrush(Qt::gray); - painter->drawRoundedRect(scrollBarGroove, 5, 5); - //painter->drawRoundedRect(scrollBarGroove, 5, 5); - painter->restore(); - } - - QRect pixmapRect = scrollBarSlider; - QColor highlightColor = option->palette.highlight().color(); - /* - * QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(), - * pixmapRect.center().x(), pixmapRect.bottom()); - * if (!horizontal) - * gradient = QLinearGradient(pixmapRect.left(), pixmapRect.center().y(), - * pixmapRect.right(), pixmapRect.center().y()); - */ - - //QLinearGradient highlightedGradient = gradient; - - QColor heldColor = 0xc4e3d7e0;//Qt::gray;//osh->isLightMode() ? Qt::white : Qt::black; - //gradient.setColorAt(0, option->palette.highlight().color()); - //gradient.setColorAt(1, option->palette.highlight().color()); - - //highlightedGradient.setColorAt(0, gradientStartColor.darker(102)); - //highlightedGradient.setColorAt(1, gradientStopColor.lighter(102)); - - // Paint slider - if (scrollBar->subControls & SC_ScrollBarSlider) { - log_debugcpp("Final scrollbar paint if"); - if (transient) { - QRect rect = scrollBarSlider.adjusted(horizontal ? 1 : 2, horizontal ? 2 : 1, -1, -1); - painter->setPen(Qt::NoPen); - painter->setBrush(isDarkBg ? lightShade() : darkShade()); - int r = qMin(rect.width(), rect.height()) / 2; - - painter->save(); - painter->setRenderHint(QPainter::Antialiasing, true); - painter->drawRoundedRect(rect, r, r); - painter->restore(); - } else { - QRect pixmapRect = scrollBarSlider; - painter->setPen(QPen(alphaOutline)); - if (option->state & State_Sunken - && scrollBar->activeSubControls & SC_ScrollBarSlider) - painter->setBrush(heldColor); - else if (option->state & State_MouseOver - && scrollBar->activeSubControls & SC_ScrollBarSlider) { - painter->setBrush(highlightColor); - } - else //if (!isDarkBg) - - if(!isDarkBg) - painter->setBrush(Qt::black); - else painter->setBrush(Qt::white); - //else - // painter->setBrush(heldColor); - - painter->drawRoundedRect(pixmapRect.adjusted(horizontal ? -1 : 0, horizontal ? 0 : -1, horizontal ? 0 : -1, horizontal ? -1 : 0), 5, 5); - - painter->setPen(innerContrastLine()); - painter->drawRoundedRect(scrollBarSlider.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, -1, -1), 5, 5); - - // Outer shadow - // painter->setPen(subtleEdge); - // if (horizontal) { - //// painter->drawLine(scrollBarSlider.topLeft() + QPoint(-2, 0), scrollBarSlider.bottomLeft() + QPoint(2, 0)); - //// painter->drawLine(scrollBarSlider.topRight() + QPoint(-2, 0), scrollBarSlider.bottomRight() + QPoint(2, 0)); - // } else { - //// painter->drawLine(pixmapRect.topLeft() + QPoint(0, -2), pixmapRect.bottomLeft() + QPoint(0, -2)); - //// painter->drawLine(pixmapRect.topRight() + QPoint(0, 2), pixmapRect.bottomRight() + QPoint(0, 2)); - // } - } - } - - /* - * // The SubLine (up/left) buttons - * if (!transient && scrollBar->subControls & SC_ScrollBarSubLine) { - * if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) - * painter->setBrush(gradientStopColor); - * else if ((scrollBar->activeSubControls & SC_ScrollBarSubLine)) - * painter->setBrush(highlightedGradient); - * else - * painter->setBrush(gradient); - * - * painter->setPen(Qt::NoPen); - * painter->drawRoundedRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0), 1, 1); - * painter->setPen(QPen(alphaOutline)); - * if (option->state & State_Horizontal) { - * painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, 0, horizontal ? 1 : 0, horizontal ? -1 : 0)); - * } else { - * painter->drawRoundedRect(scrollBarSubLine.adjusted(0, 0, horizontal ? 0 : -1, 0), 1, 1); - * } - * - * QRect upRect = scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, horizontal ? -2 : -1, horizontal ? -1 : -2); - * painter->setBrush(Qt::NoBrush); - * painter->setPen(innerContrastLine()); - * painter->drawRect(upRect); - * - * // Arrows - * Qt::ArrowType arrowType = Qt::UpArrow; - * if (option->state & State_Horizontal) - * arrowType = option->direction == Qt::LeftToRight ? Qt::LeftArrow : Qt::RightArrow; - * qt_fusion_draw_arrow(arrowType, painter, option, upRect, arrowColor); - * } - * - * // The AddLine (down/right) button - * if (!transient && scrollBar->subControls & SC_ScrollBarAddLine) { - * if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) - * painter->setBrush(gradientStopColor); - * else if ((scrollBar->activeSubControls & SC_ScrollBarAddLine)) - * painter->setBrush(midColor2); - * else - * painter->setBrush(gradient); - * - * painter->setPen(Qt::NoPen); - * painter->drawRect(scrollBarAddLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0)); - * painter->setPen(QPen(alphaOutline, 1)); - * if (option->state & State_Horizontal) { - * painter->drawRect(scrollBarAddLine.adjusted(horizontal ? -1 : 0, 0, horizontal ? -1 : 0, horizontal ? -1 : 0)); - * } else { - * painter->drawRect(scrollBarAddLine.adjusted(0, horizontal ? 0 : -1, horizontal ? 0 : -1, horizontal ? 0 : -1)); - * } - * - * QRect downRect = scrollBarAddLine.adjusted(1, 1, -1, -1); - * painter->setPen(innerContrastLine()); - * painter->setBrush(Qt::NoBrush); - * painter->drawRect(downRect); - * - * Qt::ArrowType arrowType = Qt::DownArrow; - * if (option->state & State_Horizontal) - * arrowType = option->direction == Qt::LeftToRight ? Qt::RightArrow : Qt::LeftArrow; - * qt_fusion_draw_arrow(arrowType, painter, option, downRect, arrowColor); - * } - */ - - } - painter->restore(); - break; - default: - baseStyle()->drawComplexControl(cc, option, painter, widget); -#endif // QT_CONFIG(slider) -} -} - -private: - enum Direction { - TopDown, - FromLeft, - BottomUp, - FromRight - }; - - static QLinearGradient qt_fusion_gradient(const QRect &rect, const QBrush &baseColor, Direction direction = TopDown) - { - int x = rect.center().x(); - int y = rect.center().y(); - QLinearGradient gradient; - switch (direction) { - case FromLeft: - gradient = QLinearGradient(rect.left(), y, rect.right(), y); - break; - case FromRight: - gradient = QLinearGradient(rect.right(), y, rect.left(), y); - break; - case BottomUp: - gradient = QLinearGradient(x, rect.bottom(), x, rect.top()); - break; - case TopDown: - default: - gradient = QLinearGradient(x, rect.top(), x, rect.bottom()); - break; - } - if (baseColor.gradient()) - gradient.setStops(baseColor.gradient()->stops()); - else { - QColor gradientStartColor = baseColor.color().lighter(124); - QColor gradientStopColor = baseColor.color().lighter(102); - gradient.setColorAt(0, gradientStartColor); - gradient.setColorAt(1, gradientStopColor); - // Uncomment for adding shiny shading - // QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 55); - // QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 45); - // gradient.setColorAt(0.5, midColor1); - // gradient.setColorAt(0.501, midColor2); - } - return gradient; - } - - QColor highlightedOutline(const QPalette &pal) const { - QColor highlightedOutline = highlight(pal);//.darker(25);//QColor(Qt::green); - if (highlightedOutline.value() > 160) - highlightedOutline.setHsl(highlightedOutline.hue(), highlightedOutline.saturation(), 160); - return highlightedOutline; - } - - QColor calculateButtonColor(const QPalette &pal) const { - QColor buttonColor = pal.button().color(); - int val = qGray(buttonColor.rgb()); - buttonColor = buttonColor.lighter(100 + qMax(1, (180 - val)/6)); - buttonColor.setHsv(buttonColor.hue(), buttonColor.saturation() * 0.75, buttonColor.value()); - return buttonColor; - } - - // Used for grip handles - QColor lightShade() const { - return QColor(255, 255, 255, 90); - } - - QColor darkShade() const { - return QColor(0, 0, 0, 60); - } - - QColor innerContrastLine() const { - return QColor(255, 255, 255, 30); - } - - static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50) { - const int maxFactor = 100; - QColor tmp = colorA; - tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor); - tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor); - tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor); - return tmp; - } - - - static void qt_fusion_draw_arrow(Qt::ArrowType type, QPainter *painter, const QStyleOption *option, const QRect &rect, const QColor &color) -{ - if (rect.isEmpty()) - return; - - const qreal dpi = calculateDpi(option); - const qreal dpr = painter->device()->devicePixelRatio(); - const int arrowWidth = int(dpiScaled(14, dpi)); - const int arrowHeight = int(dpiScaled(8, dpi)); - - const int arrowMax = qMin(arrowHeight, arrowWidth); - const int rectMax = qMin(rect.height(), rect.width()); - const int size = qMin(arrowMax, rectMax); - - QPixmap cachePixmap; - const QString cacheKey = "fusion-arrow"_L1 + QString::number(rect.size().width()) + QString::number(rect.size().height()) + QString::number(type); - - if (!QPixmapCache::find(cacheKey, &cachePixmap)) { - cachePixmap = styleCachePixmap(rect.size(), dpr); - QPainter cachePainter(&cachePixmap); - - QRectF arrowRect; - arrowRect.setWidth(size); - arrowRect.setHeight(arrowHeight * size / arrowWidth); - if (type == Qt::LeftArrow || type == Qt::RightArrow) - arrowRect = arrowRect.transposed(); - arrowRect.moveTo((rect.width() - arrowRect.width()) / 2.0, - (rect.height() - arrowRect.height()) / 2.0); - - std::array triangle; - switch (type) { - case Qt::DownArrow: - triangle = {arrowRect.topLeft(), arrowRect.topRight(), QPointF(arrowRect.center().x(), arrowRect.bottom())}; - break; - case Qt::RightArrow: - triangle = {arrowRect.topLeft(), arrowRect.bottomLeft(), QPointF(arrowRect.right(), arrowRect.center().y())}; - break; - case Qt::LeftArrow: - triangle = {arrowRect.topRight(), arrowRect.bottomRight(), QPointF(arrowRect.left(), arrowRect.center().y())}; - break; - default: - triangle = {arrowRect.bottomLeft(), arrowRect.bottomRight(), QPointF(arrowRect.center().x(), arrowRect.top())}; - break; - } - - cachePainter.setPen(Qt::NoPen); - cachePainter.setBrush(color); - cachePainter.setRenderHint(QPainter::Antialiasing); - cachePainter.drawPolygon(triangle.data(), int(triangle.size())); - - QPixmapCache::insert(cacheKey, cachePixmap); - } - - painter->drawPixmap(rect, cachePixmap); -} - -}; - - - -/* - * void MixerStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, - * QPainter *p, const QWidget *widget) const { - * switch (cc) { - * #if QT_CONFIG(slider) - * case CC_Slider: - * if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { - * if (slider->subControls == SC_SliderTickmarks) { - * int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); - * int ticks = slider->tickPosition; - * int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); - * int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); - * int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); - * int interval = slider->tickInterval; - * if (interval <= 0) { - * interval = slider->singleStep; - * if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, - * available) - * - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, - * 0, available) < 3) - * interval = slider->pageStep; - * } - * if (!interval) - * interval = 1; - * int fudge = len / 2; - * int pos; - * // Since there is no subrect for tickmarks do a translation here. - * p->save(); - * p->translate(slider->rect.x(), slider->rect.y()); - * p->setPen(slider->palette.windowText().color()); - * int v = slider->minimum; - * while (v <= slider->maximum + 1) { - * if (v == slider->maximum + 1 && interval == 1) - * break; - * const int v_ = qMin(v, slider->maximum); - * pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, - * v_, available) + fudge; - * if (slider->orientation == Qt::Horizontal) { - * if (ticks & QSlider::TicksAbove) - * p->drawLine(pos, 0, pos, tickOffset - 2); - * if (ticks & QSlider::TicksBelow) - * p->drawLine(pos, tickOffset + thickness + 1, pos, - * slider->rect.height()-1); - * } else { - * if (ticks & QSlider::TicksAbove) - * p->drawLine(0, pos, tickOffset - 2, pos); - * if (ticks & QSlider::TicksBelow) - * p->drawLine(tickOffset + thickness + 1, pos, - * slider->rect.width()-1, pos); - * } - * // in the case where maximum is max int - * int nextInterval = v + interval; - * if (nextInterval < v) - * break; - * v = nextInterval; - * } - * } - * } - * p->restore(); - * break; - * default: - * baseStyle()->drawComplexControl(cc, opt, p, widget); - * break; - * } - * #endif // QT_CONFIG(slider) - * } - */ - -//void MixerStyle:: - diff --git a/src/qtestmain.cpp b/src/qtestmain.cpp index d264d01..15d18fc 100644 --- a/src/qtestmain.cpp +++ b/src/qtestmain.cpp @@ -1,145 +1,37 @@ +//#include +//#include + +//#include + +//#define QTBLESSED +#include +#include + //#include "contclasses.h" -#define INIT_FILELOG -#include "qtcommon.h" #include "qtclasses.h" -#include "qtvisuals.h" -#include "settings.h" +#include "global.h" -OverseerHandler *osh = nullptr; -ini::UserSettings *set = nullptr; - -bool startupRun = false; -bool onStartup = false; -char* userSettingsPath = nullptr; - -QApplication* createApplication(int &argc, char *argv[]) { +OverseerHandler *osh = new OverseerHandler(); + +QApplication* createApplication(int &argc, char *argv[]) +{ return new QApplication(argc, argv); } -bool isInstanceRunning(QString appName) { - QLocalSocket socket; - socket.connectToServer(appName); - bool isOpen = socket.isOpen(); - socket.close(); - return isOpen; -} - -QLocalServer* startInstanceServer(QString appName) { - QLocalServer* server = new QLocalServer; - server->setSocketOptions(QLocalServer::WorldAccessOption); - server->listen(appName); - return server; -} - -void closeDebugFileLog() { - close_file_log_buffer(); -} - -void parseCmdArgs(int argc, char* argv[]) { - if(argc == 1) return; - //char* configPath = nullptr; - char* arg[] = { (char*)"--config-path=", (char*)"--change-startup" }; - - for (int i = 1; i < argc; i++) { - if(strstr(argv[i], arg[0])) { - userSettingsPath = argv[i] + strlen(arg[0]); - } - - if(strstr(argv[i], arg[1])) { - if (++i >= argc) return; - switch (argv[i][0]) { - case '0': - startupRun = true; - onStartup = false; - break; - case '1': - startupRun = true; - onStartup = true; - break; - default: - break; - } - return; - } - } - return; -} - -/* set_terminate - * void closeDebugFileLog2() { - * close_file_log_buffer(); - * abort(); - * } - */ int main (int argc, char* argv[]) { - /* - * Debug: logging report file - */ - initialize_file_log(); - atexit(closeDebugFileLog); - - QApplication::setStyle(new MixerStyle(QStyleFactory::create("Fusion"))); - //QApplication::setFont(font); - //QPalette palette = QGuiApplication::palette(); - - //palette.setColor(QPalette::Active, QPalette::Highlight, QColor(255, 192, 203, 200)); - //QColor(30,30,30,100)); - //QGuiApplication::setPalette(palette); - osh = new OverseerHandler(); - osh->populateSystemValues(); - - /* - * Arg parsing: (admin?) startup change run - */ - parseCmdArgs(argc, argv); - if (startupRun) { - if (!isInstanceRunning(PIPE_NAME)) exit(-1); - //if (startupChangeInfo->permissionChangeScope == NONE) exit(-1); - osh->updateStartupConfig(onStartup); - exit(0); - } - - //Check if running - //https://stackoverflow.com/questions/48060989/qt-show-application-if-currently-running - if (!isInstanceRunning(PIPE_NAME)) - startInstanceServer(PIPE_NAME); - else exit(0); - - /* - * Config file init - */ - if (userSettingsPath) - set = ini::UserSettings::createSettings(userSettingsPath, true); - - if (set) - OverseerHandler::settingsPath = std::string(userSettingsPath); - else setConfigDirToDefaults(); - - StylingHelper::setBackgroundColor(osh->isLightMode()); - //qRegisterMetaType(); - + //QApplication::setStyle("windowsvista"); //INIT CONT log_debugcpp("main init"); - osh->createEndpointHandlers(); + osh->reloadEndpointHandlers(); log_debugcpp("Reloaded endpoint handlers"); //INIT FRONT QScopedPointer app(createApplication(argc, argv)); - MainWindow window = MainWindow(); - //window.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::QSizePolicy::MinimumExpanding) - QApplication::setQuitOnLastWindowClosed(false); - - DarkModeEventFilter* darkMode = new DarkModeEventFilter(); - QAbstractEventDispatcher::instance()->installNativeEventFilter(darkMode); - - /* - * QFile styleFile(":/assets/style.qss"); - * styleFile.open(QFile::ReadOnly); - * QString styleSheet { QLatin1String(styleFile.readAll()) }; - */ - + //window.setEndpointHandlers(ephs); + app->setStyle("windowsvista"); + window.show(); return app->exec(); } diff --git a/src/settings.cpp b/src/settings.cpp deleted file mode 100644 index f76e73c..0000000 --- a/src/settings.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include "settings.h" -#include "msinclude.h" - -namespace ini { - - wchar_t* Utf8toUtf16(const char* str, uint64_t* size = nullptr) { - if(!str || str[0] == '\0') return nullptr; - int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); - if(size) *size = sizeNeeded; - wchar_t* utf16 = (wchar_t*)calloc(sizeNeeded, sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, str, -1, utf16, sizeNeeded); - return utf16; - } - - - - UserSettings::UserSettings(char* textContents) { - //Parsing values - bool isCRLF = false; - char *curLine = textContents; - char *separator = nullptr, *key = nullptr, *value = nullptr; - while(curLine) { - char* nextLine = strchr(curLine, '\n'); - if(nextLine == curLine + 1 || nextLine == curLine + 2) - goto nextIteration; - if (nextLine && (isCRLF || *(nextLine - 1) == '\r')) { - isCRLF = true; - *(nextLine - 1) = '\0'; - } else if (nextLine) *nextLine = '\0'; // temporarily terminate the current line - log_debugcpp("[SET] curLine: " + std::string(curLine) + " "); - - separator = strchr(curLine, '='); - if(!separator) - goto nextIteration; - *separator = '\0'; - key = trimAndAllocate(curLine); - value = trimAndAllocate(separator + 1); - values.try_emplace(key, value); - log_debugcpp("[SET] ini Map size: " + std::to_string(values.size())); - *separator = '='; - - nextIteration: - if (nextLine) { // then restore newline-char, just to be tidy - if (isCRLF) - *(nextLine - 1) = '\r'; - else *nextLine = '\n'; - } - curLine = nextLine ? (nextLine + 1) : NULL; - } - free(textContents); - } - - char* const UserSettings::getValue(char* key, uint64_t len) { - if (auto search = values.find(key); search != values.end()) - return (char* const) search->second; - return nullptr; - } - - void UserSettings::setValue(char* key, char* value, uint64_t valueSize, uint64_t keySize) { - char *newValue, *newKey; - if (auto search = values.find(key); search != values.end()) { - if(!(strcmp(value, search->second))) return; - newValue = (char*)calloc(valueSize, sizeof(char)); - if (!(search->second == pos || search->second == neg)) { - free(search->second); - } - search->second = newValue; - return; - } - - newValue = (char*)calloc(valueSize, sizeof(char)); - newKey = (char*)calloc(keySize, sizeof(char)); - values.insert(std::make_pair(newKey, newValue)); - return; - } - - void UserSettings::setValue(char* key, bool value, uint64_t keySize) { - char *newKey; - log_debugcpp("[SET] Pos value: " + std::to_string((intptr_t)pos)); - log_debugcpp("[SET] Neg value: " + std::to_string((intptr_t)neg)); - if (auto search = values.find(key); search != values.end()) { - log_debugcpp("[SET] Previous value: " + std::to_string((intptr_t)values[key])); - if (!(search->second == pos || search->second == neg)) { - free(search->second); - } - if (value) - search->second = pos; - else search->second = neg; - return; - } - - newKey = (char*)calloc(keySize, sizeof(char)); - memcpy(newKey, key, keySize * sizeof(char)); - values.insert(std::make_pair(newKey, value ? pos : neg)); - return; - } - - bool UserSettings::save(const char* path) { - if(!path) return false; - uint64_t convertedPathSize = 0; - wchar_t* utf16Path = Utf8toUtf16(path, &convertedPathSize); - if(!utf16Path) return false; - - #define releaseBeforeReturn() do { \ - CloseHandle(settingsHandle); \ - settingsHandle = nullptr; \ - free(utf16Path); \ - free(text); \ - } while(0) - - //We initially reserve 1024B for flushing. If storage is exceeded, more same-size chunks are allocated - const uint64_t chunkSize = 1024; - char* text = (char*)calloc(chunkSize, sizeof(char)); - uint64_t mapSize = values.size(); - uint64_t chunks = 1; - uint64_t keySize = 0, valueSize = 0, totalSize = 0, previousStepSize = 0; - //for(std::pair entry : values) { - std::unordered_map::iterator it; - for (it = values.begin(); it != values.end(); it++) { - keySize = strlen(it->first); - valueSize = strlen(it->second); - totalSize += valueSize + keySize + (it == values.begin() ? 1 : 2); //newline and separator - - if(totalSize > (chunkSize * chunks)) { - text = (char*)realloc(text, (++chunks * chunkSize)); - } - - if(it != values.begin()) - memcpy(text + previousStepSize++, "\n", sizeof(char)); - memcpy(text + previousStepSize, it->first, sizeof(char) * keySize); - memcpy(text + previousStepSize + keySize, "=", sizeof(char)); - memcpy(text + previousStepSize + 1 + keySize, it->second, sizeof(char) * valueSize); - - previousStepSize = totalSize; - } - - HANDLE settingsHandle = nullptr; - settingsHandle = CreateFile2( - utf16Path, - GENERIC_READ | GENERIC_WRITE, - 0, - CREATE_ALWAYS, - NULL); - if(settingsHandle == INVALID_HANDLE_VALUE) { - log_debugcpp("[SET] Can't save to file: " + std::to_string(GetLastError())); - releaseBeforeReturn(); - return false; - } - - DWORD bytesWritten; - BOOL writeSuccess = WriteFile( - settingsHandle, - text, - totalSize, - &bytesWritten, - nullptr - ); - - releaseBeforeReturn(); - if (writeSuccess == TRUE) return true; - else return false; - - return false; - #undef releaseBeforeReturn - } - - UserSettings::~UserSettings() { - //if(textContents) free(textContents); - for(std::pair entry : values) { - free(entry.first); - if (!(entry.second == pos || entry.second == neg)) - free(entry.second); - } - } - - UserSettings* UserSettings::createSettings(const char* path, bool create) { - if(!path) return nullptr; - wchar_t* utf16Path = Utf8toUtf16(path); - if(!utf16Path) return nullptr; - - #define releaseBeforeReturn() do { \ - CloseHandle(settingsHandle); \ - settingsHandle = nullptr; \ - free(utf16Path); \ - } while(0) - - char* textContents; - HANDLE settingsHandle = nullptr; - settingsHandle = CreateFile2( - utf16Path, - GENERIC_READ | GENERIC_WRITE, - 0, - (create ? OPEN_ALWAYS : OPEN_EXISTING), - NULL); - if(settingsHandle == INVALID_HANDLE_VALUE) { - std::string createString = std::string(create ? (char*)"create" : (char*)"open"); - log_debugcpp("[SET] Can't create settings file: " + std::to_string(GetLastError())); - log_debugcpp("[SET] Can't " + createString + \ - " settings file on: " + std::string(path) + \ - ", error: " + std::to_string(GetLastError())); - releaseBeforeReturn(); - return nullptr; - } - - //Calculating file size and reading file - uint64_t fileSize; - LARGE_INTEGER fileSizeStruct; - if(!GetFileSizeEx(settingsHandle, &fileSizeStruct)) { - releaseBeforeReturn(); - return nullptr; - } - fileSize = fileSizeStruct.QuadPart; - - uint32_t bytesRead = 0; - uint64_t textContentsSize = fileSize + 1; - textContents = (char*)calloc(textContentsSize, sizeof(char)); - if (ReadFile(settingsHandle, textContents, fileSize, - (LPDWORD)&bytesRead, NULL) != TRUE) { - releaseBeforeReturn(); - return nullptr; - } - - releaseBeforeReturn(); - return new UserSettings(textContents); - - //textContents.assign(tempTextContents); - //free(tempTextContents); - #undef releaseBeforeReturn - } - -} diff --git a/src/settings.h b/src/settings.h deleted file mode 100644 index 9974507..0000000 --- a/src/settings.h +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once -#include "global.h" - -namespace ini { - - //Trims spaces, LF and CRLF - static inline char* trimAndAllocate(const char* in, uint64_t len = 0) { - if (!in) return nullptr; - - uint64_t startingPos = 0, lastPos = 0; - bool foundStart = false; - for(int i = 0; ;i++) { - char c = in[i]; - if ((len > 0 && startingPos == (len - 1)) || (len > 0 && lastPos == (len - 1))) return nullptr; - if ((c != ' ' || c != '\r' || c != '\n') && !foundStart) { - foundStart = true; - lastPos = startingPos; - } - if (foundStart && (c == ' ' || c == '\r' || c == '\n')) { - break; - } - if(!foundStart) - startingPos++; - else lastPos++; - } - if(!(lastPos - startingPos)) return nullptr; - - char* trimmedString = (char*)calloc(lastPos - startingPos + 1, sizeof(char)); - memcpy(trimmedString, in + startingPos, lastPos - startingPos); - return trimmedString; - } - - struct Djb12Hasher { - size_t operator()(char* str) const { - unsigned long hash = 5381; - int c; - - while (c = *str++) - hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ - - return hash; - } - }; - - struct StrcmpEqual { - bool operator()(char* key1, char* key2) const { - return (!strcmp(key1, key2)); - } - }; - -class UserSettings { - - public: - static UserSettings* createSettings(const char* path = nullptr, bool create = false); - ~UserSettings(); - - char* const getValue(char* key, uint64_t len = 0); - void setValue(char* key, char* value, uint64_t valueSize, uint64_t keySize); //'\0' included - void setValue(char* key, bool value, uint64_t keySize); //'\0' included - - bool save(const char* path); - protected: - - private: - UserSettings(char* text = nullptr); - std::unordered_map values; - char* pos = "true"; - char* neg = "false"; -}; - -}