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 index 2206a8a..8b63932 100644 --- a/assets.qrc +++ b/assets.qrc @@ -1,10 +1,5 @@ - assets/selawk.ttf - assets/notificationAreaIcon.png - assets/style.qss - assets/logo.ico - assets/mute.svg - assets/unmute.svg + assets/notificationAreaIcon.png diff --git a/assets/SoundVolumeView.exe b/assets/SoundVolumeView.exe new file mode 100644 index 0000000..4c7a7d2 Binary files /dev/null and b/assets/SoundVolumeView.exe differ 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/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..2c8ac1c 100644 --- a/bueno.bat +++ b/bueno.bat @@ -1,7 +1,4 @@ -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 +copy /Y /B .\assets\SoundVolumeView.exe .\build\debug +copy /Y /B .\assets\SoundVolumeView.exe .\build\release +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..046d8d8 100644 --- a/qtest.pro +++ b/qtest.pro @@ -1,28 +1,16 @@ -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= -} +QMAKE_CXXFLAGS += --target=x86_64-w64-mingw32 -g -gcodeview +QMAKE_LFLAGS += --target=x86_64-w64-mingw32 -g -Wl,-pdb= -v +LIBS += -LC:/capybara/libclang/x86_64-w64-mingw32/lib -lWinmm -lodbc32 -lodbccp32 -luuid -loleaut32 -lole32 -lshell32 -ladvapi32 -lcomdlg32 -lwinspool -lgdi32 -luser32 -lkernel32 +#"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" -luuid -loleaut32 -lole32 -lshell32 -ladvapi32 -lcomdlg32 -lwinspool -lgdi32 -luser32 -lkernel32 +DEFINES += DEBUG QT_LOGGING_TO_CONSOLE=1 WIN32_LEAN_AND_MEAN +CONFIG += debug -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 +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 backsessionclasses.cpp contclasses.cpp contsessionclasses.cpp +HEADERS += qtclasses.h backlasses.h backsessionclasses.h contclasses.h contsessionclasses.h global.h debug.h backfuncs.h ipolicyconfig.h msinclude.h +RESOURCES = assets.qrc -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 +#DESTDIR += "build" diff --git a/src/back/backlasses.cpp b/src/back/backlasses.cpp index 74af6a0..8960c49 100644 --- a/src/back/backlasses.cpp +++ b/src/back/backlasses.cpp @@ -1,7 +1,5 @@ -#include "backlasses.h" -#include "backfuncs.h" - -using namespace Environment; +#include +#include EndpointNewSessionCallback::EndpointNewSessionCallback(EndpointHandler* eph){ this->eph = eph; @@ -41,27 +39,23 @@ HRESULT EndpointNewSessionCallback::QueryInterface(REFIID riid, VOID **ppvInterf HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSession) { if (eph->getFlow() == Flows::FLOW_CAPTURE) return S_OK; + HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); IAudioSessionControl2* sessionControl; //ISimmpleAudioVolume* sessionVolume; if (FAILED(NewSession->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl))) { log_wdebugcpp(L"no nueva sesion......"); }; if (sessionControl) { + sessionControl->AddRef(); + //sessionControl->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&sessionVolume); 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); + eph->addSessionSendFront(newSession); } + if (result == S_OK) + CoUninitialize(); + return S_OK; } -void EndpointNewSessionCallback::createSessionThread(SessionThreadParams params) { - params.eph->addSessionSendFront(params.session); - this->wait = false; -} - EndpointVolumeCallback::EndpointVolumeCallback(Endpoint* ep){ this->ep = ep; } @@ -100,75 +94,59 @@ HRESULT EndpointVolumeCallback::QueryInterface(REFIID riid, VOID **ppvInterface) HRESULT EndpointVolumeCallback::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]; - } - wait = true; - std::thread updateVolumeThread(&EndpointVolumeCallback::updateVolumeInfo, this, paramCopy, channelVolumes); - updateVolumeThread.detach(); - while(wait); - 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; + = pNotify->guidEventContext.Data1; osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \ - = newVolume.guidEventContext.Data2; + = pNotify->guidEventContext.Data2; osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data3 \ - = newVolume.guidEventContext.Data3; + = pNotify->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]; + osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data4[i] = pNotify->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()); - } + //memcpy(&osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller, &pNotify->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()); + } - eph->getCallbackInfo()->muted = newVolume.bMuted; - eph->getCallbackInfo()->mainVolume = newVolume.fMasterVolume; - eph->getCallbackInfo()->channels = newVolume.nChannels; + eph->getCallbackInfo()->muted = pNotify->bMuted; + eph->getCallbackInfo()->mainVolume = pNotify->fMasterVolume; + eph->getCallbackInfo()->channels = pNotify->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; + UINT j = 0; + //todo: do while here caused stack corruption; sus + while(j < pNotify->nChannels) { + if (flow & Flows::FLOW_PLAYBACK) + eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j]; + else + eph->getCallbackInfo()->channelVolumes[j] = pNotify->afChannelVolumes[j]; + j++; + } + return S_OK; } -void EndpointVolumeCallback::reportFinished() { - this->wait = false; +/* + * EndpointSituationCallback::EndpointSituationCallback(IMMDeviceEnumerator *deviceEnumerator, std::vector playbackDevices){ + * this->deviceEnumerator = deviceEnumerator; + * this->playbackDevices = playbackDevices; + * } + * + */ +//todo: not on construct since it expects them to already exist; smells like refactor! +void EndpointSituationCallback::fill(IMMDeviceEnumerator *deviceEnumerator, std::vector playbackDevices, std::vector captureDevices){ + this->deviceEnumerator = deviceEnumerator; + this->playbackDevices = playbackDevices; + this->captureDevices = captureDevices; } -EndpointSituationCallback::EndpointSituationCallback(Overseer* os){ - this->os = os; -} - - ULONG EndpointSituationCallback::AddRef(){ return InterlockedIncrement(&ref); } @@ -202,7 +180,6 @@ HRESULT EndpointSituationCallback::QueryInterface(REFIID riid, VOID **ppvInterfa 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) { @@ -218,7 +195,8 @@ HRESULT EndpointSituationCallback::OnDefaultDeviceChanged(EDataFlow flow, ERole } std::wstring wstringEndpointId = pwstrDeviceId; log_wdebugcpp(L"we got za defol 4 " + wstringEndpointId); - osh->roleBucketEntryCallback(nRole, wstringEndpointId); + osh->changeFrontDefaultsCallback(nRole, wstringEndpointId); + return S_OK; } @@ -234,162 +212,131 @@ HRESULT EndpointSituationCallback::OnDeviceRemoved(LPCWSTR pwstrDeviceId) { HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { std::wstring endpointId = std::wstring(pwstrDeviceId); - log_wdebugcpp(L"Endpoint state change for " + endpointId); - EndpointState newState; - switch (dwNewState) { + switch (dwNewState){ case DEVICE_STATE_ACTIVE: - newState = EndpointState::ENDPOINT_ACTIVE; + osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_ACTIVE); break; case DEVICE_STATE_DISABLED: - newState = EndpointState::ENDPOINT_DISABLED; + osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_DISABLED); break; case DEVICE_STATE_NOTPRESENT: - newState = EndpointState::ENDPOINT_NOTPRESENT; + osh->reviseEndpointShowing(endpointId, EndpointState::ENDPOINT_NOTPRESENT); break; case DEVICE_STATE_UNPLUGGED: - newState = EndpointState::ENDPOINT_UNPLUGGED; + osh->reviseEndpointShowing(endpointId, 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); +HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { + + /* + * log_debugcpp(" -->Changed device property " + + * key.fmtid.Data1 + key.fmtid.Data2 + key.fmtid.Data3 + "\n" + + * key.fmtid.Data4[0]+ key.fmtid.Data4[1]+ "\n"+ + * key.fmtid.Data4[2]+ key.fmtid.Data4[3] + "\n"+ + * key.fmtid.Data4[4]+ key.fmtid.Data4[5] + "\n"+ + * key.fmtid.Data4[6]+ key.fmtid.Data4[7]+ "\n"+ + * " pid " + key.pid); + */ + 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; - + //todo: preguntitas owindows dword no es uint32_t even tho mingw mingas + if(FAILED(endpoint->GetState(&this->endpointState))) {exit(-1);}; + 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 + reloadEndpointChannels(); + + /* todo: check header + * if(FAILED(endpoint->Activate(__uuidof(IAudioMeterInformation), + * CLSCTX_ALL, NULL, (void**)&endpointPeakMeter))) { log_debugcpp("peakbros..."); } + */ + + //todo:: atexit into exit Gather ID LPWSTR tempString = nullptr; - if (FAILED(endpoint->GetId(&tempString))) { exit(-1); }; + 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() { + 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) + properties->GetValue(PKEY_Device_FriendlyName , &pv); + if (pv.pwszVal == nullptr) + friendlyName = L"Unnamed Not Present Endpoint"; + else + friendlyName = std::wstring(pv.pwszVal); - 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; + this->setFlow(); + if (this->flow == Flows::FLOW_PLAYBACK) { + activateEndpointSessions(); } - - 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; - * } + * Endpoint::Endpoint(IMMDevice* endpoint) : Endpoint(endpoint, 0) {}; */ +void Endpoint::activateEndpointSessions() { + //sessionManager; + if (FAILED(endpoint->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**) &sessionManager))) { log_wdebugcpp(L"sesionbros..."); return; } + + IAudioSessionEnumerator* sessionEnumerator = nullptr; + if (FAILED(sessionManager->GetSessionEnumerator(&sessionEnumerator))) { log_wdebugcpp(L"sesEnumeratorBros..."); return; } + + int sessionCount; + sessionEnumerator->GetCount(&sessionCount); + for (int i = 0; i < sessionCount; i++) { + IAudioSessionControl* sessionControlTmp; + sessionEnumerator->GetSession(i, (IAudioSessionControl**)&sessionControlTmp); + //todo:: asegurar lo del dynamic_cast + IAudioSessionControl2* sessionControl; + sessionControlTmp->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl); + sessionControl->AddRef(); + sessionControlTmp->Release(); + Session* session = new Session(this, sessionControl, (size_t)i); + endpointSessions.push_back(session); + } + sessionEnumerator->Release(); +} + 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..."); - } + //bool extraThread = false; + /* + * Forgive me, for MS has sinned, and now I must too. + */ + if (this->endpointVolume == nullptr){ + HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&this->endpointVolume); + //if (endpointVolume == nullptr) { //why they returning 0 after dealing with the error jfc CO_E_NOTINITIALIZED) { + //CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); + //extraThread = true; + //goto initialized; + //} + //log_debugcpp(std::string("no endpointVolume (IAudioEndpointVolume)")); + if (result == S_OK) + CoUninitialize(); } - if (result == S_OK) - CoUninitialize(); } void Endpoint::reloadEndpointChannels() { @@ -414,13 +361,6 @@ 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) { @@ -435,6 +375,7 @@ uint32_t Endpoint::getChannelCount(){ return (uint32_t)channelCount; } + bool Endpoint::getMute(){ BOOL mut; if(FAILED(endpointVolume->GetMute(&mut))) { /* TIP: Below */ } @@ -442,7 +383,7 @@ bool Endpoint::getMute(){ return mute; } -void Endpoint::setState(EndpointState state){ +void Endpoint::setState(uint8_t state){ this->endpointState = state; if(state == EndpointState::ENDPOINT_ACTIVE) { this->activateEndpointVolume(); @@ -450,7 +391,7 @@ void Endpoint::setState(EndpointState state){ } } -EndpointState Endpoint::getState(){ +size_t Endpoint::getState(){ return this->endpointState; } @@ -458,13 +399,9 @@ void Endpoint::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(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) { - log_wdebugcpp(L"Master volume failed for endpoint: " + friendlyName); - }; + if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) {}; } else { - if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) { - log_wdebugcpp(L"Channel " + std::to_wstring(channel) + L" volume failed for endpoint: " + friendlyName); - }; + if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) {}; } } @@ -489,29 +426,70 @@ Roles Endpoint::getRoles(){ } void Endpoint::setRoles(Roles role){ - if (!policyConfig) return; + //otro exe momento + STARTUPINFOEXW startupConfig; + PROCESS_INFORMATION processInfo; + SecureZeroMemory(&startupConfig, sizeof(STARTUPINFOEXW)); + SecureZeroMemory(&startupConfig.StartupInfo, sizeof(STARTUPINFOW)); + startupConfig.StartupInfo.cb = sizeof(STARTUPINFOEXW); + SecureZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION)); - bool allRoles = false; - ERole val; - switch(role) { + std::wstring command = L"SoundVolumeView.exe /SetDefault " + endpointId + L" "; + std::wstring troublePair = L"0"; + switch (role) { + case Roles::ROLE_ALL: + /* + * console or multimedia, one sends both, at least for now; + * either cos of ms or dis guy; + * no choice but to treat them as one for now. + * command += L"all"; and nothing else would've been nice... + */ + troublePair = command + troublePair; + if(CreateProcessW( + NULL, + (wchar_t*)troublePair.c_str(), + NULL, + NULL, + false, + CREATE_UNICODE_ENVIRONMENT, + NULL, + NULL, + (LPSTARTUPINFOW)&startupConfig, + &processInfo + ) == true) { + WaitForSingleObject(processInfo.hProcess, INFINITE ); + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); + } + command += L"2"; + break; case Roles::ROLE_CONSOLE: - val = eConsole; + command += std::to_wstring(0); break; case Roles::ROLE_MULTIMEDIA: - val = eMultimedia; + command += std::to_wstring(1); break; case Roles::ROLE_COMMUNICATIONS: - val = eCommunications; - break; - default: - allRoles = true; + command += std::to_wstring(2); 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); + + if(CreateProcessW( + NULL, + (wchar_t*)command.c_str(), + NULL, + NULL, + false, + CREATE_UNICODE_ENVIRONMENT, + NULL, + NULL, + (LPSTARTUPINFOW)&startupConfig, + &processInfo + ) == true) { + WaitForSingleObject(processInfo.hProcess, INFINITE ); + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); + } } void Endpoint::assignRoles(Roles role){ @@ -526,12 +504,24 @@ void Endpoint::removeRoles(Roles role){ void Endpoint::setFlow() { IMMEndpoint* flowGetter; - if(FAILED(this->endpoint->QueryInterface(__uuidof(IMMEndpoint), (void**)&flowGetter))) + //this should be as simple as writing IID_IMMEndpoint, but it just won't find the macro, so I copied it. Sad. + 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; + if(FAILED(this->endpoint->QueryInterface((const _GUID)manual, (void**)&flowGetter))) { log_debugcpp("no flow..."); } EDataFlow MSflow; - flowGetter->GetDataFlow(&MSflow); + HRESULT vafllar = flowGetter->GetDataFlow(&MSflow); this->flow = (MSflow == EDataFlow::eRender ? Flows::FLOW_PLAYBACK : Flows::FLOW_CAPTURE); - log_debugcpp("Endpoint flow: " + std::to_string(flow)); flowGetter->Release(); } @@ -545,9 +535,7 @@ std::vector Endpoint::getSessions() { } size_t Endpoint::getSessionCount() { - size_t sessionCount; - sessionCount = endpointSessions.size(); - return sessionCount; + return endpointSessions.size(); } void Endpoint::registerNewSessionNotification(EndpointNewSessionCallback* ensc){ @@ -558,28 +546,18 @@ 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"); properties->Release(); endpointVolume->Release(); endpoint->Release(); sessionManager->Release(); - for (auto session : endpointSessions) { - delete session; - } } void Overseer::initCOMLibrary() { + OutputDebugStringW(L"EPWidget creation\n"); if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { - log_debugcpp("Not even COM?"); }; + log_debugcpp("si"); }; //Retrieving endpoint enumerator @@ -587,23 +565,21 @@ 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); + //if(FAILED(CoCreateInstance(__uuidof(CPolicyConfigClient), + // NULL, CLSCTX_ALL, __uuidof(IPolicyConfig10), (LPVOID *)&policyConfig))) {exit(-1);} //TODO: Release lpguid? //TODO: Uninitialize COM } -void Overseer::createEndpoints(Flows flow) { +void Overseer::reloadEndpoints(Flows flow) { IMMDeviceCollection *deviceCollection; unsigned int numEndpoints; EDataFlow MSflow = (flow == Flows::FLOW_PLAYBACK ? EDataFlow::eRender : EDataFlow::eCapture); @@ -615,16 +591,17 @@ void Overseer::createEndpoints(Flows flow) { /* * Counting them */ - if(FAILED(deviceCollection->GetCount(&numEndpoints))) { log_debugcpp("si");}; - if(numEndpoints == 0) { log_debugcpp("si"); }; + if(FAILED(deviceCollection->GetCount(&numEndpoints))) { log_debugcpp("si");}; + if(numEndpoints == 0) { log_debugcpp("si"); }; /* - * Retrieving actual endpoints and storing them on their own collection + * Retrieving actual endpoints and storing them on their own class */ IMMDevice *temp; for (unsigned int i = 0; i < numEndpoints; i++){ if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); }; - Endpoint *endpoint = new Endpoint(temp, policyConfig, i); + Endpoint *endpoint = new Endpoint(temp, i); + if (flow == Flows::FLOW_PLAYBACK) this->playbackDevices.push_back(endpoint); else @@ -652,8 +629,6 @@ void Overseer::createEndpoints(Flows flow) { break; } deviceEnumerator->GetDefaultAudioEndpoint(MSflow, val, &temp); - if (!temp) continue; - LPWSTR id = nullptr; if (flow == Flows::FLOW_PLAYBACK) { @@ -662,8 +637,9 @@ void Overseer::createEndpoints(Flows flow) { 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)); + log_wdebugcpp(L"ola defaul playback de " + + std::to_wstring(i) + L" es " + id); + playbackDevices.at(j)->assignRoles((Roles)(1 << i)); } } } else { @@ -677,23 +653,16 @@ void Overseer::createEndpoints(Flows flow) { 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!"); + log_debugcpp("ay caramba con la hot metida."); - Endpoint *endpoint = new Endpoint(newep, policyConfig); + Endpoint *endpoint = new Endpoint(newep); Flows getFlow = endpoint->getFlow(); if (getFlow == Flows::FLOW_PLAYBACK) { @@ -704,47 +673,27 @@ Endpoint* Overseer::addEndpoint(std::wstring endpointId, /* out */Flows* flow = 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() { //: epsc(deviceEnumerator, playbackDevices){ //Initializing COM library - log_debugcpp("-Initializing COM"); + log_debugcpp("Initializing Overseer"); initCOMLibrary(); - //Obtaining playback endpoint collection - createEndpoints(Flows::FLOW_PLAYBACK); + //Obtaining playback endpoint collection on this point in time + reloadEndpoints(Flows::FLOW_PLAYBACK); //reloadEndpoints(Flows::FLOW_CAPTURE); -} -NGuid Overseer::getGuid() { - return guid; -} - -void Overseer::registerEndpointSituationCallback() { + //Registering for endpoint information callback + this->epsc.fill(deviceEnumerator, playbackDevices, captureDevices); if(FAILED(deviceEnumerator->RegisterEndpointNotificationCallback(((IMMNotificationClient*)&epsc)))) { log_debugcpp("when no enchufas......"); } } +NGuid Overseer::getGuid() { + return guid; +} + std::vector Overseer::getPlaybackEndpoints() { return playbackDevices; } @@ -753,297 +702,14 @@ 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..f70e6d1 100644 --- a/src/back/backlasses.h +++ b/src/back/backlasses.h @@ -4,52 +4,16 @@ #include "backsessionclasses.h" #include "global.h" #include "contclasses.h" -//#include "environment.h" class EndpointVolumeCallback; class Session; -// Convert a wide UTF16LE string to an UTF8 string -static inline std::string utf16ToUtf8(const wchar_t* wstr) { - if(!wstr || wstr[0] == '\0') return std::string(); - int size_needed = WideCharToMultiByte(CP_UTF8, - 0, - wstr, - -1, - NULL, - 0, - NULL, - NULL); - std::string str(size_needed, 0); - WideCharToMultiByte(CP_UTF8, - 0, - wstr, - -1, - &str[0], - size_needed, - NULL, - NULL); - return str; -} - -// Convert an UTF8 string to a wide UTF16LE String -/* - * std::wstring utf8_decode(const std::string &str) - * { - * if( str.empty() ) return std::wstring(); - * int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); - * std::wstring wstrTo( size_needed, 0 ); - * MultiByteToWideChar (CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed); - * return wstrTo; - * } - */ - class Endpoint { public: - Endpoint(IMMDevice* endpoint, IPolicyConfig7* policyConfig, uint64_t idx = 0); + Endpoint(IMMDevice* endpoint, uint64_t idx); //todo: how to forward declare delegate constructors? - //Endpoint(IMMDevice* endpoint) : Endpoint(endpoint, 0) {}; + Endpoint(IMMDevice* endpoint) : Endpoint(endpoint, 0) {}; void reloadEndpointChannels(); uint64_t getIndex(); void setIndex(uint64_t idx); @@ -58,18 +22,16 @@ class Endpoint { float getVolume(int channel); void setMute(NGuid guid, bool muted); bool getMute(); - void setState(EndpointState state); - EndpointState getState(); + void setState(uint8_t state); + size_t 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); @@ -80,34 +42,28 @@ class Endpoint { void addSession(Session* session); void registerNewSessionNotification(EndpointNewSessionCallback* ensc); void unregisterNewSessionNotification(EndpointNewSessionCallback* ensc); - void deleteSessions(); - void activateEndpointSessions(); - //void deleteSessionManager(); - std::mutex endpointSessionsMutex; + ~Endpoint(); private: void inline activateEndpointVolume(); + void inline activateEndpointSessions(); std::vector endpointSessions; uint32_t channelCount = 0; - IMMDevice *endpoint; - IAudioEndpointVolume *endpointVolume = nullptr; - IPropertyStore *properties; - IAudioMeterInformation *endpointPeakMeter = nullptr; - //IAudioClient *audioClient; - int64_t defTime, minTime; - IAudioSessionManager2 *sessionManager = nullptr; + IMMDevice* endpoint; + IAudioSessionManager2 *sessionManager; Flows flow; + IAudioEndpointVolume *endpointVolume = nullptr; + IPropertyStore *properties; std::wstring friendlyName; - std::wstring descriptionName; - std::wstring deviceName; std::wstring endpointId; - EndpointState endpointState; + unsigned long endpointState; Roles endpointRoles = (Roles)0; uint64_t idx; - //Not implemented in llvm-mingw. Sad! todo: mingw patch - IPolicyConfig7* policyConfig; + /* Not implemented in llvm-mingw. Sad! + * IAudioMeterInformation *endpointPeakMeter = nullptr; + */ }; class EndpointVolumeCallback : public IAudioEndpointVolumeCallback { @@ -119,19 +75,16 @@ class EndpointVolumeCallback : public IAudioEndpointVolumeCallback { ULONG Release(); HRESULT QueryInterface(REFIID riid, VOID **ppvInterface); HRESULT OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA update); - void updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes); - void reportFinished(); //~EndpointVolumeCallback(); private: ULONG ref = 1; Endpoint* ep; - std::atomic wait = false; }; class EndpointSituationCallback : public IMMNotificationClient { public: - EndpointSituationCallback(Overseer* os); + //EndpointSituationCallback(IMMDeviceEnumerator *deviceEnumerator, std::vector playbackDevices); ULONG AddRef(); ULONG Release(); HRESULT QueryInterface(REFIID riid, VOID **ppvInterface); @@ -140,31 +93,25 @@ class EndpointSituationCallback : public IMMNotificationClient { HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId); HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState); HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key); - void reportFinishedStateChange(); + + void fill(IMMDeviceEnumerator *deviceEnumerator, std::vector playbackDevices, std::vector captureDevices); private: ULONG ref = 1; - Overseer* os; - std::atomic isEpStateChanging = false; + IMMDeviceEnumerator *deviceEnumerator; + std::vector playbackDevices; + std::vector captureDevices; }; 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); + void reloadEndpoints(Flows flow); Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow); - - void reportFinishedStateChange(); - - std::mutex playbackMutex; - std::mutex captureMutex; + NGuid getGuid(); //void setEndpointStatusCallback(); //void setEndpointStatusCallback(); @@ -176,65 +123,28 @@ class Overseer { ~Overseer(); private: - void initCOMLibrary(); - NGuid guid; IMMDeviceEnumerator *deviceEnumerator; EndpointSituationCallback epsc; - + //IPolicyConfig *policyConfig; 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 index c9aaa85..ced7fb1 100644 --- a/src/back/backsessionclasses.cpp +++ b/src/back/backsessionclasses.cpp @@ -37,11 +37,6 @@ HRESULT SessionStateCallback::QueryInterface(REFIID riid, VOID **ppvInterface) { } HRESULT SessionStateCallback::OnDisplayNameChanged(LPCWSTR NewDisplayName, LPCGUID EventContext) { - //TODO: Preguntar - while(sh->getVolumeInfo()->isNameChanged == true); - - sh->setName(std::wstring(NewDisplayName)); - sh->getVolumeInfo()->isNameChanged = true; return S_OK; } @@ -94,10 +89,8 @@ HRESULT SessionStateCallback::OnStateChanged(AudioSessionState NewState) { } HRESULT SessionStateCallback::OnSessionDisconnected(AudioSessionDisconnectReason DisconnectReason) { - if (DisconnectReason != DisconnectReasonDeviceRemoval) { - sh->setState(SessionState::DISCONNECTED); - sh->reviseSessionShowing(SessionState::DISCONNECTED); - } + sh->setState(SessionState::DISCONNECTED); + sh->reviseSessionShowing(SessionState::DISCONNECTED); return S_OK; } @@ -105,10 +98,7 @@ 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) { @@ -131,19 +121,10 @@ Session::Session(Endpoint* ep, IAudioSessionControl2* sessionControl, size_t idx 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 { + if (!wcscmp(sessionDisplayName, L"")) + this->sessionName = this->fetchProcessName(pid); + else this->sessionName = std::wstring(sessionDisplayName); - goto nameFound; - } - - nameFound: CoTaskMemFree(sessionDisplayName); } } @@ -159,13 +140,6 @@ float Session::getVolume(int channel){ 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; @@ -176,10 +150,6 @@ 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 */ } @@ -206,196 +176,87 @@ void Session::setMute(NGuid guid, bool muted) { 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; +std::wstring Session::fetchProcessName(DWORD pid) { + /* + * https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot + * https://stackoverflow.com/questions/11843368/how-to-get-process-description + */ + + /* Executable path retrieval */ + std::wstring exePath = L""; + + HANDLE processList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid); + if (processList == INVALID_HANDLE_VALUE) { + log_wdebugcpp(L"aye no procname."); + return exePath; } - *exePath = std::wstring(fileName); - return true; -} + MODULEENTRY32W me32w; + me32w.dwSize = sizeof(MODULEENTRY32W); + if(Module32FirstW(processList, &me32w)) { + do { + if (me32w.th32ProcessID == pid) { + exePath = std::wstring(me32w.szExePath); + break; + /* + * However, if the calling process is a 32-bit process, you must call the + * QueryFullProcessImageName function to retrieve the full path of the + * executable file for a 64-bit process. + */ + } + } while(Module32NextW(processList, &me32w)); + } + CloseHandle(processList); -bool Session::fetchNameViaFD(std::wstring exePath, DWORD pid, std::wstring *sessionName) { - /* File description retrieval: size and available lang-codepages */ + /* File description retrieval */ 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; + DWORD fileVersionInfoSize = GetFileVersionInfoSizeW(exePath.c_str(), &filler); + if (!fileVersionInfoSize) return exePath; void* fileVersionInfo = malloc(fileVersionInfoSize); - if(!GetFileVersionInfoExW(FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL, - exePath.c_str(),0,fileVersionInfoSize, fileVersionInfo)) { - return false; - } + if(!GetFileVersionInfoW(exePath.c_str(),0,fileVersionInfoSize, fileVersionInfo)) + return exePath; 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; } + if (!VerQueryValueW(fileVersionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&translationArray, &translationArrayLen)) + return exePath; - int8_t syslangIdx = -1; - wchar_t metadataStringKey[256]; - wchar_t* metadataString = NULL; - for (UINT i = 0; i < availableLangs; i++) { + bool match = false; + for (UINT i = 0; i < (translationArrayLen / sizeof(LANGANDCODEPAGE)); i++) { + wchar_t fileDescriptionKey[256]; LANGID defaultUILanguage = GetUserDefaultUILanguage(); if (defaultUILanguage != translationArray[i].wLanguage) continue; - syslangIdx = i; - break; + match = true; + wchar_t* fileDescription = NULL; + UINT fileDescriptionSize = 0; + swprintf(fileDescriptionKey, L"\\StringFileInfo\\%04x%04x\\FileDescription", + translationArray[i].wLanguage, translationArray[i].wCodePage); + if (VerQueryValueW(fileVersionInfo, fileDescriptionKey, (LPVOID*)&fileDescription, &fileDescriptionSize)) { + exePath = std::wstring(fileDescription); + } } - 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 (!match && 1 <= (translationArrayLen / sizeof(LANGANDCODEPAGE))) { + wchar_t fileDescriptionKey[256]; - 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; +wchar_t* fileDescription = NULL; + UINT fileDescriptionSize = 0; + swprintf(fileDescriptionKey, L"\\StringFileInfo\\%04x%04x\\FileDescription", + translationArray[0].wLanguage, translationArray[0].wCodePage); + if (VerQueryValueW(fileVersionInfo, fileDescriptionKey, (LPVOID*)&fileDescription, &fileDescriptionSize)) { + exePath = std::wstring(fileDescription); + } + } + free(fileVersionInfo); + return exePath; } //todo: conflicting names. change callback name @@ -416,10 +277,6 @@ void Session::removeStateCallback(SessionStateCallback *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 index ae87f0a..e6c8490 100644 --- a/src/back/backsessionclasses.h +++ b/src/back/backsessionclasses.h @@ -33,32 +33,25 @@ class Session { 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 fetchProcessName(DWORD pid); std::wstring sessionName; SessionState sessionState; Endpoint* ep; IAudioSessionControl2* sessionControl = nullptr; - IAudioMeterInformation* meterInformation = nullptr; ISimpleAudioVolume* sessionVolume = nullptr; - size_t idx; + size_t idx; }; diff --git a/src/back/ipolicyconfig.h b/src/back/ipolicyconfig.h index 7b474bb..2e10aab 100644 --- a/src/back/ipolicyconfig.h +++ b/src/back/ipolicyconfig.h @@ -1,42 +1,47 @@ -#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 +// ---------------------------------------------------------------------------- +// PolicyConfig.h +// Undocumented COM-interface IPolicyConfig. +// Use for set default audio render endpoint +// @author EreTIk +// ---------------------------------------------------------------------------- -/***************************************************************************** - * 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 { - +#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 ** @@ -102,69 +107,32 @@ public: 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) */ - +/* interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") */ +/* IPolicyConfigVista; */ +/* class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") */ +/* CPolicyConfigVistaClient; */ /* // ---------------------------------------------------------------------------- */ -/* // 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} */ +/* // class CPolicyConfigVistaClient */ +/* // {294935CE-F637-4E7C-A41B-AB255460B862} */ /* // */ -/* // interface IPolicyConfig */ -/* // {f8679f50-850a-41cf-9c72-430f290290c8} */ +/* // interface IPolicyConfigVista */ +/* // {568b9108-44bf-40b4-9006-86afe5b5a620} */ /* // */ /* // Query interface: */ -/* // CComPtr PolicyConfig; */ -/* // PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigClient)); */ +/* // CComPtr PolicyConfig; */ +/* // PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigVistaClient)); */ /* // */ -/* // @compatible: Windows 7 and Later */ +/* // @compatible: Windows Vista and Later */ /* // ---------------------------------------------------------------------------- */ -/* interface IPolicyConfig : public IUnknown */ +/* interface IPolicyConfigVista : public IUnknown */ /* { */ /* public: */ /* virtual HRESULT GetMixFormat( */ /* PCWSTR, */ /* WAVEFORMATEX ** */ -/* ); */ +/* ); // not available on Windows 7, use method from IPolicyConfig */ /* virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( */ /* PCWSTR, */ @@ -172,10 +140,6 @@ __CRT_UUID_DECL(IPolicyConfig7, 0xf8679f50, 0x850a, 0x41cf, 0x9c,0x72, 0x43,0x0f /* WAVEFORMATEX ** */ /* ); */ -/* virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( */ -/* PCWSTR */ -/* ); */ - /* virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( */ /* PCWSTR, */ /* WAVEFORMATEX *, */ @@ -187,22 +151,22 @@ __CRT_UUID_DECL(IPolicyConfig7, 0xf8679f50, 0x850a, 0x41cf, 0x9c,0x72, 0x43,0x0f /* 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, */ @@ -217,95 +181,12 @@ __CRT_UUID_DECL(IPolicyConfig7, 0xf8679f50, 0x850a, 0x41cf, 0x9c,0x72, 0x43,0x0f /* ); */ /* virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( */ -/* PCWSTR wszDeviceId, */ -/* ERole eRole */ +/* __in PCWSTR wszDeviceId, */ +/* __in ERole eRole */ /* ); */ /* virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( */ /* PCWSTR, */ /* INT */ -/* ); */ +/* ); // not available on Windows 7, use method from IPolicyConfig */ /* }; */ - -/* /\* 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 index 52fccbd..fc7beac 100644 --- a/src/back/msinclude.h +++ b/src/back/msinclude.h @@ -1,23 +1,17 @@ #pragma once +#define _WIN32_WINNT 0x0A00 #include //done by qt by def #define UNICODE #include -#include -#include -#include -#include -#include #include #include #include #include #include -#include #include -#include //#include #include @@ -27,38 +21,6 @@ //#include #include #include +#include "ipolicyconfig.h" #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..38c30b1 100644 --- a/src/cont/contclasses.cpp +++ b/src/cont/contclasses.cpp @@ -1,37 +1,27 @@ #include "backlasses.h" #include "contclasses.h" - -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: pragma once EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) { + //std::vector endpoints = osh->getPlaybackEndpoints().at(idx); this->idx = idx; this->flow = flow; this->ep = (flow == Flows::FLOW_PLAYBACK ? osh->getPlaybackEndpoints().at(idx) : osh->getCaptureEndpoints().at(idx)); + epc = new EndpointVolumeCallback(ep); + ensc = new EndpointNewSessionCallback(this); this->callbackInfo.caller = osh->getGuid(); + ep->registerNewSessionNotification(ensc); //epName = ep->getName(); this->setBackEndpointVolumeCallbackInfoContent(this->getState()); osh->pushBackEndpointHandler(this, flow); + + 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 OverseerHandler::pushBackEndpointHandler(EndpointHandler* eph, Flows flow) { @@ -60,6 +50,16 @@ Flows EndpointHandler::getFlow(){ return ep->getFlow(); } +/* these two, currently unused. If I use them, I should feel bad. + * Endpoint* EndpointHandler::getEndpoint() { + * return this->ep; + * } + * + * EndpointVolumeCallback* EndpointHandler::getEndpointVolumeCallback() { + * return this->epc; + * } + */ + BackEndpointVolumeCallbackInfo* EndpointHandler::getCallbackInfo(){ return &this->callbackInfo; } @@ -114,10 +114,7 @@ void EndpointHandler::setBackEndpointVolumeCallbackInfoContent(uint8_t state) { callbackInfo.muted = this->getMute(); callbackInfo.mainVolume = this->getVolume(AudioChannel::CHANNEL_MAIN); callbackInfo.channels = this->getChannelCount(); - if (!epc) { - epc = new EndpointVolumeCallback(ep); - ep->setVolumeCallback(epc); - } + 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); @@ -125,21 +122,17 @@ void EndpointHandler::setBackEndpointVolumeCallbackInfoContent(uint8_t state) { } } -void EndpointHandler::setState(EndpointState state){ +void EndpointHandler::setState(uint8_t state){ ep->setState(state); this->setBackEndpointVolumeCallbackInfoContent(state); } -void EndpointHandler::setState(EndpointState state, uint64_t index){ +void EndpointHandler::setState(uint8_t 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(); } @@ -182,15 +175,10 @@ Endpoint* EndpointHandler::getEndpoint() { } void EndpointHandler::addSessionSendFront(Session* session) { - if(!ep->endpointSessionsMutex.try_lock()) return; - sessionHandlersMutex.lock(); - - this->ep->addSession(session); + ep->addSession(session); + SessionHandler* sessionHandler = new SessionHandler(this, session, (getSessionCount() - 1)); - sessionHandlers.push_back(sessionHandler); - ep->endpointSessionsMutex.unlock(); - sessionHandlersMutex.unlock(); this->addSessionWidget(sessionHandler); } @@ -202,49 +190,6 @@ 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); @@ -256,46 +201,6 @@ 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(); } @@ -320,7 +225,7 @@ uint64_t OverseerHandler::getCaptureEndpointsCount(){ return this->os->getCaptureEndpoints().size(); } -void OverseerHandler::createEndpointHandlers(){ +void OverseerHandler::reloadEndpointHandlers(){ //todo: add capture //std::vector* ephs = new std::vector; @@ -328,7 +233,9 @@ void OverseerHandler::createEndpointHandlers(){ for(uint64_t i = 0; i < this->getPlaybackEndpointsCount(); i++){ log_debugcpp("Creating Playback handler " + std::to_string(i)); - new EndpointHandler(i, Flows::FLOW_PLAYBACK); + + EndpointHandler* ephexx = new EndpointHandler(i, Flows::FLOW_PLAYBACK); + //this->playbackEndpointHandlers.push_back(ephexx); log_debugcpp("Created Playback handler " + std::to_string(i) + ", adding to vector. " + " VSize: " + std::to_string(this->playbackEndpointHandlers.size())); } @@ -336,71 +243,55 @@ void OverseerHandler::createEndpointHandlers(){ log_debugcpp("Capture VSize: " + std::to_string(this->getCaptureEndpointsCount())); - for(uint64_t i = 0; i < this->getCaptureEndpointsCount(); i++) { + for(uint64_t i = 0; i < this->getCaptureEndpointsCount(); i++){ log_debugcpp("Creating Capture handler " + std::to_string(i)); - new EndpointHandler(i, Flows::FLOW_CAPTURE); + + /* + * if(i < (this->captureEndpointHandlers.size()) && + * this->captureEndpointHandlers.at(i) != nullptr) + * delete captureEndpointHandlers.at(i); + */ + + EndpointHandler* ephoo = new EndpointHandler(i, Flows::FLOW_CAPTURE); + //this->captureEndpointHandlers.push_back(ephoo); 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 +EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId, /* out */ Flows *flow = nullptr){ 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); + // std::vector getPlaybackEndpointHandlers(); + //std::vector getCaptureEndpointHandlers(); 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::setChangeFrontDefaultsFunction(std::function changeFrontDefaults){ + this->changeFrontDefaults = changeFrontDefaults; } -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::changeFrontDefaultsCallback(Roles role, std::wstring endpointId) { + this->changeFrontDefaults(role, endpointId); } 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; @@ -414,29 +305,22 @@ void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointSta //debug Flows flow; if (!eph) { - if (state ^ EndpointState::ENDPOINT_ACTIVE) goto end; + if (state ^ EndpointState::ENDPOINT_ACTIVE) return; + //return; //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 (flow == Flows::FLOW_CAPTURE) return; - if (eph && EndpointState::ENDPOINT_ACTIVE & state) { - eph->setState(EndpointState::ENDPOINT_ACTIVE); + + if(eph && EndpointState::ENDPOINT_ACTIVE & state) { this->addEndpointWidget(eph); - } else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE) { - eph->removeVolumeCallback(); + } else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE){ this->removeEndpointWidget(eph->getFrontVisibilityIndex()); } - - end: - handlersPlaybackMutex.unlock(); - handlersCaptureMutex.unlock(); - os->playbackMutex.unlock(); - os->captureMutex.unlock(); - os->reportFinishedStateChange(); return; } @@ -451,14 +335,3 @@ void OverseerHandler::setRemoveEndpointWidgetFunction(std::function ephs){ this->playbackEndpointHandlers = ephs; } - -void OverseerHandler::lockEndpoints() { - os->playbackMutex.lock(); - os->captureMutex.lock(); -} - -void OverseerHandler::unlockEndpoints() { - os->playbackMutex.unlock(); - os->captureMutex.unlock(); -} - diff --git a/src/cont/contclasses.h b/src/cont/contclasses.h index cd0e03e..25fcaea 100644 --- a/src/cont/contclasses.h +++ b/src/cont/contclasses.h @@ -1,7 +1,6 @@ #pragma once #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)) @@ -17,21 +16,21 @@ struct BackEndpointVolumeCallbackInfo { NGuid caller; bool muted; float mainVolume; - size_t channels; + size_t channels; std::vector channelVolumes; - bool updateName = false; }; -void setConfigDirToDefaults(); - class EndpointHandler { public: EndpointHandler(uint64_t idx, Flows flow); void setBackEndpointVolumeCallbackInfoContent(uint8_t state); - //todo: replace all getEndpointHandler() - //todo: name refactor + //these two, currently unused. If I use them, I should feel bad. + //EndpointVolumeCallback* getEndpointVolumeCallback(); + //Endpoint* getEndpoint(); + + //std::wstring epName; BackEndpointVolumeCallbackInfo* getCallbackInfo(); uint32_t getChannelCount(); @@ -40,7 +39,6 @@ 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); @@ -58,10 +56,9 @@ public: 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); + void setState(uint8_t state); + void setState(uint8_t state, uint64_t idx); - float getPeakVolume(); /* sessions */ size_t getSessionCount(); std::vector getSessionHandlers(); @@ -74,13 +71,6 @@ public: 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: @@ -107,25 +97,9 @@ 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 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); @@ -139,29 +113,25 @@ public: void pushBackEndpointHandler(EndpointHandler* eph, Flows flow); uint64_t getPlaybackEndpointsCount(); uint64_t getCaptureEndpointsCount(); - void createEndpointHandlers(); - EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow); - void reportFinishedStateChange(); + void reloadEndpointHandlers(); + EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow); NGuid getGuid(); - std::mutex handlersPlaybackMutex; - std::mutex handlersCaptureMutex; - void lockEndpoints(); - void unlockEndpoints(); + /* + * void setSessionVolumeCallback(std::function changeSessionVolume); + * void setSessionVolume(float newValue, ); + */ 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; diff --git a/src/cont/contsessionclasses.cpp b/src/cont/contsessionclasses.cpp index 0f6caaf..155c0e1 100644 --- a/src/cont/contsessionclasses.cpp +++ b/src/cont/contsessionclasses.cpp @@ -5,7 +5,7 @@ SessionHandler::SessionHandler(EndpointHandler* eph, Session* session, size_t id 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(); @@ -32,14 +32,6 @@ 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(); } @@ -85,7 +77,3 @@ void SessionHandler::reviseSessionShowing(SessionState state) { } } -SessionHandler::~SessionHandler() { - session->removeStateCallback(ssc); - ssc->Release(); -} diff --git a/src/cont/contsessionclasses.h b/src/cont/contsessionclasses.h index 24c0ba7..51f620f 100644 --- a/src/cont/contsessionclasses.h +++ b/src/cont/contsessionclasses.h @@ -9,10 +9,10 @@ class SessionStateCallback; struct SessionVolumeInfo { //SessionVolumeInfo(bool muted, float mainVolume); - bool muted; - float mainVolume; - NGuid caller; - std::atomic isNameChanged = false; + bool muted; + float mainVolume; + NGuid caller; + //size_t channels; //std::vector channelVolumes; }; @@ -29,11 +29,9 @@ class SessionHandler { 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; diff --git a/src/debug.h b/src/debug.h index 61855c1..da6285c 100644 --- a/src/debug.h +++ b/src/debug.h @@ -2,38 +2,11 @@ #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; \ @@ -42,7 +15,6 @@ std::bitset varToBitset(T info) { #define log_wdebugcpp(str) do { \ std::wcout << "[DEBUG]" << "(" << __FILE__ << ":" << __LINE__ << "): " << str << std::endl; \ } while (0) - #else #include @@ -57,30 +29,19 @@ std::bitset varToBitset(T info) { #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 -#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..292ec06 100644 --- a/src/global.h +++ b/src/global.h @@ -1,26 +1,15 @@ #pragma once -#define __STDC_WANT_LIB_EXT1__ 1 -#include -#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 STRING_MUTE "Mute" #define STRING_UNMUTE "Unmute" #define STRING_QUIT "Quit" @@ -33,29 +22,8 @@ #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), @@ -107,11 +75,8 @@ struct NGuid { /* }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..a9da261 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -1,194 +1,12 @@ #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); - * } - */ - - -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(); + 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); @@ -207,227 +25,36 @@ void ExtendedCheckBox::customEvent(QEvent* ev) { 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 +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); + layout = new QGridLayout(this); + //this->setLayout( + + muteButton = new QCheckBox(this); mainLabel = new QLabel(QString::fromStdWString(sh->getName()), this); - mainLabel->setToolTip(QString::fromStdWString(sh->getName())); - mainSlider = new MeterSlider(Qt::Horizontal, this); + mainSlider = new QSlider(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->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((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); + //mainMuteLayout = new QGridLayout(); + layout->addWidget(mainLabel, 0, 0, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(muteButton, 0, 1, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(mainSlider, 0, 2, 1, 2); //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); @@ -436,24 +63,17 @@ SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent) /* * Session Volume Polling */ - volumePoller = new QTimer(this); + volumePoller = new QTimer(); 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? @@ -462,34 +82,7 @@ SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent) 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(); + volumePoller->start(10); } void SessionWidget::updateMute(int checked){ @@ -504,85 +97,26 @@ void SessionWidget::updateMainVolume(int newValue){ SessionWidget::~SessionWidget() { volumePoller->stop(); - // volumePoller; + delete volumePoller; } -ChannelWidget::ChannelWidget(uint32_t channelCount, 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); - - 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) { +EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *parent) : 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()))); + this->eph->setState(EndpointState::ENDPOINT_ACTIVE, idx); + + layout = new QGridLayout(this); + //this->setLayout(layout); + log_debugcpp("epw main layout parent: " + std::to_string((intptr_t)(layout->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_ALL, new ExtendedCheckBox(this)}, + {Roles::ROLE_CONSOLE, new ExtendedCheckBox(this)}, + {Roles::ROLE_MULTIMEDIA, new ExtendedCheckBox(this)}, {Roles::ROLE_COMMUNICATIONS, new ExtendedCheckBox(this)} }; @@ -591,44 +125,33 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t i */ muteButton = new QCheckBox(this); mainLabel = new QLabel(QString::fromStdWString(eph->getName()), this); - mainSlider = new MeterSlider(Qt::Horizontal, this); - mainVolumeLabel = new QLabel(this); + mainSlider = new QSlider(Qt::Horizontal, 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); + layout->addWidget(mainLabel, row, 0); + layout->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->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; mainSlider->setValue((int)volume); - mainVolumeLabel->setText(QString::number(volume)); log_debugcpp("ENDPOINT SET WITH VOLUME " + std::to_string(volume)); + //tip: would need to be new widget with layout in it //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); + layout->addWidget(mainLabel, row, 0, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(muteButton, row, 1, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(mainSlider, row, 2, 1, 2); 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? @@ -636,71 +159,96 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t i connect(muteButton, &QCheckBox::stateChanged, this, (&EndpointWidget::updateMute)); - /* - * Channel sliders setup - */ - +/* + * 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); - } + for(uint32_t i = 0; i < epChannelCount && epChannelCount > 1; i++){ + QSlider* tmp = new QSlider(Qt::Horizontal); + QLabel* tmpLb = new QLabel(""); + tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + 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, row + 1, i); + layout->addWidget(tmpLb, row + 2, i); + + //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, i](int newValue){ + this->eph->setVolume(osh->getGuid(), i, newValue); + this->channelLabels.at(i)->setText(QString::number(newValue)); + }); } + row += 3; /* * 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) + defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setCheckState(assignedRoles == Roles::ROLE_ALL ? Qt::Checked : Qt::Unchecked); + //todo duditas de & + defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setDisabled(assignedRoles == Roles::ROLE_ALL ? true : false); + defaultRolesCheckBoxes.at(Roles::ROLE_ALL)->setText(STRING_ROLE_ALL); + + defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE)->setCheckState(assignedRoles & Roles::ROLE_CONSOLE ? Qt::Checked : Qt::Unchecked); + defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE)->setDisabled(assignedRoles & Roles::ROLE_CONSOLE ? true : false); + defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE)->setText(STRING_ROLE_CONSOLE); + + defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA)->setCheckState(assignedRoles & Roles::ROLE_MULTIMEDIA ? Qt::Checked : Qt::Unchecked); + defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA)->setDisabled(assignedRoles & Roles::ROLE_MULTIMEDIA ? true : false); + defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA)->setText(STRING_ROLE_MULTIMEDIA); + + defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS)->setCheckState(assignedRoles & Roles::ROLE_COMMUNICATIONS ? Qt::Checked : Qt::Unchecked); + defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS)->setDisabled(assignedRoles & Roles::ROLE_COMMUNICATIONS ? true : false); + defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS)->setText(STRING_ROLE_COMMUNICATIONS); + + connect(defaultRolesCheckBoxes.at(Roles::ROLE_ALL), &QCheckBox::stateChanged,[this] { + this->eph->setRoles(Roles::ROLE_ALL); + }); + connect(defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE), &QCheckBox::stateChanged,[this] { + this->eph->setRoles(Roles::ROLE_CONSOLE); + }); + connect(defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA), &QCheckBox::stateChanged,[this] { + this->eph->setRoles(Roles::ROLE_MULTIMEDIA); + }); - checkbox_setup(ROLE_ALL, ==); - checkbox_setup(ROLE_CONSOLE, &); - checkbox_setup(ROLE_MULTIMEDIA, &); - checkbox_setup(ROLE_COMMUNICATIONS, &); - #undef checkbox_setup + connect(defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS), &QCheckBox::stateChanged,[this] { + this->eph->setRoles(Roles::ROLE_COMMUNICATIONS); + }); + + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_ALL), row, 0); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE), row, 1); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA), row, 2); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS), row, 3); 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); + this->channelSliders.at(i)->blockSignals(true); + this->channelSliders.at(i)->setValue((int)((eph->getCallbackInfo()->channelVolumes[i] + roundingFactor) * 100)); + this->channelLabels.at(i)->setText(QString::number((int)((eph->getCallbackInfo()->channelVolumes[i] + roundingFactor) * 100))); + this->channelSliders.at(i)->blockSignals(false); } //memcpy(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)); @@ -710,17 +258,17 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t i mainSlider->blockSignals(false); muteButton->blockSignals(false); }); - timer->start(POLLING_RATE); + timer->start(10); - /* First Widget batch */ + /* First SessionWidget 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 */); + layout->addWidget(sessionWidget, row, 4); row++; sessionWidgets.push_back(sessionWidget); eph->getSessionHandlers().at(i)->setFrontIndex(i); } - + /* Add/Remove SessionWidget callback */ eph->setAddSessionWidgetFunction([this](SessionHandler* sessionHandler) { QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent((QEvent::Type)CustomQEvent::SessionWidgetCreated, sessionHandler)); @@ -730,43 +278,31 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t i QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent((QEvent::Type)CustomQEvent::SessionWidgetObsolete, sessionHandler)); }); + //todo parent? + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 1, 0); + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 4, 0); + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 6, 0); + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 6, 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); + this->layout->addWidget(sw, row, 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; + this->sessionWidgets.at(i)->setParent(nullptr); + this->layout->removeWidget(sessionWidgets.at(i)); + delete sessionWidgets.at(i); sessionWidgets.at(i) = nullptr; - //row--; ev->payload->setFrontIndex(INT_MAX); - this->setUpdatesEnabled(true); //this->sessionWidgetsUpdateTimer->start(); return; } @@ -782,55 +318,39 @@ void EndpointWidget::customEvent(QEvent* 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) { + if (ev->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) { +void MainWindow::removeEndpointWidget(CustomWidgetEvent* ev){ uint64_t i = ev->payload; this->ews.at(i)->setParent(nullptr); - this->widgetLayout->removeWidget(ews.at(i)); + this->layout->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(); + 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); +void MainWindow::addEndpointWidget(CustomWidgetEvent* ev){ + EndpointWidget* epw = new EndpointWidget(this->ews.size(), ev->payload, widget); + this->layout->addWidget(epw); ews.push_back(epw); return; } @@ -864,38 +384,6 @@ void MainWindow::reorderEndpointWidgetCollection() { 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(int checked){ bool muted = (checked == 2 ? true : false); this->eph->setMute(osh->getGuid(), muted); @@ -903,7 +391,6 @@ void EndpointWidget::updateMute(int checked){ } void EndpointWidget::updateMainVolume(int newValue){ - mainVolumeLabel->setText(QString::number(newValue)); this->eph->setVolume(osh->getGuid(), AudioChannel::CHANNEL_MAIN, newValue); } @@ -938,15 +425,6 @@ void EndpointWidget::updateMainVolume(int newValue){ * } */ -void EndpointWidget::updateChannelsVisibility() { - if (!cw) return; - - char* const channelSettings = set->getValue("show_channels"); - if(channelSettings && !(strcmp(channelSettings, "true"))){ - cw->setVisible(true); - } else cw->setVisible(false); -} - EndpointHandler* EndpointWidget::getEndpointHandler(){ return this->eph; } @@ -957,9 +435,9 @@ EndpointHandler* EndpointWidget::getEndpointHandler(){ * } */ -void EndpointWidget::setIndex(uint64_t idx) { +void EndpointWidget::setIndex(uint64_t idx){ this->idx = idx; - this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ACTIVE, this->idx); + this->eph->setFrontVisibilityInfo(EndpointState::ENDPOINT_ACTIVE, this->idx); } uint64_t EndpointWidget::getIndex(){ @@ -970,178 +448,40 @@ std::map EndpointWidget::getDefaultRolesWidgets() { return defaultRolesCheckBoxes; } -HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) { - widgetLayout = new QGridLayout(this); - - 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(); }); - 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); - } - - }); +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { + // setWindowState(Qt::WindowFullScreen); + // setCentralWidget(centralWidget); - 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"); - /* * 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(); + widget = new QWidget(); + layout = 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)); + widget->setLayout(layout); + setCentralWidget(widget); + //layout->addWidget(pintas, 0, 0); + setWindowTitle(STRING_TITLE); - //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();}) ); + trayIconMenu->addAction(trayIconMenuQuit); connect(trayIconMenuQuit, &QAction::triggered, qApp, &QCoreApplication::quit); trayIcon->setIcon(QIcon(":/assets/notificationAreaIcon.png")); setWindowIcon(QIcon(":/assets/notificationAreaIcon.png")); @@ -1151,30 +491,48 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { 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->setChangeFrontDefaultsFunction([this](Roles role, std::wstring endpointId) { + for (auto epw : this->ews) { + /* + * Is this the new default endpoint? + */ + if (epw->getEndpointHandler()->getId() == endpointId) { + //not necessary to keep endpointState flags up to date right now, but updating it will allow for later config files / profiles + epw->getDefaultRolesWidgets().at(role)->blockSignals(true); + epw->getEndpointHandler()->assignRoles(role); + epw->getDefaultRolesWidgets().at(role)->blockSignals(false); + QCoreApplication::instance()->postEvent(epw->getDefaultRolesWidgets().at(role), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); + //epw->defaultRolesCheckBoxes.at(role)->postEnableChange(); + /* + * And were you THE default? + */ + if (epw->getEndpointHandler()->getRoles() == Roles::ROLE_ALL) { + QCoreApplication::instance()->postEvent(epw->getDefaultRolesWidgets().at(Roles::ROLE_ALL), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); + } + /* + * Are you the dethroned king? + */ + } else if (epw->getEndpointHandler()->getRoles() & role) { + /* + * And were you THE default up until now? + */ + if (epw->getEndpointHandler()->getRoles() == Roles::ROLE_ALL) { + QCoreApplication::instance()->postEvent(epw->getDefaultRolesWidgets().at(Roles::ROLE_ALL), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); + } + + epw->getDefaultRolesWidgets().at(role)->blockSignals(true); + //Same as before. ini-san will come... + epw->getEndpointHandler()->removeRoles(role); + epw->getDefaultRolesWidgets().at(role)->blockSignals(false); + QCoreApplication::instance()->postEvent(epw->getDefaultRolesWidgets().at(role), new QEvent((QEvent::Type)CustomQEvent::EndpointDefaultChange)); + + } + } + }); osh->setRemoveEndpointWidgetFunction([this](uint64_t index) { QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent((QEvent::Type)CustomQEvent::EndpointWidgetObsolete, index)); @@ -1183,166 +541,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { 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) { @@ -1350,22 +548,17 @@ void MainWindow::closeEvent(QCloseEvent *event) { 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(); + //this->trayIcon->showMessage("ini file calling","tratarte como un gilipollas la primera 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(); - } + this->showNormal(); break; default: break; @@ -1374,28 +567,18 @@ void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason) { void MainWindow::reloadEndpointWidgets() { size_t i = 0; - ews.resize(2); - - osh->handlersPlaybackMutex.lock(); - for (size_t epwIndex = 2; i < (osh->getPlaybackEndpointHandlers().size()); i++) { + for (size_t epwIndex = 0; 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); } + EndpointWidget *epw = new EndpointWidget(epwIndex, osh->getPlaybackEndpointHandlers().at(i), widget); + epwIndex++; + //alfinal estoes solopara inicializarlmao + 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); + //todo:: tas aqui tirao, no me gustas y probablemente yo a ti tampoco + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), i, 0); } diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index 1b2658b..b9c4fa8 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -1,32 +1,67 @@ #pragma once -#include "qtcommon.h" +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#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" #include "contclasses.h" -#include "settings.h" - -class MeterSlider; - -enum SpawnPos { - LEFT = (1 << 1), - RIGHT = (0 << 1), - UP = (1 << 0), - DOWN = (0 << 0) -}; +//class EndpointHandler; +/* + * 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); + * }; + */ 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; + SessionWidgetObsolete = 1005 }; template @@ -35,86 +70,57 @@ 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; + QSlider *mainSlider = nullptr; uint64_t idx; - QHBoxLayout *widgetLayout = nullptr; - ExtendedCheckBox *muteButton = nullptr; + QGridLayout *layout = nullptr; + QCheckBox *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 EndpointWidget : public QWidget { 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(); + EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *parent = nullptr); + EndpointHandler* getEndpointHandler(); std::map getDefaultRolesWidgets(); - + void setIndex(uint64_t idx); uint64_t getIndex(); - //void setVolume(int channel, float volume); - void calculateSize(uint64_t width, uint64_t height); - + void setVolume(int channel, float volume); + ~EndpointWidget(); //void updateMainVolume(float newValue); //void updateVolume(uint32_t channel, float newValue); @@ -122,10 +128,7 @@ public: //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); @@ -139,14 +142,12 @@ private slots: private: int row; - const int sessionCol = 2; QCheckBox *muteButton = nullptr; - QLabel *mainLabel = nullptr; - QLabel *mainVolumeLabel = nullptr; - MeterSlider *mainSlider = nullptr; + QLabel *mainLabel = nullptr, *leftChannelLabel = nullptr, *rightChannelLabel = nullptr; + QSlider *mainSlider = nullptr; std::vector channelSliders; std::vector channelLabels; - QGridLayout *widgetLayout = nullptr; + QGridLayout *layout = nullptr; QGridLayout *mainMuteLayout = nullptr; std::map defaultRolesCheckBoxes; @@ -154,9 +155,7 @@ private: size_t defaultRolesVectorSize = 4; QTimer* timer = nullptr; uint64_t idx; - ChannelWidget* cw = nullptr; std::vector sessionWidgets; - QSize minimum; //std::vector *ephs; //std::vector *sliders; @@ -165,22 +164,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,16 +171,11 @@ 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); @@ -208,37 +186,15 @@ private slots: 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; 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 +202,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..19cf627 100644 --- a/src/qtestmain.cpp +++ b/src/qtestmain.cpp @@ -1,22 +1,27 @@ +//#include +//#include + +//#include + +//#define QTBLESSED +#include +#include + +#include +#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 = nullptr; + +QApplication* createApplication(int &argc, char *argv[]) +{ return new QApplication(argc, argv); } -bool isInstanceRunning(QString appName) { +bool isSingleInstanceRunning(QString appName) { QLocalSocket socket; socket.connectToServer(appName); bool isOpen = socket.isOpen(); @@ -24,122 +29,36 @@ bool isInstanceRunning(QString appName) { return isOpen; } -QLocalServer* startInstanceServer(QString appName) { +QLocalServer* startSingleInstanceServer(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); - } - + //QApplication::setStyle("windowsvista"); //Check if running //https://stackoverflow.com/questions/48060989/qt-show-application-if-currently-running - if (!isInstanceRunning(PIPE_NAME)) - startInstanceServer(PIPE_NAME); + if (!isSingleInstanceRunning("Mixer")) + startSingleInstanceServer("Mixer"); 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()); + osh = new OverseerHandler(); //qRegisterMetaType(); //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) + //window.setEndpointHandlers(ephs); 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()) }; - */ - + 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"; -}; - -}